1*0Sstevel@tonic-gate# Pod::Text -- Convert POD data to formatted ASCII text. 2*0Sstevel@tonic-gate# $Id: Text.pm,v 2.21 2002/08/04 03:34:58 eagle Exp $ 3*0Sstevel@tonic-gate# 4*0Sstevel@tonic-gate# Copyright 1999, 2000, 2001, 2002 by Russ Allbery <rra@stanford.edu> 5*0Sstevel@tonic-gate# 6*0Sstevel@tonic-gate# This program is free software; you may redistribute it and/or modify it 7*0Sstevel@tonic-gate# under the same terms as Perl itself. 8*0Sstevel@tonic-gate# 9*0Sstevel@tonic-gate# This module converts POD to formatted text. It replaces the old Pod::Text 10*0Sstevel@tonic-gate# module that came with versions of Perl prior to 5.6.0 and attempts to match 11*0Sstevel@tonic-gate# its output except for some specific circumstances where other decisions 12*0Sstevel@tonic-gate# seemed to produce better output. It uses Pod::Parser and is designed to be 13*0Sstevel@tonic-gate# very easy to subclass. 14*0Sstevel@tonic-gate# 15*0Sstevel@tonic-gate# Perl core hackers, please note that this module is also separately 16*0Sstevel@tonic-gate# maintained outside of the Perl core as part of the podlators. Please send 17*0Sstevel@tonic-gate# me any patches at the address above in addition to sending them to the 18*0Sstevel@tonic-gate# standard Perl mailing lists. 19*0Sstevel@tonic-gate 20*0Sstevel@tonic-gate############################################################################## 21*0Sstevel@tonic-gate# Modules and declarations 22*0Sstevel@tonic-gate############################################################################## 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gatepackage Pod::Text; 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gaterequire 5.004; 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gateuse Carp qw(carp croak); 29*0Sstevel@tonic-gateuse Exporter (); 30*0Sstevel@tonic-gateuse Pod::ParseLink qw(parselink); 31*0Sstevel@tonic-gateuse Pod::Select (); 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gateuse strict; 34*0Sstevel@tonic-gateuse vars qw(@ISA @EXPORT %ESCAPES $VERSION); 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate# We inherit from Pod::Select instead of Pod::Parser so that we can be used by 37*0Sstevel@tonic-gate# Pod::Usage. 38*0Sstevel@tonic-gate@ISA = qw(Pod::Select Exporter); 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate# We have to export pod2text for backward compatibility. 41*0Sstevel@tonic-gate@EXPORT = qw(pod2text); 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate# Don't use the CVS revision as the version, since this module is also in Perl 44*0Sstevel@tonic-gate# core and too many things could munge CVS magic revision strings. This 45*0Sstevel@tonic-gate# number should ideally be the same as the CVS revision in podlators, however. 46*0Sstevel@tonic-gate$VERSION = 2.21; 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate############################################################################## 50*0Sstevel@tonic-gate# Table of supported E<> escapes 51*0Sstevel@tonic-gate############################################################################## 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate# This table is taken near verbatim from Pod::PlainText in Pod::Parser, which 54*0Sstevel@tonic-gate# got it near verbatim from the original Pod::Text. It is therefore credited 55*0Sstevel@tonic-gate# to Tom Christiansen, and I'm glad I didn't have to write it. :) "iexcl" to 56*0Sstevel@tonic-gate# "divide" added by Tim Jenness. 57*0Sstevel@tonic-gate%ESCAPES = ( 58*0Sstevel@tonic-gate 'amp' => '&', # ampersand 59*0Sstevel@tonic-gate 'apos' => "'", # apostrophe 60*0Sstevel@tonic-gate 'lt' => '<', # left chevron, less-than 61*0Sstevel@tonic-gate 'gt' => '>', # right chevron, greater-than 62*0Sstevel@tonic-gate 'quot' => '"', # double quote 63*0Sstevel@tonic-gate 'sol' => '/', # solidus (forward slash) 64*0Sstevel@tonic-gate 'verbar' => '|', # vertical bar 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate "Aacute" => "\xC1", # capital A, acute accent 67*0Sstevel@tonic-gate "aacute" => "\xE1", # small a, acute accent 68*0Sstevel@tonic-gate "Acirc" => "\xC2", # capital A, circumflex accent 69*0Sstevel@tonic-gate "acirc" => "\xE2", # small a, circumflex accent 70*0Sstevel@tonic-gate "AElig" => "\xC6", # capital AE diphthong (ligature) 71*0Sstevel@tonic-gate "aelig" => "\xE6", # small ae diphthong (ligature) 72*0Sstevel@tonic-gate "Agrave" => "\xC0", # capital A, grave accent 73*0Sstevel@tonic-gate "agrave" => "\xE0", # small a, grave accent 74*0Sstevel@tonic-gate "Aring" => "\xC5", # capital A, ring 75*0Sstevel@tonic-gate "aring" => "\xE5", # small a, ring 76*0Sstevel@tonic-gate "Atilde" => "\xC3", # capital A, tilde 77*0Sstevel@tonic-gate "atilde" => "\xE3", # small a, tilde 78*0Sstevel@tonic-gate "Auml" => "\xC4", # capital A, dieresis or umlaut mark 79*0Sstevel@tonic-gate "auml" => "\xE4", # small a, dieresis or umlaut mark 80*0Sstevel@tonic-gate "Ccedil" => "\xC7", # capital C, cedilla 81*0Sstevel@tonic-gate "ccedil" => "\xE7", # small c, cedilla 82*0Sstevel@tonic-gate "Eacute" => "\xC9", # capital E, acute accent 83*0Sstevel@tonic-gate "eacute" => "\xE9", # small e, acute accent 84*0Sstevel@tonic-gate "Ecirc" => "\xCA", # capital E, circumflex accent 85*0Sstevel@tonic-gate "ecirc" => "\xEA", # small e, circumflex accent 86*0Sstevel@tonic-gate "Egrave" => "\xC8", # capital E, grave accent 87*0Sstevel@tonic-gate "egrave" => "\xE8", # small e, grave accent 88*0Sstevel@tonic-gate "ETH" => "\xD0", # capital Eth, Icelandic 89*0Sstevel@tonic-gate "eth" => "\xF0", # small eth, Icelandic 90*0Sstevel@tonic-gate "Euml" => "\xCB", # capital E, dieresis or umlaut mark 91*0Sstevel@tonic-gate "euml" => "\xEB", # small e, dieresis or umlaut mark 92*0Sstevel@tonic-gate "Iacute" => "\xCD", # capital I, acute accent 93*0Sstevel@tonic-gate "iacute" => "\xED", # small i, acute accent 94*0Sstevel@tonic-gate "Icirc" => "\xCE", # capital I, circumflex accent 95*0Sstevel@tonic-gate "icirc" => "\xEE", # small i, circumflex accent 96*0Sstevel@tonic-gate "Igrave" => "\xCC", # capital I, grave accent 97*0Sstevel@tonic-gate "igrave" => "\xEC", # small i, grave accent 98*0Sstevel@tonic-gate "Iuml" => "\xCF", # capital I, dieresis or umlaut mark 99*0Sstevel@tonic-gate "iuml" => "\xEF", # small i, dieresis or umlaut mark 100*0Sstevel@tonic-gate "Ntilde" => "\xD1", # capital N, tilde 101*0Sstevel@tonic-gate "ntilde" => "\xF1", # small n, tilde 102*0Sstevel@tonic-gate "Oacute" => "\xD3", # capital O, acute accent 103*0Sstevel@tonic-gate "oacute" => "\xF3", # small o, acute accent 104*0Sstevel@tonic-gate "Ocirc" => "\xD4", # capital O, circumflex accent 105*0Sstevel@tonic-gate "ocirc" => "\xF4", # small o, circumflex accent 106*0Sstevel@tonic-gate "Ograve" => "\xD2", # capital O, grave accent 107*0Sstevel@tonic-gate "ograve" => "\xF2", # small o, grave accent 108*0Sstevel@tonic-gate "Oslash" => "\xD8", # capital O, slash 109*0Sstevel@tonic-gate "oslash" => "\xF8", # small o, slash 110*0Sstevel@tonic-gate "Otilde" => "\xD5", # capital O, tilde 111*0Sstevel@tonic-gate "otilde" => "\xF5", # small o, tilde 112*0Sstevel@tonic-gate "Ouml" => "\xD6", # capital O, dieresis or umlaut mark 113*0Sstevel@tonic-gate "ouml" => "\xF6", # small o, dieresis or umlaut mark 114*0Sstevel@tonic-gate "szlig" => "\xDF", # small sharp s, German (sz ligature) 115*0Sstevel@tonic-gate "THORN" => "\xDE", # capital THORN, Icelandic 116*0Sstevel@tonic-gate "thorn" => "\xFE", # small thorn, Icelandic 117*0Sstevel@tonic-gate "Uacute" => "\xDA", # capital U, acute accent 118*0Sstevel@tonic-gate "uacute" => "\xFA", # small u, acute accent 119*0Sstevel@tonic-gate "Ucirc" => "\xDB", # capital U, circumflex accent 120*0Sstevel@tonic-gate "ucirc" => "\xFB", # small u, circumflex accent 121*0Sstevel@tonic-gate "Ugrave" => "\xD9", # capital U, grave accent 122*0Sstevel@tonic-gate "ugrave" => "\xF9", # small u, grave accent 123*0Sstevel@tonic-gate "Uuml" => "\xDC", # capital U, dieresis or umlaut mark 124*0Sstevel@tonic-gate "uuml" => "\xFC", # small u, dieresis or umlaut mark 125*0Sstevel@tonic-gate "Yacute" => "\xDD", # capital Y, acute accent 126*0Sstevel@tonic-gate "yacute" => "\xFD", # small y, acute accent 127*0Sstevel@tonic-gate "yuml" => "\xFF", # small y, dieresis or umlaut mark 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate "laquo" => "\xAB", # left pointing double angle quotation mark 130*0Sstevel@tonic-gate "lchevron" => "\xAB", # synonym (backwards compatibility) 131*0Sstevel@tonic-gate "raquo" => "\xBB", # right pointing double angle quotation mark 132*0Sstevel@tonic-gate "rchevron" => "\xBB", # synonym (backwards compatibility) 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate "iexcl" => "\xA1", # inverted exclamation mark 135*0Sstevel@tonic-gate "cent" => "\xA2", # cent sign 136*0Sstevel@tonic-gate "pound" => "\xA3", # (UK) pound sign 137*0Sstevel@tonic-gate "curren" => "\xA4", # currency sign 138*0Sstevel@tonic-gate "yen" => "\xA5", # yen sign 139*0Sstevel@tonic-gate "brvbar" => "\xA6", # broken vertical bar 140*0Sstevel@tonic-gate "sect" => "\xA7", # section sign 141*0Sstevel@tonic-gate "uml" => "\xA8", # diaresis 142*0Sstevel@tonic-gate "copy" => "\xA9", # Copyright symbol 143*0Sstevel@tonic-gate "ordf" => "\xAA", # feminine ordinal indicator 144*0Sstevel@tonic-gate "not" => "\xAC", # not sign 145*0Sstevel@tonic-gate "shy" => '', # soft (discretionary) hyphen 146*0Sstevel@tonic-gate "reg" => "\xAE", # registered trademark 147*0Sstevel@tonic-gate "macr" => "\xAF", # macron, overline 148*0Sstevel@tonic-gate "deg" => "\xB0", # degree sign 149*0Sstevel@tonic-gate "plusmn" => "\xB1", # plus-minus sign 150*0Sstevel@tonic-gate "sup2" => "\xB2", # superscript 2 151*0Sstevel@tonic-gate "sup3" => "\xB3", # superscript 3 152*0Sstevel@tonic-gate "acute" => "\xB4", # acute accent 153*0Sstevel@tonic-gate "micro" => "\xB5", # micro sign 154*0Sstevel@tonic-gate "para" => "\xB6", # pilcrow sign = paragraph sign 155*0Sstevel@tonic-gate "middot" => "\xB7", # middle dot = Georgian comma 156*0Sstevel@tonic-gate "cedil" => "\xB8", # cedilla 157*0Sstevel@tonic-gate "sup1" => "\xB9", # superscript 1 158*0Sstevel@tonic-gate "ordm" => "\xBA", # masculine ordinal indicator 159*0Sstevel@tonic-gate "frac14" => "\xBC", # vulgar fraction one quarter 160*0Sstevel@tonic-gate "frac12" => "\xBD", # vulgar fraction one half 161*0Sstevel@tonic-gate "frac34" => "\xBE", # vulgar fraction three quarters 162*0Sstevel@tonic-gate "iquest" => "\xBF", # inverted question mark 163*0Sstevel@tonic-gate "times" => "\xD7", # multiplication sign 164*0Sstevel@tonic-gate "divide" => "\xF7", # division sign 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate "nbsp" => "\x01", # non-breaking space 167*0Sstevel@tonic-gate); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate############################################################################## 171*0Sstevel@tonic-gate# Initialization 172*0Sstevel@tonic-gate############################################################################## 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate# Initialize the object. Must be sure to call our parent initializer. 175*0Sstevel@tonic-gatesub initialize { 176*0Sstevel@tonic-gate my $self = shift; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate $$self{alt} = 0 unless defined $$self{alt}; 179*0Sstevel@tonic-gate $$self{indent} = 4 unless defined $$self{indent}; 180*0Sstevel@tonic-gate $$self{margin} = 0 unless defined $$self{margin}; 181*0Sstevel@tonic-gate $$self{loose} = 0 unless defined $$self{loose}; 182*0Sstevel@tonic-gate $$self{sentence} = 0 unless defined $$self{sentence}; 183*0Sstevel@tonic-gate $$self{width} = 76 unless defined $$self{width}; 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate # Figure out what quotes we'll be using for C<> text. 186*0Sstevel@tonic-gate $$self{quotes} ||= '"'; 187*0Sstevel@tonic-gate if ($$self{quotes} eq 'none') { 188*0Sstevel@tonic-gate $$self{LQUOTE} = $$self{RQUOTE} = ''; 189*0Sstevel@tonic-gate } elsif (length ($$self{quotes}) == 1) { 190*0Sstevel@tonic-gate $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes}; 191*0Sstevel@tonic-gate } elsif ($$self{quotes} =~ /^(.)(.)$/ 192*0Sstevel@tonic-gate || $$self{quotes} =~ /^(..)(..)$/) { 193*0Sstevel@tonic-gate $$self{LQUOTE} = $1; 194*0Sstevel@tonic-gate $$self{RQUOTE} = $2; 195*0Sstevel@tonic-gate } else { 196*0Sstevel@tonic-gate croak qq(Invalid quote specification "$$self{quotes}"); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate # Stack of indentations. 200*0Sstevel@tonic-gate $$self{INDENTS} = []; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate # Current left margin. 203*0Sstevel@tonic-gate $$self{MARGIN} = $$self{indent} + $$self{margin}; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate $self->SUPER::initialize; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate # Tell Pod::Parser that we want the non-POD stuff too if code was set. 208*0Sstevel@tonic-gate $self->parseopts ('-want_nonPODs' => 1) if $$self{code}; 209*0Sstevel@tonic-gate} 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate############################################################################## 213*0Sstevel@tonic-gate# Core overrides 214*0Sstevel@tonic-gate############################################################################## 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate# Called for each command paragraph. Gets the command, the associated 217*0Sstevel@tonic-gate# paragraph, the line number, and a Pod::Paragraph object. Just dispatches 218*0Sstevel@tonic-gate# the command to a method named the same as the command. =cut is handled 219*0Sstevel@tonic-gate# internally by Pod::Parser. 220*0Sstevel@tonic-gatesub command { 221*0Sstevel@tonic-gate my $self = shift; 222*0Sstevel@tonic-gate my $command = shift; 223*0Sstevel@tonic-gate return if $command eq 'pod'; 224*0Sstevel@tonic-gate return if ($$self{EXCLUDE} && $command ne 'end'); 225*0Sstevel@tonic-gate if ($self->can ('cmd_' . $command)) { 226*0Sstevel@tonic-gate $command = 'cmd_' . $command; 227*0Sstevel@tonic-gate $self->$command (@_); 228*0Sstevel@tonic-gate } else { 229*0Sstevel@tonic-gate my ($text, $line, $paragraph) = @_; 230*0Sstevel@tonic-gate my $file; 231*0Sstevel@tonic-gate ($file, $line) = $paragraph->file_line; 232*0Sstevel@tonic-gate $text =~ s/\n+\z//; 233*0Sstevel@tonic-gate $text = " $text" if ($text =~ /^\S/); 234*0Sstevel@tonic-gate warn qq($file:$line: Unknown command paragraph: =$command$text\n); 235*0Sstevel@tonic-gate return; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate} 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate# Called for a verbatim paragraph. Gets the paragraph, the line number, and a 240*0Sstevel@tonic-gate# Pod::Paragraph object. Just output it verbatim, but with tabs converted to 241*0Sstevel@tonic-gate# spaces. 242*0Sstevel@tonic-gatesub verbatim { 243*0Sstevel@tonic-gate my $self = shift; 244*0Sstevel@tonic-gate return if $$self{EXCLUDE}; 245*0Sstevel@tonic-gate $self->item if defined $$self{ITEM}; 246*0Sstevel@tonic-gate local $_ = shift; 247*0Sstevel@tonic-gate return if /^\s*$/; 248*0Sstevel@tonic-gate s/^(\s*\S+)/(' ' x $$self{MARGIN}) . $1/gme; 249*0Sstevel@tonic-gate $self->output ($_); 250*0Sstevel@tonic-gate} 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate# Called for a regular text block. Gets the paragraph, the line number, and a 253*0Sstevel@tonic-gate# Pod::Paragraph object. Perform interpolation and output the results. 254*0Sstevel@tonic-gatesub textblock { 255*0Sstevel@tonic-gate my $self = shift; 256*0Sstevel@tonic-gate return if $$self{EXCLUDE}; 257*0Sstevel@tonic-gate $self->output ($_[0]), return if $$self{VERBATIM}; 258*0Sstevel@tonic-gate local $_ = shift; 259*0Sstevel@tonic-gate my $line = shift; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate # Interpolate and output the paragraph. 262*0Sstevel@tonic-gate $_ = $self->interpolate ($_, $line); 263*0Sstevel@tonic-gate s/\s+$/\n/; 264*0Sstevel@tonic-gate if (defined $$self{ITEM}) { 265*0Sstevel@tonic-gate $self->item ($_ . "\n"); 266*0Sstevel@tonic-gate } else { 267*0Sstevel@tonic-gate $self->output ($self->reformat ($_ . "\n")); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate} 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate# Called for a formatting code. Gets the command, argument, and a 272*0Sstevel@tonic-gate# Pod::InteriorSequence object and is expected to return the resulting text. 273*0Sstevel@tonic-gate# Calls methods for code, bold, italic, file, and link to handle those types 274*0Sstevel@tonic-gate# of codes, and handles S<>, E<>, X<>, and Z<> directly. 275*0Sstevel@tonic-gatesub interior_sequence { 276*0Sstevel@tonic-gate local $_; 277*0Sstevel@tonic-gate my ($self, $command, $seq); 278*0Sstevel@tonic-gate ($self, $command, $_, $seq) = @_; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate # We have to defer processing of the inside of an L<> formatting code. If 281*0Sstevel@tonic-gate # this code is nested inside an L<> code, return the literal raw text of 282*0Sstevel@tonic-gate # it. 283*0Sstevel@tonic-gate my $parent = $seq->nested; 284*0Sstevel@tonic-gate while (defined $parent) { 285*0Sstevel@tonic-gate return $seq->raw_text if ($parent->cmd_name eq 'L'); 286*0Sstevel@tonic-gate $parent = $parent->nested; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate # Index entries are ignored in plain text. 290*0Sstevel@tonic-gate return '' if ($command eq 'X' || $command eq 'Z'); 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate # Expand escapes into the actual character now, warning if invalid. 293*0Sstevel@tonic-gate if ($command eq 'E') { 294*0Sstevel@tonic-gate if (/^\d+$/) { 295*0Sstevel@tonic-gate return chr; 296*0Sstevel@tonic-gate } else { 297*0Sstevel@tonic-gate return $ESCAPES{$_} if defined $ESCAPES{$_}; 298*0Sstevel@tonic-gate my ($file, $line) = $seq->file_line; 299*0Sstevel@tonic-gate warn "$file:$line: Unknown escape: E<$_>\n"; 300*0Sstevel@tonic-gate return "E<$_>"; 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate # For all the other formatting codes, empty content produces no output. 305*0Sstevel@tonic-gate return if $_ eq ''; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate # For S<>, compress all internal whitespace and then map spaces to \01. 308*0Sstevel@tonic-gate # When we output the text, we'll map this back. 309*0Sstevel@tonic-gate if ($command eq 'S') { 310*0Sstevel@tonic-gate s/\s+/ /g; 311*0Sstevel@tonic-gate tr/ /\01/; 312*0Sstevel@tonic-gate return $_; 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate # Anything else needs to get dispatched to another method. 316*0Sstevel@tonic-gate if ($command eq 'B') { return $self->seq_b ($_) } 317*0Sstevel@tonic-gate elsif ($command eq 'C') { return $self->seq_c ($_) } 318*0Sstevel@tonic-gate elsif ($command eq 'F') { return $self->seq_f ($_) } 319*0Sstevel@tonic-gate elsif ($command eq 'I') { return $self->seq_i ($_) } 320*0Sstevel@tonic-gate elsif ($command eq 'L') { return $self->seq_l ($_, $seq) } 321*0Sstevel@tonic-gate else { 322*0Sstevel@tonic-gate my ($file, $line) = $seq->file_line; 323*0Sstevel@tonic-gate warn "$file:$line: Unknown formatting code: $command<$_>\n"; 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate} 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate# Called for each paragraph that's actually part of the POD. We take 328*0Sstevel@tonic-gate# advantage of this opportunity to untabify the input. Also, if given the 329*0Sstevel@tonic-gate# code option, we may see paragraphs that aren't part of the POD and need to 330*0Sstevel@tonic-gate# output them directly. 331*0Sstevel@tonic-gatesub preprocess_paragraph { 332*0Sstevel@tonic-gate my $self = shift; 333*0Sstevel@tonic-gate local $_ = shift; 334*0Sstevel@tonic-gate 1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me; 335*0Sstevel@tonic-gate $self->output_code ($_) if $self->cutting; 336*0Sstevel@tonic-gate $_; 337*0Sstevel@tonic-gate} 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate############################################################################## 341*0Sstevel@tonic-gate# Command paragraphs 342*0Sstevel@tonic-gate############################################################################## 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate# All command paragraphs take the paragraph and the line number. 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate# First level heading. 347*0Sstevel@tonic-gatesub cmd_head1 { 348*0Sstevel@tonic-gate my ($self, $text, $line) = @_; 349*0Sstevel@tonic-gate $self->heading ($text, $line, 0, '===='); 350*0Sstevel@tonic-gate} 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate# Second level heading. 353*0Sstevel@tonic-gatesub cmd_head2 { 354*0Sstevel@tonic-gate my ($self, $text, $line) = @_; 355*0Sstevel@tonic-gate $self->heading ($text, $line, $$self{indent} / 2, '== '); 356*0Sstevel@tonic-gate} 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate# Third level heading. 359*0Sstevel@tonic-gatesub cmd_head3 { 360*0Sstevel@tonic-gate my ($self, $text, $line) = @_; 361*0Sstevel@tonic-gate $self->heading ($text, $line, $$self{indent} * 2 / 3 + 0.5, '= '); 362*0Sstevel@tonic-gate} 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate# Third level heading. 365*0Sstevel@tonic-gatesub cmd_head4 { 366*0Sstevel@tonic-gate my ($self, $text, $line) = @_; 367*0Sstevel@tonic-gate $self->heading ($text, $line, $$self{indent} * 3 / 4 + 0.5, '- '); 368*0Sstevel@tonic-gate} 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate# Start a list. 371*0Sstevel@tonic-gatesub cmd_over { 372*0Sstevel@tonic-gate my $self = shift; 373*0Sstevel@tonic-gate local $_ = shift; 374*0Sstevel@tonic-gate $self->item ("\n\n") if defined $$self{ITEM}; 375*0Sstevel@tonic-gate unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} } 376*0Sstevel@tonic-gate push (@{ $$self{INDENTS} }, $$self{MARGIN}); 377*0Sstevel@tonic-gate $$self{MARGIN} += ($_ + 0); 378*0Sstevel@tonic-gate} 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate# End a list. 381*0Sstevel@tonic-gatesub cmd_back { 382*0Sstevel@tonic-gate my ($self, $text, $line, $paragraph) = @_; 383*0Sstevel@tonic-gate $self->item ("\n\n") if defined $$self{ITEM}; 384*0Sstevel@tonic-gate $$self{MARGIN} = pop @{ $$self{INDENTS} }; 385*0Sstevel@tonic-gate unless (defined $$self{MARGIN}) { 386*0Sstevel@tonic-gate my $file; 387*0Sstevel@tonic-gate ($file, $line) = $paragraph->file_line; 388*0Sstevel@tonic-gate warn "$file:$line: Unmatched =back\n"; 389*0Sstevel@tonic-gate $$self{MARGIN} = $$self{indent}; 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate} 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate# An individual list item. 394*0Sstevel@tonic-gatesub cmd_item { 395*0Sstevel@tonic-gate my $self = shift; 396*0Sstevel@tonic-gate if (defined $$self{ITEM}) { $self->item } 397*0Sstevel@tonic-gate local $_ = shift; 398*0Sstevel@tonic-gate s/\s+$//; 399*0Sstevel@tonic-gate $$self{ITEM} = $_ ? $self->interpolate ($_) : '*'; 400*0Sstevel@tonic-gate} 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate# Begin a block for a particular translator. Setting VERBATIM triggers 403*0Sstevel@tonic-gate# special handling in textblock(). 404*0Sstevel@tonic-gatesub cmd_begin { 405*0Sstevel@tonic-gate my $self = shift; 406*0Sstevel@tonic-gate local $_ = shift; 407*0Sstevel@tonic-gate my ($kind) = /^(\S+)/ or return; 408*0Sstevel@tonic-gate if ($kind eq 'text') { 409*0Sstevel@tonic-gate $$self{VERBATIM} = 1; 410*0Sstevel@tonic-gate } else { 411*0Sstevel@tonic-gate $$self{EXCLUDE} = 1; 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate} 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate# End a block for a particular translator. We assume that all =begin/=end 416*0Sstevel@tonic-gate# pairs are properly closed. 417*0Sstevel@tonic-gatesub cmd_end { 418*0Sstevel@tonic-gate my $self = shift; 419*0Sstevel@tonic-gate $$self{EXCLUDE} = 0; 420*0Sstevel@tonic-gate $$self{VERBATIM} = 0; 421*0Sstevel@tonic-gate} 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate# One paragraph for a particular translator. Ignore it unless it's intended 424*0Sstevel@tonic-gate# for text, in which case we treat it as a verbatim text block. 425*0Sstevel@tonic-gatesub cmd_for { 426*0Sstevel@tonic-gate my $self = shift; 427*0Sstevel@tonic-gate local $_ = shift; 428*0Sstevel@tonic-gate my $line = shift; 429*0Sstevel@tonic-gate return unless s/^text\b[ \t]*\n?//; 430*0Sstevel@tonic-gate $self->verbatim ($_, $line); 431*0Sstevel@tonic-gate} 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate############################################################################## 435*0Sstevel@tonic-gate# Formatting codes 436*0Sstevel@tonic-gate############################################################################## 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate# The simple ones. These are here mostly so that subclasses can override them 439*0Sstevel@tonic-gate# and do more complicated things. 440*0Sstevel@tonic-gatesub seq_b { return $_[0]{alt} ? "``$_[1]''" : $_[1] } 441*0Sstevel@tonic-gatesub seq_f { return $_[0]{alt} ? "\"$_[1]\"" : $_[1] } 442*0Sstevel@tonic-gatesub seq_i { return '*' . $_[1] . '*' } 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate# Apply a whole bunch of messy heuristics to not quote things that don't 445*0Sstevel@tonic-gate# benefit from being quoted. These originally come from Barrie Slaymaker and 446*0Sstevel@tonic-gate# largely duplicate code in Pod::Man. 447*0Sstevel@tonic-gatesub seq_c { 448*0Sstevel@tonic-gate my $self = shift; 449*0Sstevel@tonic-gate local $_ = shift; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate # A regex that matches the portion of a variable reference that's the 452*0Sstevel@tonic-gate # array or hash index, separated out just because we want to use it in 453*0Sstevel@tonic-gate # several places in the following regex. 454*0Sstevel@tonic-gate my $index = '(?: \[.*\] | \{.*\} )?'; 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate # Check for things that we don't want to quote, and if we find any of 457*0Sstevel@tonic-gate # them, return the string with just a font change and no quoting. 458*0Sstevel@tonic-gate m{ 459*0Sstevel@tonic-gate ^\s* 460*0Sstevel@tonic-gate (?: 461*0Sstevel@tonic-gate ( [\'\`\"] ) .* \1 # already quoted 462*0Sstevel@tonic-gate | \` .* \' # `quoted' 463*0Sstevel@tonic-gate | \$+ [\#^]? \S $index # special ($^Foo, $") 464*0Sstevel@tonic-gate | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func 465*0Sstevel@tonic-gate | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call 466*0Sstevel@tonic-gate | [+-]? ( \d[\d.]* | \.\d+ ) (?: [eE][+-]?\d+ )? # a number 467*0Sstevel@tonic-gate | 0x [a-fA-F\d]+ # a hex constant 468*0Sstevel@tonic-gate ) 469*0Sstevel@tonic-gate \s*\z 470*0Sstevel@tonic-gate }xo && return $_; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate # If we didn't return, go ahead and quote the text. 473*0Sstevel@tonic-gate return $$self{alt} ? "``$_''" : "$$self{LQUOTE}$_$$self{RQUOTE}"; 474*0Sstevel@tonic-gate} 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate# Handle links. Since this is plain text, we can't actually make any real 477*0Sstevel@tonic-gate# links, so this is all to figure out what text we print out. Most of the 478*0Sstevel@tonic-gate# work is done by Pod::ParseLink. 479*0Sstevel@tonic-gatesub seq_l { 480*0Sstevel@tonic-gate my ($self, $link, $seq) = @_; 481*0Sstevel@tonic-gate my ($text, $type) = (parselink ($link))[1,4]; 482*0Sstevel@tonic-gate my ($file, $line) = $seq->file_line; 483*0Sstevel@tonic-gate $text = $self->interpolate ($text, $line); 484*0Sstevel@tonic-gate $text = '<' . $text . '>' if $type eq 'url'; 485*0Sstevel@tonic-gate return $text || ''; 486*0Sstevel@tonic-gate} 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate############################################################################## 490*0Sstevel@tonic-gate# Header handling 491*0Sstevel@tonic-gate############################################################################## 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate# The common code for handling all headers. Takes the interpolated header 494*0Sstevel@tonic-gate# text, the line number, the indentation, and the surrounding marker for the 495*0Sstevel@tonic-gate# alt formatting method. 496*0Sstevel@tonic-gatesub heading { 497*0Sstevel@tonic-gate my ($self, $text, $line, $indent, $marker) = @_; 498*0Sstevel@tonic-gate $self->item ("\n\n") if defined $$self{ITEM}; 499*0Sstevel@tonic-gate $text =~ s/\s+$//; 500*0Sstevel@tonic-gate $text = $self->interpolate ($text, $line); 501*0Sstevel@tonic-gate if ($$self{alt}) { 502*0Sstevel@tonic-gate my $closemark = reverse (split (//, $marker)); 503*0Sstevel@tonic-gate my $margin = ' ' x $$self{margin}; 504*0Sstevel@tonic-gate $self->output ("\n" . "$margin$marker $text $closemark" . "\n\n"); 505*0Sstevel@tonic-gate } else { 506*0Sstevel@tonic-gate $text .= "\n" if $$self{loose}; 507*0Sstevel@tonic-gate my $margin = ' ' x ($$self{margin} + $indent); 508*0Sstevel@tonic-gate $self->output ($margin . $text . "\n"); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate} 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate############################################################################## 514*0Sstevel@tonic-gate# List handling 515*0Sstevel@tonic-gate############################################################################## 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate# This method is called whenever an =item command is complete (in other words, 518*0Sstevel@tonic-gate# we've seen its associated paragraph or know for certain that it doesn't have 519*0Sstevel@tonic-gate# one). It gets the paragraph associated with the item as an argument. If 520*0Sstevel@tonic-gate# that argument is empty, just output the item tag; if it contains a newline, 521*0Sstevel@tonic-gate# output the item tag followed by the newline. Otherwise, see if there's 522*0Sstevel@tonic-gate# enough room for us to output the item tag in the margin of the text or if we 523*0Sstevel@tonic-gate# have to put it on a separate line. 524*0Sstevel@tonic-gatesub item { 525*0Sstevel@tonic-gate my $self = shift; 526*0Sstevel@tonic-gate local $_ = shift; 527*0Sstevel@tonic-gate my $tag = $$self{ITEM}; 528*0Sstevel@tonic-gate unless (defined $tag) { 529*0Sstevel@tonic-gate carp "Item called without tag"; 530*0Sstevel@tonic-gate return; 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate undef $$self{ITEM}; 533*0Sstevel@tonic-gate my $indent = $$self{INDENTS}[-1]; 534*0Sstevel@tonic-gate unless (defined $indent) { $indent = $$self{indent} } 535*0Sstevel@tonic-gate my $margin = ' ' x $$self{margin}; 536*0Sstevel@tonic-gate if (!$_ || /^\s+$/ || ($$self{MARGIN} - $indent < length ($tag) + 1)) { 537*0Sstevel@tonic-gate my $realindent = $$self{MARGIN}; 538*0Sstevel@tonic-gate $$self{MARGIN} = $indent; 539*0Sstevel@tonic-gate my $output = $self->reformat ($tag); 540*0Sstevel@tonic-gate $output =~ s/^$margin /$margin:/ if ($$self{alt} && $indent > 0); 541*0Sstevel@tonic-gate $output =~ s/\n*$/\n/; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate # If the text is just whitespace, we have an empty item paragraph; 544*0Sstevel@tonic-gate # this can result from =over/=item/=back without any intermixed 545*0Sstevel@tonic-gate # paragraphs. Insert some whitespace to keep the =item from merging 546*0Sstevel@tonic-gate # into the next paragraph. 547*0Sstevel@tonic-gate $output .= "\n" if $_ && $_ =~ /^\s*$/; 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate $self->output ($output); 550*0Sstevel@tonic-gate $$self{MARGIN} = $realindent; 551*0Sstevel@tonic-gate $self->output ($self->reformat ($_)) if $_ && /\S/; 552*0Sstevel@tonic-gate } else { 553*0Sstevel@tonic-gate my $space = ' ' x $indent; 554*0Sstevel@tonic-gate $space =~ s/^$margin /$margin:/ if $$self{alt}; 555*0Sstevel@tonic-gate $_ = $self->reformat ($_); 556*0Sstevel@tonic-gate s/^$margin /$margin:/ if ($$self{alt} && $indent > 0); 557*0Sstevel@tonic-gate my $tagspace = ' ' x length $tag; 558*0Sstevel@tonic-gate s/^($space)$tagspace/$1$tag/ or warn "Bizarre space in item"; 559*0Sstevel@tonic-gate $self->output ($_); 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate} 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate############################################################################## 565*0Sstevel@tonic-gate# Output formatting 566*0Sstevel@tonic-gate############################################################################## 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate# Wrap a line, indenting by the current left margin. We can't use Text::Wrap 569*0Sstevel@tonic-gate# because it plays games with tabs. We can't use formline, even though we'd 570*0Sstevel@tonic-gate# really like to, because it screws up non-printing characters. So we have to 571*0Sstevel@tonic-gate# do the wrapping ourselves. 572*0Sstevel@tonic-gatesub wrap { 573*0Sstevel@tonic-gate my $self = shift; 574*0Sstevel@tonic-gate local $_ = shift; 575*0Sstevel@tonic-gate my $output = ''; 576*0Sstevel@tonic-gate my $spaces = ' ' x $$self{MARGIN}; 577*0Sstevel@tonic-gate my $width = $$self{width} - $$self{MARGIN}; 578*0Sstevel@tonic-gate while (length > $width) { 579*0Sstevel@tonic-gate if (s/^([^\n]{0,$width})\s+// || s/^([^\n]{$width})//) { 580*0Sstevel@tonic-gate $output .= $spaces . $1 . "\n"; 581*0Sstevel@tonic-gate } else { 582*0Sstevel@tonic-gate last; 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate $output .= $spaces . $_; 586*0Sstevel@tonic-gate $output =~ s/\s+$/\n\n/; 587*0Sstevel@tonic-gate $output; 588*0Sstevel@tonic-gate} 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate# Reformat a paragraph of text for the current margin. Takes the text to 591*0Sstevel@tonic-gate# reformat and returns the formatted text. 592*0Sstevel@tonic-gatesub reformat { 593*0Sstevel@tonic-gate my $self = shift; 594*0Sstevel@tonic-gate local $_ = shift; 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate # If we're trying to preserve two spaces after sentences, do some munging 597*0Sstevel@tonic-gate # to support that. Otherwise, smash all repeated whitespace. 598*0Sstevel@tonic-gate if ($$self{sentence}) { 599*0Sstevel@tonic-gate s/ +$//mg; 600*0Sstevel@tonic-gate s/\.\n/. \n/g; 601*0Sstevel@tonic-gate s/\n/ /g; 602*0Sstevel@tonic-gate s/ +/ /g; 603*0Sstevel@tonic-gate } else { 604*0Sstevel@tonic-gate s/\s+/ /g; 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate $self->wrap ($_); 607*0Sstevel@tonic-gate} 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate# Output text to the output device. 610*0Sstevel@tonic-gatesub output { $_[1] =~ tr/\01/ /; print { $_[0]->output_handle } $_[1] } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate# Output a block of code (something that isn't part of the POD text). Called 613*0Sstevel@tonic-gate# by preprocess_paragraph only if we were given the code option. Exists here 614*0Sstevel@tonic-gate# only so that it can be overridden by subclasses. 615*0Sstevel@tonic-gatesub output_code { $_[0]->output ($_[1]) } 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate############################################################################## 619*0Sstevel@tonic-gate# Backwards compatibility 620*0Sstevel@tonic-gate############################################################################## 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate# The old Pod::Text module did everything in a pod2text() function. This 623*0Sstevel@tonic-gate# tries to provide the same interface for legacy applications. 624*0Sstevel@tonic-gatesub pod2text { 625*0Sstevel@tonic-gate my @args; 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate # This is really ugly; I hate doing option parsing in the middle of a 628*0Sstevel@tonic-gate # module. But the old Pod::Text module supported passing flags to its 629*0Sstevel@tonic-gate # entry function, so handle -a and -<number>. 630*0Sstevel@tonic-gate while ($_[0] =~ /^-/) { 631*0Sstevel@tonic-gate my $flag = shift; 632*0Sstevel@tonic-gate if ($flag eq '-a') { push (@args, alt => 1) } 633*0Sstevel@tonic-gate elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) } 634*0Sstevel@tonic-gate else { 635*0Sstevel@tonic-gate unshift (@_, $flag); 636*0Sstevel@tonic-gate last; 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate # Now that we know what arguments we're using, create the parser. 641*0Sstevel@tonic-gate my $parser = Pod::Text->new (@args); 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate # If two arguments were given, the second argument is going to be a file 644*0Sstevel@tonic-gate # handle. That means we want to call parse_from_filehandle(), which means 645*0Sstevel@tonic-gate # we need to turn the first argument into a file handle. Magic open will 646*0Sstevel@tonic-gate # handle the <&STDIN case automagically. 647*0Sstevel@tonic-gate if (defined $_[1]) { 648*0Sstevel@tonic-gate my @fhs = @_; 649*0Sstevel@tonic-gate local *IN; 650*0Sstevel@tonic-gate unless (open (IN, $fhs[0])) { 651*0Sstevel@tonic-gate croak ("Can't open $fhs[0] for reading: $!\n"); 652*0Sstevel@tonic-gate return; 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate $fhs[0] = \*IN; 655*0Sstevel@tonic-gate return $parser->parse_from_filehandle (@fhs); 656*0Sstevel@tonic-gate } else { 657*0Sstevel@tonic-gate return $parser->parse_from_file (@_); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate} 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate############################################################################## 663*0Sstevel@tonic-gate# Module return value and documentation 664*0Sstevel@tonic-gate############################################################################## 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate1; 667*0Sstevel@tonic-gate__END__ 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate=head1 NAME 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gatePod::Text - Convert POD data to formatted ASCII text 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate=head1 SYNOPSIS 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate use Pod::Text; 676*0Sstevel@tonic-gate my $parser = Pod::Text->new (sentence => 0, width => 78); 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate # Read POD from STDIN and write to STDOUT. 679*0Sstevel@tonic-gate $parser->parse_from_filehandle; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate # Read POD from file.pod and write to file.txt. 682*0Sstevel@tonic-gate $parser->parse_from_file ('file.pod', 'file.txt'); 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate=head1 DESCRIPTION 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gatePod::Text is a module that can convert documentation in the POD format (the 687*0Sstevel@tonic-gatepreferred language for documenting Perl) into formatted ASCII. It uses no 688*0Sstevel@tonic-gatespecial formatting controls or codes whatsoever, and its output is therefore 689*0Sstevel@tonic-gatesuitable for nearly any device. 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gateAs a derived class from Pod::Parser, Pod::Text supports the same methods and 692*0Sstevel@tonic-gateinterfaces. See L<Pod::Parser> for all the details; briefly, one creates a 693*0Sstevel@tonic-gatenew parser with C<< Pod::Text->new() >> and then calls either 694*0Sstevel@tonic-gateparse_from_filehandle() or parse_from_file(). 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gatenew() can take options, in the form of key/value pairs, that control the 697*0Sstevel@tonic-gatebehavior of the parser. The currently recognized options are: 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate=over 4 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate=item alt 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gateIf set to a true value, selects an alternate output format that, among other 704*0Sstevel@tonic-gatethings, uses a different heading style and marks C<=item> entries with a 705*0Sstevel@tonic-gatecolon in the left margin. Defaults to false. 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate=item code 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gateIf set to a true value, the non-POD parts of the input file will be included 710*0Sstevel@tonic-gatein the output. Useful for viewing code documented with POD blocks with the 711*0Sstevel@tonic-gatePOD rendered and the code left intact. 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate=item indent 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gateThe number of spaces to indent regular text, and the default indentation for 716*0Sstevel@tonic-gateC<=over> blocks. Defaults to 4. 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate=item loose 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gateIf set to a true value, a blank line is printed after a C<=head1> heading. 721*0Sstevel@tonic-gateIf set to false (the default), no blank line is printed after C<=head1>, 722*0Sstevel@tonic-gatealthough one is still printed after C<=head2>. This is the default because 723*0Sstevel@tonic-gateit's the expected formatting for manual pages; if you're formatting 724*0Sstevel@tonic-gatearbitrary text documents, setting this to true may result in more pleasing 725*0Sstevel@tonic-gateoutput. 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate=item margin 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gateThe width of the left margin in spaces. Defaults to 0. This is the margin 730*0Sstevel@tonic-gatefor all text, including headings, not the amount by which regular text is 731*0Sstevel@tonic-gateindented; for the latter, see the I<indent> option. To set the right 732*0Sstevel@tonic-gatemargin, see the I<width> option. 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate=item quotes 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gateSets the quote marks used to surround CE<lt>> text. If the value is a 737*0Sstevel@tonic-gatesingle character, it is used as both the left and right quote; if it is two 738*0Sstevel@tonic-gatecharacters, the first character is used as the left quote and the second as 739*0Sstevel@tonic-gatethe right quoted; and if it is four characters, the first two are used as 740*0Sstevel@tonic-gatethe left quote and the second two as the right quote. 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gateThis may also be set to the special value C<none>, in which case no quote 743*0Sstevel@tonic-gatemarks are added around CE<lt>> text. 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate=item sentence 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gateIf set to a true value, Pod::Text will assume that each sentence ends in two 748*0Sstevel@tonic-gatespaces, and will try to preserve that spacing. If set to false, all 749*0Sstevel@tonic-gateconsecutive whitespace in non-verbatim paragraphs is compressed into a 750*0Sstevel@tonic-gatesingle space. Defaults to true. 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate=item width 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gateThe column at which to wrap text on the right-hand side. Defaults to 76. 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate=back 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gateThe standard Pod::Parser method parse_from_filehandle() takes up to two 759*0Sstevel@tonic-gatearguments, the first being the file handle to read POD from and the second 760*0Sstevel@tonic-gatebeing the file handle to write the formatted output to. The first defaults 761*0Sstevel@tonic-gateto STDIN if not given, and the second defaults to STDOUT. The method 762*0Sstevel@tonic-gateparse_from_file() is almost identical, except that its two arguments are the 763*0Sstevel@tonic-gateinput and output disk files instead. See L<Pod::Parser> for the specific 764*0Sstevel@tonic-gatedetails. 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate=head1 DIAGNOSTICS 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate=over 4 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate=item Bizarre space in item 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate=item Item called without tag 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate(W) Something has gone wrong in internal C<=item> processing. These 775*0Sstevel@tonic-gatemessages indicate a bug in Pod::Text; you should never see them. 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate=item Can't open %s for reading: %s 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate(F) Pod::Text was invoked via the compatibility mode pod2text() interface 780*0Sstevel@tonic-gateand the input file it was given could not be opened. 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate=item Invalid quote specification "%s" 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate(F) The quote specification given (the quotes option to the constructor) was 785*0Sstevel@tonic-gateinvalid. A quote specification must be one, two, or four characters long. 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate=item %s:%d: Unknown command paragraph: %s 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate(W) The POD source contained a non-standard command paragraph (something of 790*0Sstevel@tonic-gatethe form C<=command args>) that Pod::Man didn't know about. It was ignored. 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate=item %s:%d: Unknown escape: %s 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate(W) The POD source contained an C<EE<lt>E<gt>> escape that Pod::Text didn't 795*0Sstevel@tonic-gateknow about. 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate=item %s:%d: Unknown formatting code: %s 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate(W) The POD source contained a non-standard formatting code (something of 800*0Sstevel@tonic-gatethe form C<XE<lt>E<gt>>) that Pod::Text didn't know about. 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate=item %s:%d: Unmatched =back 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate(W) Pod::Text encountered a C<=back> command that didn't correspond to an 805*0Sstevel@tonic-gateC<=over> command. 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate=back 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate=head1 RESTRICTIONS 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gateEmbedded Ctrl-As (octal 001) in the input will be mapped to spaces on 812*0Sstevel@tonic-gateoutput, due to an internal implementation detail. 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate=head1 NOTES 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gateThis is a replacement for an earlier Pod::Text module written by Tom 817*0Sstevel@tonic-gateChristiansen. It has a revamped interface, since it now uses Pod::Parser, 818*0Sstevel@tonic-gatebut an interface roughly compatible with the old Pod::Text::pod2text() 819*0Sstevel@tonic-gatefunction is still available. Please change to the new calling convention, 820*0Sstevel@tonic-gatethough. 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gateThe original Pod::Text contained code to do formatting via termcap 823*0Sstevel@tonic-gatesequences, although it wasn't turned on by default and it was problematic to 824*0Sstevel@tonic-gateget it to work at all. This rewrite doesn't even try to do that, but a 825*0Sstevel@tonic-gatesubclass of it does. Look for L<Pod::Text::Termcap>. 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate=head1 SEE ALSO 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gateL<Pod::Parser>, L<Pod::Text::Termcap>, L<pod2text(1)> 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gateThe current version of this module is always available from its web site at 832*0Sstevel@tonic-gateL<http://www.eyrie.org/~eagle/software/podlators/>. It is also part of the 833*0Sstevel@tonic-gatePerl core distribution as of 5.6.0. 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate=head1 AUTHOR 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gateRuss Allbery <rra@stanford.edu>, based I<very> heavily on the original 838*0Sstevel@tonic-gatePod::Text by Tom Christiansen <tchrist@mox.perl.com> and its conversion to 839*0Sstevel@tonic-gatePod::Parser by Brad Appleton <bradapp@enteract.com>. 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate=head1 COPYRIGHT AND LICENSE 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gateCopyright 1999, 2000, 2001, 2002 by Russ Allbery <rra@stanford.edu>. 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gateThis program is free software; you may redistribute it and/or modify it 846*0Sstevel@tonic-gateunder the same terms as Perl itself. 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate=cut 849