Take me over?
NAME
Pod::PP - POD pre-processor
SYNOPSIS
# normally used via the podpp script
require Pod::PP;
my $pp = Pod::PP->make(
-incpath => ['h', 'h/sys'],
-symbols => { DIR => "/var/www", TMPDIR => "/var/tmp" },
);
$pp->parse_from_filehandle(\*STDIN);
$pp->parse_from_file("file.pp");
DESCRIPTION
The Pod::PP
module is a POD pre-processor built on top of Pod::Parser
. The helper script podpp provides a pre-processor command for POD, whose interface is very much like cpp, the C pre-processor. However, unlike C, the Pod::PP
processing is not normally invoked when parsing POD.
If you wish to automate the pre-processing for every POD file, you need to write .pp
files (say) instead of .pod
files, and add the following make rules to your Makefile
:
PODPP = podpp
PP_FLAGS =
.SUFFIXES: .pp .pod
.pp.pod:
$(PODPP) $(PP_FLAGS) $< >$*.pod
Those teach make how to derive a .pod
from a .pp
file using the podpp pre-processor.
Pod::PP
uses the P<>
notation to request symbol expansion. Since it processes text, you need to tag the symbols to be expanded explicitely. Expansion is done recursively, until there is no more expansion possible.
If you are familiar with cpp, most directives will be easy to grasp. For instance, using the ==
prefix to make shorter commands:
==pp include "common.pp"
==pp define DIR /var/www
==pp define TMP /tmp
==pp ifdef SOME_COMMON_SYMBOL
==pp define FOO common foo
==pp else
==pp define FOO P<DIR>
==pp endif
The ==
notation is not standard POD, but it is understood by Pod::Parser
and very convenient when it comes to writing things like the above block, because there's no need to separate commands by blank lines. Since the code is going to be processed by podpp anyway, there's no problem, and podpp will always emit legitimate POD. That is, given the following:
==head1 NAME
Some data
it will re-emit:
=head1 NAME
Some data
thereby normalizing the output. It is guaranteed that after a podpp pass, the output is regular POD. If you make errors in writing the Pod::PP
directives, you will not get the expected output, but it will be regular POD.
DIRECTIVES
The pre-processing directives can be given in two forms, depending on whether you wish to process your POD files containing Pod::PP
directives with the usual POD tools before or after having run podpp on them:
By using the
=for pp
form before all commands, you ensure that regular POD tools will simply ignore those. This might result in incorrect processing though, if you depend on the definition of some symbols to produce different outputs (i.e. you would need a podpp pass anyway).By using the
=pp
form before all commands, you require that podpp be run on your file to produce regular POD that can be then processed via regular POD tools.
Here are the supported directives, in alphabetical order:
=pp comment
comment-
A comment. Will be stripped out upon reading.
When
Pod::PP
encounters an error whilst processing a directive, e.g. an include with a file not found, it will leave a comment in the output, albeit using the=for pp
form so that it is properly ignored by standard POD tools. =pp define
symbol [value]-
Defines symbol to be value. If there's no value, the symbol is simply defined to an empty value. There may be an arbitrary amount of spaces or tabs between symbol and value.
A symbol can be tested for defined-ness via
=pp ifdef
, used in expressions via=pp if
, or expanded viaP<sym>
. =pp elif
expr-
Alternate condition. There may be as many
=pp elif
as needed, but they must precede any=pp else
directive, and follow a leading=pp if
test. See=pp if
below for the expr definiton.Naturally, within an
=pp if
test, the expression expr is evaluated only if theif
condition was false. =pp else
-
The else clause of the
=pp if
or=pp ifdef
test. =pp endif
-
Closes the testing sequence opened by last
=pp if
or=pp ifdef
. =pp if
expr-
Starts a conditional text sequence. If expr evaluates to true, the remaining up to the matching
=pp elif
or=pp else
or=pp endif
is included in the output, otherwise it is stripped.Within an expression, you may include any symbol, verbatim, and form any legal Perl expression. For instance:
==pp define X 4 ==pp define LIMIT 100 =pp if X*X < LIMIT Include this portion if X*X < LIMIT =pp else Include this portion if X*X >= LIMIT =pp endif
would yield, when processed by podpp:
Include this portion if X*X < LIMIT
since the condition is true with the current symbol values.
You may also use the
defined()
operator in tests, as in cpp:=pp if defined(X) || !defined(LIMIT)
A bad expression will result in an error message, but you must know that your expressions are converted into Perl, and then are evaluated within a
Safe
compartment: the errors will be reported relative to the translated Perl expressions, not to your original expressions. =pp ifdef
symbol-
Tests whether a symbol is defined. This is equivalent to:
=pp if defined(symbol)
only it is shorter to say.
=pp ifndef
symbol-
Tests whether a symbol is not defined. This is equivalent to:
=pp if !defined(symbol)
but it is shorter to say.
=pp image
[<center>] "path"-
This directive is not a regular pre-processing directive in that it is highly specialized. It's there because I historically implemented
Pod::PP
to pre-process that command in my PODs.It's a high-level macro, that is hardwired because
Pod::PP
is not rich enough yet to be able to support the definition of that kind of macro.It is expanded into two POD directives: one for HTML, one for text. An example will be better than a lengthy description:
=pp image <center> "logo.png"
will expand into:
=for html <P ALIGN="center"><IMG SRC="logo.png" ALT="logo"></P> =begin text [image "logo.png" not rendered] =end text
The <center> tag is optional, and you may use <right> instead to right-justify your image in HTML.
=pp include
"file"-
Includes
"file"
at the present location, throughPod::PP
. That is, the included file may itself usePod::PP
directives.The algorithm to find the file is as follows:
1. The file is first looked for from the location of the current file being processed.
2. If not found there, the search path is traversed. You may supply a search path with the -I flag in podpp or via the
-incpath
of the creation routine forPod::PP
.3. If still not found, an error is reported.
=pp require
"file"-
Same as an
=pp include
directive, but the"file"
is included only once. The absolute path of the file is used to determine whether it has already been included. For example, assuming we're in filedir/foo
, and thatdir/foo/file.pp
exists, the following:==pp require "file.pp" ==pp require "../dir/file.pp"
will result in only one inclusion of
"file.pp"
, since both require statements end up requesting the inclusion of the same path. =pp undef
symbol-
Undefines the target symbol.
DIAGNOSTICS
Pod::PP
uses Log::Agent
to emit its diagnostics. The podpp script leaves Log::Agent
in its default configuration, thereby redirecting all the errors to STDERR. If you use the Pod::PP
interface directly in a script, you can look at configuring alternatives for the logs in Log::Agent.
Whenever possible, Pod::PP
leaves a trail in the output marking the error. For instance, feeding the following to podpp:
=pp include "no-such-file"
would print the following error to STDERR:
podpp: error in Pod::PP directive 'include' at "example", line 17:
cannot find "no-such-file"
and leave the following trail:
=for pp comment (at "example", line 17):
Following "=pp" directive failed: cannot find "no-such-file"
=pp include "no-such-file"
which will be ignored by all POD tools.
INTERFACE
You will normally don't care, since you will be mostly interfacing with Pod::PP
via the podpp script. This section is therefore only useful for people wishing to use Pod::PP
from within a program.
Since Pod::PP
inherits from Pod::Parser
, it conforms to its interface, in particular for the parse_from_filehandle()
and parse_from_file()
routines. See Pod::Parser for more information.
The creation routine make()
takes the following mandatory arguments:
-incpath
=> array_ref-
The additional include search path (
"."
is always part of the search path, and always the first thing looked at). The array_ref provides a list of directories to look. For instance:-incpath => ["h", "/home/ram/usr/podpp"]
would add the two directories, in the order given.
-symbols
=> hash_ref-
Provides the intial set of defined symbols. Each key from the hash_ref is a symbol for the pre-processor:
-symbols => { DIR => "/var/tmp" TMP => "/tmp" }
Given the above, the following input:
dir is "P<DIR>" and tmp is "P<TMP>"
would become after processing:
dir is "/var/tmp" and tmp is "/tmp"
as expected.
BUGS
The =pp image
directive is a hack. It should not be implemented at this level, but it was convenient to do so.
AUTHOR
Raphael Manfredi <Raphael_Manfredi@pobox.com>
SEE ALSO
Pod::Parser(3).