Pod::Simple(3perl)
π Pod::Simple(3perl) π
okay bestie, welcome to the group chat where we learn to parse Pod. this is Pod::Simple, a framework for parsing Pod, and it's genuinely iconic. let's go π«Ά
β¨ NAME β¨
Pod::Simple β framework for parsing Pod π
π SYNOPSIS π
use an existing formatter, real quick:
# using an existing formatter
use Pod::Simple::XHTML;
my $parser = Pod::Simple::XHTML->new;
$parser->parse_file('path/to/file.pod');
or, if you're feeling main character energy, make your own:
# creating a new formatter
package Pod::Simple::SomeFormatter;
use parent qw(Pod::Simple);
sub _handle_element_start {
my ($parser, $element_name, $attr_hash_r) = @_;
...
}
...
π¦ DESCRIPTION π¦
So. Pod::Simple is a Perl library for parsing text in the Pod ("plain old documentation") markup language β the one people typically use for writing documentation for Perl and for Perl modules. The Pod format itself is explained over in perlpod, and the most common formatter is called perldoc.
π¨ PSA bestie: if your Pod contains non-ASCII characters, you GOTTA read the "ENCODING" section. no skipping. π
Pod formatters can use Pod::Simple to parse Pod documents and render them into plain text, HTML, or any number of other formats. Usually those formatters are subclasses of Pod::Simple, which means they inherit its methods β like parse_file. slay, inheritance ate π
But β and this is important, no cap β Pod::Simple doesn't understand and properly parse Perl itself. So if you have a file that contains a Perl program with a multi-line quoted string, and that string has lines that look like pod, Pod::Simple will treat them as pod. π This can be avoided if the file makes these into indented here documents instead.
If you're reading this doc just because you have a Pod-processing subclass that you want to use β honestly, this document (plus the docs for the subclass) is probably all you need to read. π
If you're reading this because you want to write a formatter subclass, keep reading, then go read Pod::Simple::Subclassing, and then possibly even read perlpodspec (some of which is for parser-writers, but a lot of it is notes to formatter-writers). iykyk πΈ
β MAIN METHODS β
$parser = SomeClass->new();β this returns a brand new parser object, whereSomeClassis a subclass of Pod::Simple. fresh out the box β¨$parser->output_fh( *OUT );β this sets the filehandle that$parser's output gets written to. You can pass*STDOUTor*STDERR, otherwise you should probably do something like this:
my $outfile = "output.txt";
open TXTOUT, ">$outfile" or die "Can't write to $outfile: $!";
$parser->output_fh(*TXTOUT);
...before you call one of the $parser->parse_whatever methods. order matters bestie π«Ά
$parser->output_string( \$somestring );β this sets the string that$parser's output will be sent to, instead of any filehandle. in-memory vibes only π$parser->parse_file( $some_filename );$parser->parse_file( *INPUT_FH );β this reads the Pod content of the file (or filehandle) that you specify, and processes it with that$parserobject, according to however$parser's class works, and according to whatever parser options you've set up for this$parserobject.$parser->parse_string_document( $all_content );β works just likeparse_file, except it reads the Pod content not from a file but from a string you've already got in memory. β¨$parser->parse_lines( ...@lines..., undef );β this processes the lines in@lines(where each list item must be a defined value, and must contain exactly one line of content β so no items like"foo\nbar"are allowed π ββοΈ). The finalundefis what tells it the document being parsed is done.
The other parser_whatever methods are meant to be called only once per $parser object; but parse_lines can be called as many times per $parser object as you want β as long as the last call (and only the last call) ends with an undef value.
$parser->content_seenβ returns true only if there's been any real content seen for this document. Returns false in cases where the document contains content, but doesn't make use of any Pod markup. πSomeClass->filter( $filename );SomeClass->filter( *INPUT_FH );SomeClass->filter( \$document_content );β this is a shortcut method that creates a new parser object, sets the output handle to STDOUT, and then processes the specified file (or filehandle, or in-memory document). handy for one-liners like this:
perl -MPod::Simple::Text -e "Pod::Simple::Text->filter('thingy.pod')"
π SECONDARY METHODS π
Some of these might be interesting to general users, as well as to formatter-writers. π«Ά
Note that the general pattern here is that the accessor-methods read the attribute's value with $value = $parser->attribute and set the attribute's value with $parser->attribute(newvalue). For each accessor, they typically only mention one syntax or another, based on which one you're actually most likely to use. β¨
$parser->parse_characters( SOMEVALUE )β the Pod parser normally expects to read octets and to convert those octets to characters based on the=encodingdeclaration in the Pod source. Set this option to a true value to say that the Pod source is already a Perl character stream. This tells the parser to ignore any=encodingcommand and to skip all the code paths involving decoding octets. π$parser->no_whining( SOMEVALUE )β set this attribute to a true value and you suppress the parser's complaints about irregularities in the Pod coding. By default this attribute's value is false, which means irregularities will be reported. π
note bestie: turning this attribute true won't suppress one or two kinds of complaints about rarely occurring unrecoverable errors. those ones still get through. π
$parser->no_errata_section( SOMEVALUE )β set this attribute to a true value and you stop the parser from generating a "POD ERRORS" section at the end of the document. By default this attribute's value is false, meaning an errata section will be generated, as necessary.$parser->complain_stderr( SOMEVALUE )β set this attribute to a true value and it'll send reports of parsing errors to STDERR. By default this attribute's value is false, meaning no output is sent to STDERR.
heads up: settingcomplain_stderralso setsno_errata_section. two-for-one π«Ά
$parser->source_filenameβ returns the filename that this parser object was set to read from.$parser->doc_has_startedβ returns true if$parserhas read from a source, and has seen Pod content in it. it's giving "we're so back" π₯$parser->source_deadβ returns true if$parserhas read from a source, and come to the end of that source. it's giving "it's over" π$parser->strip_verbatim_indent( SOMEVALUE )β okay so theperlpodspec for a Verbatim paragraph says "It should be reproduced exactly...", which means all that whitespace you used to indent your verbatim blocks gets preserved in the output. Which is lowkey annoying for outputs like HTML, where that whitespace just sits in front of every single line. It's an unfortunate case where syntax is turned into semantics. π
If the POD you're parsing adheres to a consistent indentation policy, you can have that indentation stripped from the beginning of every line of your verbatim blocks. This method tells Pod::Simple what to strip. For two-space indents, you'd use:
$parser->strip_verbatim_indent(' ');
For tab indents, you'd use a tab character:
$parser->strip_verbatim_indent("\t");
If the POD is inconsistent about the indentation of verbatim blocks, but you've figured out a heuristic to determine how much a particular verbatim block is indented, you can pass a code reference instead. The code reference will be executed with one argument, an array reference of all the lines in the verbatim block, and it should return the value to be stripped from each line. For example, if you decide you're fine with using the first line of the verbatim block to set the standard for the indentation of the rest of the block, you can look at the first line and return the appropriate value, like so:
$new->strip_verbatim_indent(sub {
my $lines = shift;
(my $indent = $lines->[0]) =~ s/\S.*//;
return $indent;
});
If you'd rather treat each line individually, you can do that too β just transform them in-place in the code reference and return undef. Say you don't want any lines indented. You can do something like this:
$new->strip_verbatim_indent(sub {
my $lines = shift;
sub { s/^\s+// for @{ $lines },
return undef;
});
$parser->expand_verbatim_tabs( n )β Default:8β
If, after any stripping of indentation in verbatim blocks, there are still tabs left, this method call says what to do with them. 0 means leave them as tabs; any other number means each tab is to be translated so as to have tab stops every n columns.
This is independent of other methods (except that it operates after any verbatim input stripping is done).
Like the other methods, the input parameter is not checked for validity. undef or something containing non-digits has the same effect as 8. π
π TERTIARY METHODS π
okay bestie these are the deep-cut little helpers, the side-quest methods. lowkey nobody uses them on day one but when you need them you need them β¨
$parser->abandon_output_fh()β bails on writing output to the file handle. not a single thing the$parseralready read gets touched, it's all still fine π«Ά$parser->abandon_output_string()β same energy but for the output string instead of the fh. again, all the POD$parseralready read? untouched, unbothered, thriving π$parser->accept_code( @codes )β it's just an alias foraccept_codes. same thing, shorter name, we love options π$parser->accept_codes( @codes )β lets$parseraccept a whole list of "Formatting Codes" from perlpod. use this when you wanna roll your own user-defined codes, icon behaviour fr fr$parser->accept_directive_as_data( @directives )β lets$parseraccept a list of directives for data paragraphs. a directive is the label of a "Command Paragraph" in perlpod, and a data paragraph is one delimited by=begin/=for/=enddirectives. this is the move for user-defined directives, slay π₯$parser->accept_directive_as_processed( @directives )β lets$parseraccept a list of directives for processed paragraphs. reminder: a directive = the label of a "Command Paragraph" in perlpod, and a processed paragraph is also known as an "Ordinary Paragraph" in perlpod. yep, also for user-defined directives β¨$parser->accept_directive_as_verbatim( @directives )β lets$parseraccept a list of directives for "Verbatim Paragraph" in perlpod. (cue the chorus: a directive is the label of a "Command Paragraph" in perlpod.) user-defined directives, once more, with feeling π$parser->accept_target( @targets )β alias foraccept_targets. no cap.$parser->accept_target_as_text( @targets )β alias foraccept_targets_as_text. also no cap.$parser->accept_targets( @targets )β takes in targets for=begin/=for/=endsections of the POD π$parser->accept_targets_as_text( @targets )β takes in targets for=begin/=for/=endsections that should be parsed as POD. if you want the actual details you gotta go read "About Data Paragraphs" in perlpodspec, iykyk π$parser->any_errata_seen()β vibe check for whether any errata got spotted. here's the example, memorise it:
die "too many errors\n" if $parser->any_errata_seen();
$parser->errata_seen()β hands you a hash reference of every erratum seen, whines and screams alike. the keys of that hash ref are the line number, and each value is an array reference of the errors for that line. example:
if ( $parser->any_errata_seen() ) {
$logger->log( $parser->errata_seen() );
}
$parser->detected_encoding()β returns the encoding that corresponds to=encoding, but only if that encoding was actually recognized and handled. if it wasn't, no dice π$parser->encoding()β returns the encoding of the document no matter what, even when the encoding isn't being handled correctly. messy but honest π$parser->parse_from_file( $source, $to )β parses from the$sourcefile to the$tofile. basically the same deal as "parse_from_file" in Pod::Parser π$parser->scream( @error_messages )β logs an error that cannot be ignored. loud on purpose, periodt π’$parser->unaccept_code( @codes )β alias forunaccept_codes. (yes another one.)$parser->unaccept_codes( @codes )β removes@codesas valid codes for the parse. bye babe π$parser->unaccept_directive( @directives )β alias forunaccept_directives.$parser->unaccept_directives( @directives )β removes@directivesas valid directives for the parse.$parser->unaccept_target( @targets )β alias forunaccept_targets.$parser->unaccept_targets( @targets )β removes@targetsas valid targets for the parse.$parser->version_report()β returns a string that describes the version π·οΈ$parser->whine( @error_messages )β logs an error, unless$parser->no_whining( TRUE );is in effect. then it just keeps it to itself πΆ
πΈ ENCODING πΈ
so here's the tea on how Pod::Simple reads your stuff: it expects to read octets. then it decodes those octets into Perl's internal character string representation, using whatever the =encoding declaration in the POD source says. that's the whole plan π€
but what if your POD source has no =encoding declaration at all? then $parser gets to guessing. it tries to figure out the encoding β picking one of UTF-8 or CP 1252 β by peeking at the first non-ASCII bytes and running the heuristic described in perlpodspec. (and if your POD source is only ASCII bytes, the encoding is just assumed to be ASCII. simple life β¨)
and if you set the parse_characters option to a true value? whole different mode, bestie:
- the parser expects characters instead of octets,
- it ignores any
=encodingentirely, - and it makes no attempt whatsoever to decode the input π«₯
π SEE ALSO π
- Pod::Simple::Subclassing
- perlpod
- perlpodspec
- Pod::Escapes
- perldoc
π«Ά SUPPORT π«Ά
got questions? wanna discuss POD and Pod::Simple? send them to the pod-people@perl.org mail list. to subscribe, send an empty email to pod-people-subscribe@perl.org π¬
this module lives in an open GitHub repository at <https://github.com/perl-pod/pod-simple/>. feel free to fork it and contribute, or clone <https://github.com/perl-pod/pod-simple.git> and send patches! we love that π
and please use <https://github.com/perl-pod/pod-simple/issues/new> to file a bug report π
β COPYRIGHT AND DISCLAIMERS β
Copyright (c) 2002 Sean M. Burke.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.
read that last bit again, bestie β no warranty, no promises, it's giving "use at your own risk, but lovingly" π
π AUTHOR π
Pod::Simple was created by Sean M. Burke <sburke@cpan.org>. but don't bother him, he's retired π (let the man rest, fr fr)
Pod::Simple is maintained by:
- Allison Randal
"allison@perl.org" - Hans Dieter Pearcey
"hdp@cpan.org" - David E. Wheeler
"dwheeler@cpan.org" - Karl Williamson
"khw@cpan.org"
Documentation has been contributed by:
- Gabor Szabo
"szabgab@gmail.com" - Shawn H Corey
"SHCOREY at cpan.org"
and that's a wrap on the whole page, bestie π this version of Pod::Simple(3perl) shipped as part of perl v5.44.0 and got stamped with the date 2026-10-17 β so if you're reading this later, yes, the time travellers got here first. go forth and parse some POD, you absolute icon ππ
π¦ where this page comes from
- arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms