NAME
Pod::Term - Yet another POD Parser for terminal (ie command line) output
SYNOPSIS
use Pod::Term;
my $pt = Pod::Term->new;
$pt->globals({
max_cols => 72,
base_color => 'yellow'
});
Pod::Term->set_props({
head1 => {
indent => 2,
after_indent => 4,
bottom_spacing => 2,
color => 'green'
},
'item-number' => {
indent => 2,
color => 'bright_cyan',
prepend => {
text => '@number -',
color => 'blue'
}
}
});
$pt->parse_file( '/path/to/pod/file' );
DESCRIPTION
Despite the plethora of Pod parsing modules on CPAN I couldn't seem to coax any into meeting my presentation requirements for pod printed at the terminal. I never anticipated getting diverted onto writing a full-blown POD parser, but that is what ended up happening. My advice to anyone considering writing a POD parser - don't go there. Quantum mechanics is much less troublesome.
This is yet another POD parser. It inherits from POD::Simple and so all Pod::Simple methods should be available (but Pod::Simple seems pretty complex under the hood and possibly in need of some maintenance. I am wondering if the advice to 'use Pod::Simple for all things Pod' is really the best? e.g. I was not able to get the output_string
method to work at all).
Like Pod::Text::Color, Pod::Term uses Term::ANSIColor to set ANSI color values to POD elements. However I was not able to get Pod::Text::Color to cleanly wrap colored text. It seems that Pod::Text::Color attempts to wrap the text after putting in the color characters, by trying to ignore those characters - I am not sure if it is the reason. I also couldn't seem to control the spacing, indents etc.
Pod::Term wraps text before inserting color values, and should produce a nice clean wrap. It also offers a decent level of control over formatting, by allowing you to assign simple directives (indent
, top_spacing
etc.) to individual page elements (head1
, over
etc.) POD has never looked so good!
METHODS
Basically Pod::Term formats according to whatever it finds in the prop_map
attribute. If you want to know what's in there by default, you can do something like:
use Data::Dumper;
use Pod::Term;
my $pt = Pod::Term->new;
print "prop_map contains: ".Dumper( $pt->prop_map )."\n";
You should find prop_map is a hashref which looks something like:
{
head1 => {
display => 'block',
stacking => 'revert',
indent => 0,
after_indent => 2,
color => 'on_blue',
bottom_spacing => 2
},
head2 => {
display => 'block',
stacking => 'revert',
indent => 0,
after_indent => 2,
color => 'blue',
bottom_spacing => 2
}
# ...
}
with one entry per POD element type, (using the element names that are generated by Pod::Simple
.) So to adjust formatting, you can either directly replace the hashref in prop_map
:
$pt->prop_map({
# new property map hashref
});
or use one of the property adjuster methods set_prop
and set_props
. As the names suggest, the former sets just one property in the map, while the second can set many:
$pt->set_prop( 'head1', 'indent', 2);
$pt->set_props({
head2 => {
bottom_spacing => 2,
color => 'bright_magenta'
},
Para => {
top_spacing => 5,
color => 'white'
}
});
Once you have specified your format options, you are ready to parse.
A quick method summary:
- prop_map
-
get/set the map of element properties (ie the hash of formatting options). This will use a set of default values if not explicitly set.
my $current_prop_map = $pt->prop_map; # get $pt->prop_map( $new_prop_map ); # set
- set_prop
-
Set the value of an individual property in the map
$pt->set_prop($element_name, $prop_name, $new_value ); $pt->set_prop('head2', 'bottom_spacing', 3);
- set_props
-
Set the values of several properties in the properties map at the same time. Pod::Text uses Hash::Merge to insert the new values.
$pt->set_props({ Document => { indent => 2, bottom_spacing => 2 }, head1 => { indent => 4, color => 'red' } });
- globals
-
globals is a hashref containing formatting which affects the whole document. Again it is a good idea to dump this to see the defaults and what is available for modification:
use Data::Dumper; use Pod::Term; my $pt = Pod::Term->new; print "globals: ".Dumper( $pt->globals )."\n";
At the time of writing, it contains just 2 variables:
{ max_cols => 76, base_color => white }
but should I update the module but forget to update this documentation, then Data::Dumper is your friend.
Hopefully the 2 above global attributes are reasonably straightforward:
- max_cols
-
max_cols
is basically the number of columns to wrap to (except for 'Verbatim' sections - which are printed... verbatim, which means they can stray outside the wrapping margin if the POD author was being inconsiderate) - base_color
-
base_color
is the color to start out with and revert back to if no color is specified. However, it's best to set colors explicitly where possible to avoid surprises.
PROPERTY MAP VALUES
I've called these "properties" rather than "attributes" because Pod::Simple uses "attributes" to mean something else. And "property map" is really a hashref which delegates properties to elements.
Some values I recommend you play with - and some I don't. Here are the ones that are fun to adjust:
properties which apply to "block" elements only
(see the display property for what is meant by a block
element.)
- indent
-
The number of spaces to add to the indent when the element is parsed. Note indents are cumulative (in general - see
stacking
). This indent happens before the element gets printed. - after_indent
-
The number of spaces to add to the indent immediately after the element is parsed. e.g. specifying
after_indent = 2
on ahead1
element means a paragraph occurring immediately after yourhead1
title will be indented 2 spaces relative to thehead1
. - top_spacing
-
How many lines to print immediately above the element
- bottom_spacing
-
How many lines to print immediately below the element. Note that in many cases specifying 0 for this is not a good idea. You should probably make sure that either
top_spacing
orbottom_spacing
are at least 1 for the elements which have text bodies, otherwise no linespace character will be printed between text blocks (and I'm afraid Pod::Term does not neatly run paragraphs together in this situation). - color
-
The color to set to the element. Pod::Term uses Term::ANSIColor for colors. See the man page for Term::ANSIColor for a list of available colors.
properties applying to both inline
and block
elements
- prepend
-
prepend is really intended for list items. For example, you may want your bullets to start with a blue dash (-) etc. To do this, set your attribute thus:
$pt->set_prop('item-bullet','prepend', { text => '*', color => '-' });
Note that the
prepend
attribute should be a hashref containingtext
at a minimum, and possiblycolor
. In theory you can useprepend
with any element - but in the case of 'over' elements in particular it will lead to unexpected effects. This is because parents of nested elements are rendered after the child - so you would get your prepended text occurring at the end of your list, which is probably not what you want.Both
prepend
andappend
should not contain newline characters. Blocks are defined to be lumps of text without return characters, so trying toprepend
orappend
then will cause confusion. To add newline characters to the beginning and end of blocks, usetop_spacing
andbottom_spacing
- append
-
Like
prepend
, but occurs at the end of the element. See the documentation forprepend
.
And now for the properties that you might want to leave alone. However it's important to understand what they do
- display
-
This is a CSS style property, which can take 2 values with names borrowed from CSS,
inline
andblock
. If you are familiar with both CSS and POD then it should be quite easy to work out which POD elements should be defined asinline
and which asblock
. Formatting codes such asB
- which indicates bold text - obviously counts as aninline
element, whilehead1
,Para
etc areblock
elements. The crucial difference being thatblock
elements expect to have line spacing between them, whereas inline follows the text. Things like top and bottom spacing only really make sense for block style elements, so setting abottom_spacing
value on aB
element will not have any effect - stacking
-
stacking controls how the left indent is calculated on
block
elements. Possible values arerevert
,nest
andspot
. POD suffers from an identity crisis, since for the most part it presents as a series of elements which don't nest, but then incorporates theover
element which works as an envelope and can be nested to arbitrary depth,html
style.There are the
head1
,head2
... elements - which are expected to occur as a single set, and not within other sections. For these, it's probably best if eachhead1
has the same indent, and eachhead2
has the same indent within the samehead1
. So these getstacking=revert
, meaning the indent level will fall back to what it was last time the same element was encountered.over
anditem
elements typically getstacking=nest
meaning a newly encounteredover
gets an increased indent (as long as theindent
property is set for the relevantover
element.)spot
is more complex, and should be used with caution. It is an uncomfortable combination ofrevert
andnest
, reverting only if the last stacked element is the same as itself. Otherwise it will nest. The idea withspot
is to keep list items that may contain nested paragraphs in line with each other, rather than the next item after the paragraph indenting further.Stacking may be confusing, and it may be best to make sure you can't get what you want by altering other settings before getting too experimental with it.
SEE ALSO
Pod::Simple, Pod::Text, Pod::Text::Color, Term::ANSIColor
AUTHOR
Tom Gracey tomgracey@gmail.com
COPYRIGHT AND LICENSE
Copyright (C) 2018 by Tom Gracey
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.20.1 or, at your option, any later version of Perl 5 you may have available.