diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | MAINTAIN | 5 | ||||
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | ext/Devel/Peek/Peek.pm | 2 | ||||
-rw-r--r-- | lib/Pod/LaTeX.pm | 1567 | ||||
-rw-r--r-- | pod/pod2latex.PL | 928 |
6 files changed, 1857 insertions, 647 deletions
@@ -54,6 +54,7 @@ pueschel Norbert Pueschel pueschel@imsdd.meb.uni-bonn.de pvhp Peter Prymmer pvhp@forte.com raphael Raphael Manfredi Raphael_Manfredi@pobox.com rdieter Rex Dieter rdieter@math.unl.edu +rra Russ Allbery rra@stanford.edu rsanders Robert Sanders Robert.Sanders@linux.org roberto Ollivier Robert roberto@keltia.freenix.fr roderick Roderick Schertler roderick@argon.org @@ -434,10 +434,13 @@ lib/Pod/Checker.pm bradapp lib/Pod/Functions.pm lib/Pod/Html.pm tchrist lib/Pod/InputObjects.pm bradapp +lib/Pod/LaTeX.pm tjenness +lib/Pod/Man.pm rra lib/Pod/Parser.pm bradapp lib/Pod/PlainText.pm bradapp lib/Pod/Select.pm bradapp -lib/Pod/Text.pm tchrist +lib/Pod/Text.pm rra +lib/Pod/Text/* rra lib/Pod/Usage.pm bradapp lib/Search/Dict.pm lib/SelectSaver.pm @@ -643,6 +643,7 @@ lib/Pod/Find.pm used by pod/splitpod lib/Pod/Functions.pm used by pod/splitpod lib/Pod/Html.pm Convert POD data to HTML lib/Pod/InputObjects.pm Pod-Parser - define objects for input streams +lib/Pod/LaTeX.pm Convert POD data to LaTeX lib/Pod/Man.pm Convert POD data to *roff lib/Pod/ParseUtils.pm Pod-Parser - pod utility functions lib/Pod/Parser.pm Pod-Parser - define base class for parsing POD diff --git a/ext/Devel/Peek/Peek.pm b/ext/Devel/Peek/Peek.pm index 1ef29b476f..101adcd00f 100644 --- a/ext/Devel/Peek/Peek.pm +++ b/ext/Devel/Peek/Peek.pm @@ -62,7 +62,7 @@ function. For more information on the format of output of mstat() see L<perldebug/Using C<$ENV{PERL_DEBUG_MSTATS}>>. Function C<DumpArray()> allows dumping of multiple values (useful when you -need to analize returns of functions). +need to analyze returns of functions). The global variable $Devel::Peek::pv_limit can be set to limit the number of character printed in various string values. Setting it to 0 diff --git a/lib/Pod/LaTeX.pm b/lib/Pod/LaTeX.pm new file mode 100644 index 0000000000..8adb58921c --- /dev/null +++ b/lib/Pod/LaTeX.pm @@ -0,0 +1,1567 @@ +package Pod::LaTeX; + +# Copyright (C) 2000 by Tim Jenness <t.jenness@jach.hawaii.edu> +# All Rights Reserved. + +=head1 NAME + +Pod::LaTeX - Convert Pod data to formatted Latex + +=head1 SYNOPSIS + + use Pod::LaTeX; + my $parser = Pod::LaTeX->new ( ); + + $parser->parse_from_filehandle; + + $parser->parse_from_file ('file.pod', 'file.tex'); + +=head1 DESCRIPTION + +C<Pod::LaTeX> is a module to convert documentation in the Pod format +into Latex. The L<B<pod2latex>|pod2latex> X<pod2latex> command uses +this module for translation. + +C<Pod::LaTeX> is a derived class from L<Pod::Select|Pod::Select>. + +=cut + + +use strict; +require Pod::ParseUtils; +use base qw/ Pod::Select /; + +# use Data::Dumper; # for debugging +use Carp; + +use vars qw/ $VERSION %HTML_Escapes @LatexSections /; + +$VERSION = '0.52'; + +# Definitions of =headN -> latex mapping +@LatexSections = (qw/ + chapter + section + subsection + subsubsection + paragraph + subparagraph + /); + +# Standard escape sequences converted to Latex +# Up to "yuml" these are taken from the original pod2latex +# command written by Taro Kawagish (kawagish@imslab.co.jp) + +%HTML_Escapes = ( + 'amp' => '&', # ampersand + 'lt' => '$<$', # ' left chevron, less-than + 'gt' => '$>$', # ' right chevron, greater-than + 'quot' => '"', # double quote + + "Aacute" => "\\'{A}", # capital A, acute accent + "aacute" => "\\'{a}", # small a, acute accent + "Acirc" => "\\^{A}", # capital A, circumflex accent + "acirc" => "\\^{a}", # small a, circumflex accent + "AElig" => '\\AE', # capital AE diphthong (ligature) + "aelig" => '\\ae', # small ae diphthong (ligature) + "Agrave" => "\\`{A}", # capital A, grave accent + "agrave" => "\\`{a}", # small a, grave accent + "Aring" => '\\u{A}', # capital A, ring + "aring" => '\\u{a}', # small a, ring + "Atilde" => '\\~{A}', # capital A, tilde + "atilde" => '\\~{a}', # small a, tilde + "Auml" => '\\"{A}', # capital A, dieresis or umlaut mark + "auml" => '\\"{a}', # small a, dieresis or umlaut mark + "Ccedil" => '\\c{C}', # capital C, cedilla + "ccedil" => '\\c{c}', # small c, cedilla + "Eacute" => "\\'{E}", # capital E, acute accent + "eacute" => "\\'{e}", # small e, acute accent + "Ecirc" => "\\^{E}", # capital E, circumflex accent + "ecirc" => "\\^{e}", # small e, circumflex accent + "Egrave" => "\\`{E}", # capital E, grave accent + "egrave" => "\\`{e}", # small e, grave accent + "ETH" => '\\OE', # capital Eth, Icelandic + "eth" => '\\oe', # small eth, Icelandic + "Euml" => '\\"{E}', # capital E, dieresis or umlaut mark + "euml" => '\\"{e}', # small e, dieresis or umlaut mark + "Iacute" => "\\'{I}", # capital I, acute accent + "iacute" => "\\'{i}", # small i, acute accent + "Icirc" => "\\^{I}", # capital I, circumflex accent + "icirc" => "\\^{i}", # small i, circumflex accent + "Igrave" => "\\`{I}", # capital I, grave accent + "igrave" => "\\`{i}", # small i, grave accent + "Iuml" => '\\"{I}', # capital I, dieresis or umlaut mark + "iuml" => '\\"{i}', # small i, dieresis or umlaut mark + "Ntilde" => '\\~{N}', # capital N, tilde + "ntilde" => '\\~{n}', # small n, tilde + "Oacute" => "\\'{O}", # capital O, acute accent + "oacute" => "\\'{o}", # small o, acute accent + "Ocirc" => "\\^{O}", # capital O, circumflex accent + "ocirc" => "\\^{o}", # small o, circumflex accent + "Ograve" => "\\`{O}", # capital O, grave accent + "ograve" => "\\`{o}", # small o, grave accent + "Oslash" => "\\O", # capital O, slash + "oslash" => "\\o", # small o, slash + "Otilde" => "\\~{O}", # capital O, tilde + "otilde" => "\\~{o}", # small o, tilde + "Ouml" => '\\"{O}', # capital O, dieresis or umlaut mark + "ouml" => '\\"{o}', # small o, dieresis or umlaut mark + "szlig" => '\\ss{}', # small sharp s, German (sz ligature) + "THORN" => '\\L', # capital THORN, Icelandic + "thorn" => '\\l',, # small thorn, Icelandic + "Uacute" => "\\'{U}", # capital U, acute accent + "uacute" => "\\'{u}", # small u, acute accent + "Ucirc" => "\\^{U}", # capital U, circumflex accent + "ucirc" => "\\^{u}", # small u, circumflex accent + "Ugrave" => "\\`{U}", # capital U, grave accent + "ugrave" => "\\`{u}", # small u, grave accent + "Uuml" => '\\"{U}', # capital U, dieresis or umlaut mark + "uuml" => '\\"{u}', # small u, dieresis or umlaut mark + "Yacute" => "\\'{Y}", # capital Y, acute accent + "yacute" => "\\'{y}", # small y, acute accent + "yuml" => '\\"{y}', # small y, dieresis or umlaut mark + + # Added by TimJ + + "iexcl" => '!`', # inverted exclamation mark +# "cent" => ' ', # cent sign + "pound" => '\pounds', # (UK) pound sign +# "curren" => ' ', # currency sign +# "yen" => ' ', # yen sign +# "brvbar" => ' ', # broken vertical bar + "sect" => '\S', # section sign + "uml" => '\"{}', # diaresis + "copy" => '\copyright', # Copyright symbol +# "ordf" => ' ', # feminine ordinal indicator + "laquo" => '$\ll$', # ' # left pointing double angle quotation mark + "not" => '$\neg$', # ' # not sign + "shy" => '-', # soft hyphen +# "reg" => ' ', # registered trademark + "macr" => '$^-$', # ' # macron, overline + "deg" => '$^\circ$', # ' # degree sign + "plusmn" => '$\pm$', # ' # plus-minus sign + "sup2" => '$^2$', # ' # superscript 2 + "sup3" => '$^3$', # ' # superscript 3 + "acute" => "\\'{}", # acute accent + "micro" => '$\mu$', # micro sign + "para" => '\P', # pilcrow sign = paragraph sign + "middot" => '$\cdot$', # middle dot = Georgian comma + "cedil" => '\c{}', # cedilla + "sup1" => '$^1$', # ' # superscript 1 +# "ordm" => ' ', # masculine ordinal indicator + "raquo" => '$\gg$', # ' # right pointing double angle quotation mark + "frac14" => '$\frac{1}{4}$', # ' # vulgar fraction one quarter + "frac12" => '$\frac{1}{2}$', # ' # vulgar fraction one half + "frac34" => '$\frac{3}{4}$', # ' # vulgar fraction three quarters + "iquest" => "?'", # inverted question mark + "times" => '$\times$', # ' # multiplication sign + "divide" => '$\div$', # division sign + + # Greek letters using HTML codes + "alpha" => '$\alpha$', # ' + "beta" => '$\beta$', # ' + "gamma" => '$\gamma$', # ' + "delta" => '$\delta$', # ' + "epsilon"=> '$\epsilon$', # ' + "zeta" => '$\zeta$', # ' + "eta" => '$\eta$', # ' + "theta" => '$\theta$', # ' + "iota" => '$\iota$', # ' + "kappa" => '$\kappa$', # ' + "lambda" => '$\lambda$', # ' + "mu" => '$\mu$', # ' + "nu" => '$\nu$', # ' + "xi" => '$\xi$', # ' + "omicron"=> '$o$', # ' + "pi" => '$\pi$', # ' + "rho" => '$\rho$', # ' + "sigma" => '$\sigma$', # ' + "tau" => '$\tau$', # ' + "upsilon"=> '$\upsilon$', # ' + "phi" => '$\phi$', # ' + "chi" => '$\chi$', # ' + "psi" => '$\psi$', # ' + "omega" => '$\omega$', # ' + + "Alpha" => '$A$', # ' + "Beta" => '$B$', # ' + "Gamma" => '$\Gamma$', # ' + "Delta" => '$\Delta$', # ' + "Epsilon"=> '$E$', # ' + "Zeta" => '$Z$', # ' + "Eta" => '$H$', # ' + "Theta" => '$\Theta$', # ' + "Iota" => '$I$', # ' + "Kappa" => '$K$', # ' + "Lambda" => '$\Lambda$', # ' + "Mu" => '$M$', # ' + "Nu" => '$N$', # ' + "Xi" => '$\Xi$', # ' + "Omicron"=> '$O$', # ' + "Pi" => '$\Pi$', # ' + "Rho" => '$R$', # ' + "Sigma" => '$\Sigma$', # ' + "Tau" => '$T$', # ' + "Upsilon"=> '$\Upsilon$', # ' + "Phi" => '$\Phi$', # ' + "Chi" => '$X$', # ' + "Psi" => '$\Psi$', # ' + "Omega" => '$\Omega$', # ' + + +); + + +=head1 OBJECT METHODS + +The following methods are provided in this module. Methods inherited +from C<Pod::Select> are not described in the public interface. + +=over 4 + +=begin __PRIVATE__ + +=item C<initialize> + +Initialise the object. This method is subclassed from C<Pod::Parser>. +The base class method is invoked. This method defines the default +behaviour of the object unless overridden by supplying arguments to +the constructor. + +Internal settings are defaulted as well as the public instance data. +Internal hash values are accessed directly (rather than through +a method) and start with an underscore. + +This method should not be invoked by the user directly. + +=end __PRIVATE__ + +=cut + + + +# - An array for nested lists + +# Arguments have already been read by this point + +sub initialize { + my $self = shift; + + # print Dumper($self); + + # Internals + $self->{_Lists} = []; # For nested lists + $self->{_suppress_all_para} = 0; # For =begin blocks + $self->{_suppress_next_para} = 0; # For =for blocks + $self->{_dont_modify_any_para}=0; # For =begin blocks + $self->{_dont_modify_next_para}=0; # For =for blocks + $self->{_CURRENT_HEAD1} = ''; # Name of current HEAD1 section + + # Options - only initialise if not already set + + # Cause the '=head1 NAME' field to be treated specially + # The contents of the NAME paragraph will be converted + # to a section title. All subsequent =head1 will be converted + # to =head2 and down. Will not affect =head1's prior to NAME + # Assumes: 'Module - purpose' format + # Also creates a purpose field + # The name is used for Labeling of the subsequent subsections + $self->{ReplaceNAMEwithSection} = 0 + unless exists $self->{ReplaceNAMEwithSection}; + $self->{AddPreamble} = 1 # make full latex document + unless exists $self->{AddPreamble}; + $self->{StartWithNewPage} = 0 # Start new page for pod section + unless exists $self->{StartWithNewPage}; + $self->{TableOfContents} = 0 # Add table of contents + unless exists $self->{TableOfContents}; # only relevent if AddPreamble=1 + $self->{AddPostamble} = 1 # Add closing latex code at end + unless exists $self->{AddPostamble}; # effectively end{document} and index + $self->{MakeIndex} = 1 # Add index (only relevant AddPostamble + unless exists $self->{MakeIndex}; # and AddPreamble) + + $self->{UniqueLabels} = 1 # Use label unique for each pod + unless exists $self->{UniqueLabels}; # either based on the filename + # or supplied + + # Control the level of =head1. default is \section + # + $self->{Head1Level} = 1 # Offset in latex sections + unless exists $self->{Head1Level}; # 0 is chapter, 2 is subsection + + # Control at which level numbering of sections is turned off + # ie subsection becomes subsection* + # The numbering is relative to the latex sectioning commands + # and is independent of Pod heading level + # default is to number \section but not \subsection + $self->{LevelNoNum} = 2 + unless exists $self->{LevelNoNum}; + + # Label to be used as prefix to all internal section names + # If not defined will attempt to derive it from the filename + # This can not happen when running parse_from_filehandle though + # hence the ability to set the label externally + # The label could then be Pod::Parser_DESCRIPTION or somesuch + + $self->{Label} = undef # label to be used as prefix + unless exists $self->{Label}; # to all internal section names + + # These allow the caller to add arbritrary latex code to + # start and end of document. AddPreamble and AddPostamble are ignored + # if these are set. + # Also MakeIndex and TableOfContents are also ignored. + $self->{UserPreamble} = undef # User supplied start (AddPreamble =1) + unless exists $self->{Label}; + $self->{UserPostamble} = undef # Use supplied end (AddPostamble=1) + unless exists $self->{Label}; + + # Run base initialize + $self->SUPER::initialize; + +} + +=back + +=head2 Data Accessors + +The following methods are provided for accessing instance data. These +methods should be used for accessing configuration parameters rather +than assuming the object is a hash. + +Default values can be supplied by using these names as keys to a hash +of arguments when using the C<new()> constructor. + +=over 4 + +=item B<AddPreamble> + +Logical to control whether a C<latex> preamble is to be written. +If true, a valid C<latex> preamble is written before the pod data is written. +This is similar to: + + \documentclass{article} + \begin{document} + +but will be more complicated if table of contents and indexing are required. +Can be used to set or retrieve the current value. + + $add = $parser->AddPreamble(); + $parser->AddPreamble(1); + +If used in conjunction with C<AddPostamble> a full latex document will +be written that could be immediately processed by C<latex>. + +=cut + +sub AddPreamble { + my $self = shift; + if (@_) { + $self->{AddPreamble} = shift; + } + return $self->{AddPreamble}; +} + +=item B<AddPostamble> + +Logical to control whether a standard C<latex> ending is written to the output +file after the document has been processed. +In its simplest form this is simply: + + \end{document} + +but can be more complicated if a index is required. +Can be used to set or retrieve the current value. + + $add = $parser->AddPostamble(); + $parser->AddPostamble(1); + +If used in conjunction with C<AddPreaamble> a full latex document will +be written that could be immediately processed by C<latex>. + +=cut + +sub AddPostamble { + my $self = shift; + if (@_) { + $self->{AddPostamble} = shift; + } + return $self->{AddPostamble}; +} + +=item B<Head1Level> + +The C<latex> sectioning level that should be used to correspond to +a pod C<=head1> directive. This can be used, for example, to turn +a C<=head1> into a C<latex> C<subsection>. This should hold a number +corresponding to the required position in an array containing the +following elements: + + [0] chapter + [1] section + [2] subsection + [3] subsubsection + [4] paragraph + [5] subparagraph + +Can be used to set or retrieve the current value: + + $parser->Head1Level(2); + $sect = $parser->Head1Level; + +Setting this number too high can result in sections that may not be reproducible +in the expected way. For example, setting this to 4 would imply that C<=head3> +do not have a corresponding C<latex> section (C<=head1> would correspond to +a C<paragraph>). + +A check is made to ensure that the supplied value is an integer in the +range 0 to 5. + +Default is for a value of 1 (i.e. a C<section>). + +=cut + +sub Head1Level { + my $self = shift; + if (@_) { + my $arg = shift; + if ($arg =~ /^\d$/ && $arg <= $#LatexSections) { + $self->{Head1Level} = $arg; + } else { + carp "Head1Level supplied ($arg) must be integer in range 0 to ".$#LatexSections . "- Ignoring\n"; + } + } + return $self->{Head1Level}; +} + +=item B<Label> + +This is the label that is prefixed to all C<latex> label and index +entries to make them unique. In general, pods have similarly titled +sections (NAME, DESCRIPTION etc) and a C<latex> label will be multiply +defined if more than one pod document is to be included in a single +C<latex> file. To overcome this, this label is prefixed to a label +whenever a label is required (joined with an underscore) or to an +index entry (joined by an exclamation mark which is the normal index +separator). For example, C<\label{text}> becomes C<\label{Label_text}>. + +Can be used to set or retrieve the current value: + + $label = $parser->Label; + $parser->Label($label); + +This label is only used if C<UniqueLabels> is true. +Its value is set automatically from the C<NAME> field +if C<ReplaceNAMEwithSection> is true. If this is not the case +it must be set manually before starting the parse. + +Default value is C<undef>. + +=cut + +sub Label { + my $self = shift; + if (@_) { + $self->{Label} = shift; + } + return $self->{Label}; +} + +=item B<LevelNoNum> + +Control the point at which C<latex> section numbering is turned off. +For example, this can be used to make sure that C<latex> sections +are numbered but subsections are not. + +Can be used to set or retrieve the current value: + + $lev = $parser->LevelNoNum; + $parser->LevelNoNum(2); + +The argument must be an integer between 0 and 5 and is the same as the +number described in C<Head1Level> method description. The number has +nothing to do with the pod heading number, only the C<latex> sectioning. + +Default is 2. (i.e. C<latex> subsections are written as C<subsection*> +but sections are numbered). + +=cut + +sub LevelNoNum { + my $self = shift; + if (@_) { + $self->{LevelNoNum} = shift; + } + return $self->{LevelNoNum}; +} + +=item B<MakeIndex> + +Controls whether C<latex> commands for creating an index are to be inserted +into the preamble and postamble + + $makeindex = $parser->MakeIndex; + $parser->MakeIndex(0); + +Irrelevant if both C<AddPreamble> and C<AddPostamble> are false (or equivalently, +C<UserPreamble> and C<UserPostamble> are set). + +Default is for an index to be created. + +=cut + +sub MakeIndex { + my $self = shift; + if (@_) { + $self->{MakeIndex} = shift; + } + return $self->{MakeIndex}; +} + +=item B<ReplaceNAMEwithSection> + +This controls whether the C<NAME> section in the pod is to be translated +literally or converted to a slightly modified output where the section +name is the pod name rather than "NAME". + +If true, the pod segment + + =head1 NAME + + pod::name - purpose + + =head1 SYNOPSIS + +is converted to the C<latex> + + \section{pod::name\label{pod_name}\index{pod::name}} + + Purpose + + \subsection*{SYNOPSIS\label{pod_name_SYNOPSIS}% + \index{pod::name!SYNOPSIS}} + +(dependent on the value of C<Head1Level> and C<LevelNoNum>). Note that +subsequent C<head1> directives translate to subsections rather than +sections and that the labels and index now include the pod name (dependent +on the value of C<UniqueLabels>). + +The C<Label> is set from the pod name regardless of any current value +of C<Label>. + + $mod = $parser->ReplaceNAMEwithSection; + $parser->ReplaceNAMEwithSection(0); + +Default is to translate the pod literally. + +=cut + +sub ReplaceNAMEwithSection { + my $self = shift; + if (@_) { + $self->{ReplaceNAMEwithSection} = shift; + } + return $self->{ReplaceNAMEwithSection}; +} + +=item B<StartWithNewPage> + +If true, each pod translation will begin with a C<latex> +C<\clearpage>. + + $parser->StartWithNewPage(1); + $newpage = $parser->StartWithNewPage; + +Default is false. + +=cut + +sub StartWithNewPage { + my $self = shift; + if (@_) { + $self->{StartWithNewPage} = shift; + } + return $self->{StartWithNewPage}; +} + +=item B<TableOfContents> + +If true, a table of contents will be created. +Irrelevant if C<AddPreamble> is false or C<UserPreamble> +is set. + + $toc = $parser->TableOfContents; + $parser->TableOfContents(1); + +Default is false. + +=cut + +sub TableOfContents { + my $self = shift; + if (@_) { + $self->{TableOfContents} = shift; + } + return $self->{TableOfContents}; +} + +=item B<UniqueLabels> + +If true, the translator will attempt to make sure that +each C<latex> label or index entry will be uniquely identified +by prefixing the contents of C<Label>. This allows +multiple documents to be combined without clashing +common labels such as C<DESCRIPTION> and C<SYNOPSIS> + + $parser->UniqueLabels(1); + $unq = $parser->UniqueLabels; + +Default is true. + +=cut + +sub UniqueLabels { + my $self = shift; + if (@_) { + $self->{UniqueLabels} = shift; + } + return $self->{UniqueLabels}; +} + +=item B<UserPreamble> + +User supplied C<latex> preamble. Added before the pod translation +data. + +If set, the contents will be prepended to the output file before the translated +data regardless of the value of C<AddPreamble>. +C<MakeIndex> and C<TableOfContents> will also be ignored. + +=cut + +sub UserPreamble { + my $self = shift; + if (@_) { + $self->{UserPreamble} = shift; + } + return $self->{UserPreamble}; +} + +=item B<UserPostamble> + +User supplied C<latex> postamble. Added after the pod translation +data. + +If set, the contents will be prepended to the output file after the translated +data regardless of the value of C<AddPostamble>. +C<MakeIndex> will also be ignored. + +=cut + +sub UserPostamble { + my $self = shift; + if (@_) { + $self->{UserPostamble} = shift; + } + return $self->{UserPostamble}; +} + +=begin __PRIVATE__ + +=item B<Lists> + +Contains details of the currently active lists. + The array contains C<Pod::List> objects. A new C<Pod::List> +object is created each time a list is encountered and it is +pushed onto this stack. When the list context ends, it +is popped from the stack. The array will be empty if no +lists are active. + +Returns array of list information in array context +Returns array ref in scalar context + +=cut + + + +sub lists { + my $self = shift; + return @{ $self->{_Lists} } if wantarray(); + return $self->{_Lists}; +} + +=end __PRIVATE__ + +=back + +=begin __PRIVATE__ + +=head2 Subclassed methods + +The following methods override methods provided in the C<Pod::Select> +base class. See C<Pod::Parser> and C<Pod::Select> for more information +on what these methods require. + +=over 4 + +=cut + +######### END ACCESSORS ################### + +# Opening pod + +=item B<begin_pod> + +Writes the C<latex> preamble if requested. + +=cut + +sub begin_pod { + my $self = shift; + + # Get the pod identification + # This should really come from the '=head1 NAME' paragraph + + my $infile = $self->input_file; + my $class = ref($self); + my $date = gmtime(time); + + # Comment message to say where this came from + my $comment = << "__TEX_COMMENT__"; +%% Latex generated from POD in document $infile +%% Using the perl module $class +%% Converted on $date +__TEX_COMMENT__ + + # Write the preamble + # If the caller has supplied one then we just use that + + my $preamble = ''; + if (defined $self->UserPreamble) { + + $preamble = $self->UserPreamble; + + # Add the description of where this came from + $preamble .= "\n$comment"; + + + } elsif ($self->AddPreamble) { + # Write our own preamble + + # Code to initialise index making + # Use an array so that we can prepend comment if required + my @makeidx = ( + '\usepackage{makeidx}', + '\makeindex', + ); + + unless ($self->MakeIndex) { + foreach (@makeidx) { + $_ = '%% ' . $_; + } + } + my $makeindex = join("\n",@makeidx) . "\n"; + + + # Table of contents + my $tableofcontents = '\tableofcontents'; + + $tableofcontents = '%% ' . $tableofcontents + unless $self->TableOfContents; + + # Roll our own + $preamble = << "__TEX_HEADER__"; +\\documentclass{article} + +$comment + +$makeindex + +\\begin{document} + +$tableofcontents + +__TEX_HEADER__ + + } + + # Write the header (blank if none) + $self->_output($preamble); + + # Start on new page if requested + $self->_output("\\clearpage\n") if $self->StartWithNewPage; + +} + + +=item B<end_pod> + +Write the closing C<latex> code. + +=cut + +sub end_pod { + my $self = shift; + + # End string + my $end = ''; + + # Use the user version of the postamble if deinfed + if (defined $self->UserPostamble) { + $end = $self->UserPostamble; + + $self->_output($end); + + } elsif ($self->AddPostamble) { + + # Check for index + my $makeindex = '\printindex'; + + $makeindex = '%% '. $makeindex unless $self->MakeIndex; + + $end = "$makeindex\n\n\\end{document}\n"; + } + + + $self->_output($end); + +} + +=item B<command> + +Process basic pod commands. + +=cut + +sub command { + my $self = shift; + my ($command, $paragraph, $line_num, $parobj) = @_; + + # return if we dont care + return if $command eq 'pod'; + + $paragraph = $self->_replace_special_chars($paragraph); + + # Interpolate pod sequences in paragraph + $paragraph = $self->interpolate($paragraph, $line_num); + + $paragraph =~ s/\s+$//; + + # Now run the command + if ($command eq 'over') { + + $self->begin_list($paragraph, $line_num); + + } elsif ($command eq 'item') { + + $self->add_item($paragraph, $line_num); + + } elsif ($command eq 'back') { + + $self->end_list($line_num); + + } elsif ($command eq 'head1') { + + # Store the name of the section + $self->{_CURRENT_HEAD1} = $paragraph; + + # Print it + $self->head(1, $paragraph, $parobj); + + } elsif ($command eq 'head2') { + + $self->head(2, $paragraph, $parobj); + + } elsif ($command eq 'head3') { + + $self->head(3, $paragraph, $parobj); + + } elsif ($command eq 'head4') { + + $self->head(4, $paragraph, $parobj); + + } elsif ($command eq 'head5') { + + $self->head(5, $paragraph, $parobj); + + } elsif ($command eq 'head6') { + + $self->head(6, $paragraph, $parobj); + + } elsif ($command eq 'begin') { + + # pass through if latex + if ($paragraph =~ /^latex/i) { + # Make sure that subsequent paragraphs are not modfied before printing + $self->{_dont_modify_any_para} = 1; + + } else { + # Suppress all subsequent paragraphs unless + # it is explcitly intended for latex + $self->{_suppress_all_para} = 1; + } + + } elsif ($command eq 'for') { + + # pass through if latex + if ($paragraph =~ /^latex/i) { + # Make sure that next paragraph is not modfied before printing + $self->{_dont_modify_next_para} = 1; + + } else { + # Suppress the next paragraph unless it is latex + $self->{_suppress_next_para} = 1 + } + + } elsif ($command eq 'end') { + + # Reset suppression + $self->{_suppress_all_para} = 0; + $self->{_dont_modify_any_para} = 0; + + } elsif ($command eq 'pod') { + + # Do nothing + + } else { + carp "Command $command not recognised at line $line_num\n"; + } + +} + +=item B<verbatim> + +Verbatim text + +=cut + +sub verbatim { + my $self = shift; + my ($paragraph, $line_num, $parobj) = @_; + + # Expand paragraph unless in =for or =begin block + if ($self->{_dont_modify_any_para} || $self->{_dont_modify_next_para}) { + # Just print as is + $self->_output($paragraph); + + # Reset flag if in =for + $self->{_dont_modify_next_para} = 0; + + } else { + + return if $paragraph =~ /^\s+$/; + + # Clean trailing space + $paragraph =~ s/\s+$//; + + $self->_output('\begin{verbatim}' . "\n$paragraph\n". '\end{verbatim}'."\n"); + } +} + +=item B<textblock> + +Plain text paragraph. + +=cut + +sub textblock { + my $self = shift; + my ($paragraph, $line_num, $parobj) = @_; + + # print Dumper($self); + + # Expand paragraph unless in =for or =begin block + if ($self->{_dont_modify_any_para} || $self->{_dont_modify_next_para}) { + # Just print as is + $self->_output($paragraph); + + # Reset flag if in =for + $self->{_dont_modify_next_para} = 0; + + return; + } + + + # Escape latex special characters + $paragraph = $self->_replace_special_chars($paragraph); + + # Interpolate interior sequences + my $expansion = $self->interpolate($paragraph, $line_num); + $expansion =~ s/\s+$//; + + + # If we are replacing 'head1 NAME' with a section + # we need to look in the paragraph and rewrite things + # Need to make sure this is called only on the first paragraph + # following 'head1 NAME' and not on subsequent paragraphs that may be + # present. + if ($self->{_CURRENT_HEAD1} =~ /^NAME/i && $self->ReplaceNAMEwithSection()) { + + # Strip white space from start and end + $paragraph =~ s/^\s+//; + $paragraph =~ s/\s$//; + + # Split the string into 2 parts + my ($name, $purpose) = split(/\s+-\s+/, $expansion,2); + + # Now prevent this from triggering until a new head1 NAME is set + $self->{_CURRENT_HEAD1} = '_NAME'; + + # Might want to clear the Label() before doing this (CHECK) + + # Print the heading + $self->head(1, $name, $parobj); + + # Set the labeling in case we want unique names later + $self->Label( $self->_create_label( $name, 1 ) ); + + # Raise the Head1Level by one so that subsequent =head1 appear + # as subsections of the main name section unless we are already + # at maximum [Head1Level() could check this itself - CHECK] + $self->Head1Level( $self->Head1Level() + 1) + unless $self->Head1Level == $#LatexSections; + + # Now write out the new latex paragraph + $purpose = ucfirst($purpose); + $self->_output("\n\n$purpose\n\n"); + + } else { + # Just write the output + $self->_output("\n\n$expansion\n\n"); + } + +} + +=item B<interior_sequence> + +Interior sequence expansion + +=cut + +sub interior_sequence { + my $self = shift; + + my ($seq_command, $seq_argument, $pod_seq) = @_; + + if ($seq_command eq 'B') { + return "\\textbf{$seq_argument}"; + + } elsif ($seq_command eq 'I') { + return "\\textit{$seq_argument}"; + + } elsif ($seq_command eq 'E') { + + # If it is simply a number + if ($seq_argument =~ /^\d+$/) { + return chr($seq_argument); + # Look up escape in hash table + } elsif (exists $HTML_Escapes{$seq_argument}) { + return $HTML_Escapes{$seq_argument}; + + } else { + my ($file, $line) = $pod_seq->file_line(); + warn "Escape sequence $seq_argument not recognised at line $line of file $file\n"; + return; + } + + } elsif ($seq_command eq 'Z') { + + # Zero width space + return '$\!$'; # ' + + } elsif ($seq_command eq 'C') { + return "\\texttt{$seq_argument}"; + + } elsif ($seq_command eq 'F') { + return "\\emph{$seq_argument}"; + + } elsif ($seq_command eq 'S') { + # non breakable spaces + my $nbsp = '$\:$'; #' + + $seq_argument =~ s/\s/$nbsp/g; + return $seq_argument; + + } elsif ($seq_command eq 'L') { + + my $link = new Pod::Hyperlink($seq_argument); + + # undef on failure + unless (defined $link) { + carp $@; + return; + } + + # Handle internal links differently + my $type = $link->type; + my $page = $link->page; + + if ($type eq 'section' && $page eq '') { + # Use internal latex reference + my $node = $link->node; + + # Convert to a label + $node = $self->_create_label($node); + + return "\\S\\ref{$node}"; + + } else { + # Use default markup for external references + # (although Starlink would use \xlabel) + my $markup = $link->markup; + + my ($file, $line) = $pod_seq->file_line(); + + return $self->interpolate($link->markup, $line); + } + + + + } elsif ($seq_command eq 'P') { + # Special markup for Pod::Hyperlink + # Replace :: with / + my $link = $seq_argument; + $link =~ s/::/\//g; + + my $ref = "\\emph{$seq_argument}"; + return $ref; + + } elsif ($seq_command eq 'Q') { + # Special markup for Pod::Hyperlink + return "\\textsf{$seq_argument}\n"; + + } elsif ($seq_command eq 'X') { + # Index entries + + # use \index command + # I will let '!' go through for now + # not sure how sub categories are handled in X<> + my $index = $self->_create_index($seq_argument); + return "\\index{$index}\n"; + + } else { + carp "Unknown sequence $seq_command<$seq_argument>"; + } + +} + +=back + +=head2 List Methods + +Methods used to handle lists. + +=over 4 + +=item B<begin_list> + +Called when a new list is found (via the C<over> directive). +Creates a new C<Pod::List> object and stores it on the +list stack. + + $parser->begin_list($indent, $line_num); + +=cut + +sub begin_list { + my $self = shift; + my $indent = shift; + my $line_num = shift; + + # Indicate that a list should be started for the next item + # need to do this to work out the type of list + push ( @{$self->lists}, new Pod::List(-indent => $indent, + -start => $line_num, + -file => $self->input_file, + ) + ); + +} + +=item B<end_list> + +Called when the end of a list is found (the C<back> directive). +Pops the C<Pod::List> object off the stack of lists and writes +the C<latex> code required to close a list. + + $parser->end_list($line_num); + +=cut + +sub end_list { + my $self = shift; + my $line_num = shift; + + unless (defined $self->lists->[-1]) { + my $file = $self->input_file; + warn "No list is active at line $line_num (file=$file). Missing =over?\n"; + return; + } + + # What to write depends on list type + my $type = $self->lists->[-1]->type; + + # Dont write anything if the list type is not set + # iomplying that a list was created but no entries were + # placed in it (eg because of a =begin/=end combination) + $self->_output("\\end{$type}\n") + if (defined $type && length($type) > 0); + + # Clear list + pop(@{ $self->lists}); + +} + +=item B<add_item> + +Add items to the list. The first time an item is encountered +(determined from the state of the current C<Pod::List> object) +the type of list is determined (ordered, unnumbered or description) +and the relevant latex code issued. + + $parser->add_item($paragraph, $line_num); + +=cut + +sub add_item { + my $self = shift; + my $paragraph = shift; + my $line_num = shift; + + unless (defined $self->lists->[-1]) { + my $file = $self->input_file; + warn "List has already ended by line $line_num of file $file. Missing =over?\n"; + # Replace special chars +# $paragraph = $self->_replace_special_chars($paragraph); + $self->_output("$paragraph\n\n"); + return; + } + + # If paragraphs printing is turned off via =begin/=end or whatver + # simply return immediately + return if ($self->{_suppress_all_para} || $self->{_suppress_next_para}); + + # Check to see whether we are starting a new lists + if (scalar($self->lists->[-1]->item) == 0) { + + # Examine the paragraph to determine what type of list + # we have + $paragraph =~ s/\s+$//; + $paragraph =~ s/^\s+//; + + my $type; + if ($paragraph eq '*') { + $type = 'itemize'; + } elsif ($paragraph =~ /^\d/) { + $type = 'enumerate'; + } else { + $type = 'description'; + } + $self->lists->[-1]->type($type); + + $self->_output("\\begin{$type}\n"); + + } + + my $type = $self->lists->[-1]->type; + + if ($type eq 'description') { + + $self->_output("\\item[$paragraph] \\mbox{}"); + } else { + $self->_output('\item '); + } + + # Store the item name in the object. Required so that + # we can tell if the list is new or not + $self->lists->[-1]->item($paragraph); + +} + +=back + +=head2 Methods for headings + +=over 4 + +=item B<head> + +Print a heading of the required level. + + $parser->head($level, $paragraph, $parobj); + +The first argument is the pod heading level. The second argument +is the contents of the heading. The 3rd argument is a Pod::Paragraph +object so that the line number can be extracted. + +=cut + +sub head { + my $self = shift; + my $num = shift; + my $paragraph = shift; + my $parobj = shift; + + # If we are replace 'head1 NAME' with a section + # we return immediately if we get it + return + if ($self->{_CURRENT_HEAD1} =~ /^NAME/i && $self->ReplaceNAMEwithSection()); + + # Create a label + my $label = $self->_create_label($paragraph); + + # Create an index entry + my $index = $self->_create_index($paragraph); + + # Work out position in the above array taking into account + # that =head1 is equivalent to $self->Head1Level + + my $level = $self->Head1Level() - 1 + $num; + + # Warn if heading to large + if ($num > $#LatexSections) { + my $line = $parobj->file_line; + my $file = $self->input_file; + warn "Heading level too large ($level) for LaTeX at line $line of file $file\n"; + $level = $#LatexSections; + } + + # Check to see whether section should be unnumbered + my $star = ($level >= $self->LevelNoNum ? '*' : ''); + + # Section + $self->_output("\\" .$LatexSections[$level] .$star ."{$paragraph\\label{".$label ."}\\index{".$index."}}"); + +} + + +=back + +=end __PRIVATE__ + +=begin __PRIVATE__ + +=head2 Internal methods + +Internal routines are described in this section. They do not form part of the +public interface. All private methods start with an underscore. + +=over 4 + +=item B<_output> + +Output text to the output filehandle. This method must be always be called +to output parsed text. + + $parser->_output($text); + +Does not write anything if a =begin or =for is active that should be +ignored. + +=cut + +sub _output { + my $self = shift; + my $text = shift; + + print { $self->output_handle } $text + unless $self->{_suppress_all_para} || + $self->{_suppress_next_para}; + + # Reset pargraph stuff for =for + $self->{_suppress_next_para} = 0 + if $self->{_suppress_next_para}; +} + + +=item B<_replace_special_chars> + +Subroutine to replace characters that are special in C<latex> +with the escaped forms + + $escaped = $parser->_replace_special_chars($paragraph); + +Need to call this routine before interior_sequences are munged but +not if verbatim. + +Special characters and the C<latex> equivalents are: + + } \} + { \{ + _ \_ + $ \$ + % \% + & \& + \ $\backslash$ + ^ \^{} + +=cut + +sub _replace_special_chars { + my $self = shift; + my $paragraph = shift; + + # Replace a \ with $\backslash$ + # This is made more complicated because the dollars will be escaped + # by the subsequent replacement. Easiest to add \backslash + # now and then add the dollars + $paragraph =~ s/\\/\\backslash/g; + + # Must be done after escape of \ since this command adds latex escapes + # Replace characters that can be escaped + $paragraph =~ s/([\$\#&%_{}])/\\$1/g; + + # Replace ^ characters with \^{} so that $^F works okay + $paragraph =~ s/(\^)/\\$1\{\}/g; + + # Now add the dollars around each \backslash + $paragraph =~ s/(\\backslash)/\$$1\$/g; + + return $paragraph; +} + + +=item B<_create_label> + +Return a string that can be used as an internal reference +in a C<latex> document (i.e. accepted by the C<\label> command) + + $label = $parser->_create_label($string) + +If UniqueLabels is true returns a label prefixed by Label() +This can be suppressed with an optional second argument. + + $label = $parser->_create_label($string, $suppress); + +If a second argument is supplied (of any value including undef) +the Label() is never prefixed. This means that this routine can +be called to create a Label() without prefixing a previous setting. + +=cut + +sub _create_label { + my $self = shift; + my $paragraph = shift; + my $suppress = (@_ ? 1 : 0 ); + + # Remove latex commands + $paragraph = $self->_clean_latex_commands($paragraph); + + # Remove non alphanumerics from the label and replace with underscores + # want to protect '-' though so use negated character classes + $paragraph =~ s/[^-:\w]/_/g; + + # Multiple underscores will look unsightly so remove repeats + # This will also have the advantage of tidying up the end and + # start of string + $paragraph =~ s/_+/_/g; + + # If required need to make sure that the label is unique + # since it is possible to have multiple pods in a single + # document + if (!$suppress && $self->UniqueLabels() && defined $self->Label) { + $paragraph = $self->Label() .'_'. $paragraph; + } + + return $paragraph; +} + + +=item B<_create_index> + +Similar to C<_create_label> except an index entry is created. +If C<UniqueLabels> is true, the index entry is prefixed by +the current C<Label> and an exclamation mark. + + $ind = $parser->_create_index($paragraph); + +An exclamation mark is used by C<makeindex> to generate +sub-entries in an index. + +=cut + +sub _create_index { + my $self = shift; + my $paragraph = shift; + my $suppress = (@_ ? 1 : 0 ); + + # Remove latex commands + $paragraph = $self->_clean_latex_commands($paragraph); + + # If required need to make sure that the index entry is unique + # since it is possible to have multiple pods in a single + # document + if (!$suppress && $self->UniqueLabels() && defined $self->Label) { + $paragraph = $self->Label() .'!'. $paragraph; + } + + # Need to replace _ with space + $paragraph =~ s/_/ /g; + + return $paragraph; + +} + +=item B<_clean_latex_commands> + +Removes latex commands from text. The latex command is assumed to be of the +form C<\command{ text }>. "C<text>" is retained + + $clean = $parser->_clean_latex_commands($text); + +=cut + +sub _clean_latex_commands { + my $self = shift; + my $paragraph = shift; + + # Remove latex commands of the form \text{ } + # and replace with the contents of the { } + # need to make this non-greedy so that it can handle + # "\text{a} and \text2{b}" + # without converting it to + # "a} and \text2{b" + # This match will still get into trouble if \} is present + # This is not vital since the subsequent replacement of non-alphanumeric + # characters will tidy it up anyway + $paragraph =~ s/\\\w+{(.*?)}/$1/g; + + return $paragraph +} + +=back + +=end __PRIVATE__ + +=head1 NOTES + +Compatible with C<latex2e> only. Can not be used with C<latex> v2.09 +or earlier. + +A subclass of C<Pod::Select> so that specific pod sections can be +converted to C<latex> by using the C<select> method. + +Some HTML escapes are missing and many have not been tested. + +=head1 SEE ALSO + +L<Pod::Parser>, L<Pod::Select>, L<pod2latex> + +=head1 AUTHORS + +Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> + +=head1 COPYRIGHT + +Copyright (C) 2000 Tim Jenness. All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=begin __PRIVATE__ + +=head1 REVISION + +$Id: LaTeX.pm,v 1.4 2000/05/16 01:26:55 timj Exp $ + +=end __PRIVATE__ + +=cut diff --git a/pod/pod2latex.PL b/pod/pod2latex.PL index 71115f3f21..3d3cfb65bc 100644 --- a/pod/pod2latex.PL +++ b/pod/pod2latex.PL @@ -34,676 +34,314 @@ $Config{startperl} # In the following, perl variables are not expanded during extraction. print OUT <<'!NO!SUBS!'; -# -# pod2latex, version 1.1 -# by Taro Kawagish (kawagish@imslab.co.jp), Jan 11, 1995. -# -# pod2latex filters Perl pod documents to LaTeX documents. -# -# What pod2latex does: -# 1. Pod file 'perl_doc_entry.pod' is filtered to 'perl_doc_entry.tex'. -# 2. Indented paragraphs are translated into -# '\begin{verbatim} ... \end{verbatim}'. -# 3. '=head1 heading' command is translated into '\section{heading}' -# 4. '=head2 heading' command is translated into '\subsection*{heading}' -# 5. '=over N' command is translated into -# '\begin{itemize}' if following =item starts with *, -# '\begin{enumerate}' if following =item starts with 1., -# '\begin{description}' if else. -# (indentation level N is ignored.) -# 6. '=item * heading' command is translated into '\item heading', -# '=item 1. heading' command is translated into '\item heading', -# '=item heading' command(other) is translated into '\item[heading]'. -# 7. '=back' command is translated into -# '\end{itemize}' if started with '\begin{itemize}', -# '\end{enumerate}' if started with '\begin{enumerate}', -# '\end{description}' if started with '\begin{description}'. -# 8. other paragraphs are translated into strings with TeX special characters -# escaped. -# 9. In heading text, and other paragraphs, the following translation of pod -# quotes are done, and then TeX special characters are escaped after that. -# I<text> to {\em text\/}, -# B<text> to {\bf text}, -# S<text> to text1, -# where text1 is a string with blank characters replaced with ~, -# C<text> to {\tt text2}, -# where text2 is a string with TeX special characters escaped to -# obtain a literal printout, -# E<text> (HTML escape) to TeX escaped string, -# L<text> to referencing string as is done by pod2man, -# F<file> to {\em file\/}, -# Z<> to a null string, -# 10. those headings are indexed: -# '=head1 heading' => \section{heading}\index{heading} -# '=head2 heading' => \subsection*{heading}\index{heading} -# only when heading does not match frequent patterns such as -# DESCRIPTION, DIAGNOSTICS,... -# '=item heading' => \item{heading}\index{heading} -# -# Usage: -# pod2latex perl_doc_entry.pod -# this will write to a file 'perl_doc_entry.tex'. -# -# To LaTeX: -# The following commands need to be defined in the preamble of the LaTeX -# document: -# \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} -# \def\underscore{\leavevmode\kern.04em\vbox{\hrule width 0.4em height 0.3pt}} -# and \parindent should be set zero: -# \setlength{\parindent}{0pt} -# -# Note: -# This script was written modifing pod2man. -# -# Bug: -# If HTML escapes E<text> other than E<amp>,E<lt>,E<gt>,E<quot> are used -# in C<>, translation will produce wrong character strings. -# Translation of HTML escapes of various European accents might be wrong. - - -# TeX special characters. -##$tt_ables = "!@*()-=+|;:'\"`,./?<>"; -$backslash_escapables = "#\$%&{}_"; -$backslash_escapables2 = "#\$%&{}"; # except _ -##$nonverbables = "^\\~"; -##$bracketesc = "[]"; -##@tex_verb_fences = unpack("aaaaaaaaa","|#@!*+?:;"); - -@head1_freq_patterns # =head1 patterns which need not be index'ed - = ("AUTHOR","Author","BUGS","DATE","DESCRIPTION","DIAGNOSTICS", - "ENVIRONMENT","EXAMPLES","FILES","INTRODUCTION","NAME","NOTE", - "SEE ALSO","SYNOPSIS","WARNING"); - -$indent = 0; - -# parse the pods, produce LaTeX. - -use Pod::Plainer; -open(POD,"-|") or Pod::Plainer -> new() -> parse_from_file($ARGV[0]), exit; - -($pod=$ARGV[0]) =~ s/\.pod$//; -open(LATEX,">$pod.tex"); -&do_hdr(); - -$cutting = 1; -$begun = ""; -$/ = ""; # record separator is blank lines -while (<POD>) { - if ($cutting) { - next unless /^=/; - $cutting = 0; - } - if ($begun) { - if (/^=end\s+$begun/) { - $begun = ""; - } - elsif ($begun =~ /^(tex|latex)$/) { - print LATEX $_; - } - next; - } - chop; - length || (print LATEX "\n") && next; - - # translate indented lines as a verabatim paragraph - if (/^\s/) { - @lines = split(/\n/); - print LATEX "\\begin{verbatim}\n"; - for (@lines) { - 1 while s - {^( [^\t]* ) \t ( \t* ) } - { $1 . ' ' x (8 - (length($1)%8) + 8*(length($2))) }ex; - print LATEX $_,"\n"; - } - print LATEX "\\end{verbatim}\n"; - next; - } - if (/^=for\s+(\S+)\s*/s) { - if ($1 eq "tex" or $1 eq "latex") { - print LATEX $',"\n"; - } else { - # ignore unknown for - } - next; - } - elsif (/^=begin\s+(\S+)\s*/s) { - $begun = $1; - if ($1 eq "tex" or $1 eq "latex") { - print LATEX $'."\n"; - } - next; - } +# pod2latex conversion program + +use Pod::LaTeX; +use Pod::Find qw/ pod_find /; +use Pod::Usage; +use Getopt::Long; +use File::Basename; + +# Read command line arguments + +my %options = ( + "help" => 0, + "man" => 0, + "sections" => [], + "full" => 0, + "out" => undef, + "verbose" => 0, + "modify" => 0, + ); + +GetOptions(\%options, + "help", + "man", + "verbose", + "full", + "sections=s@", + "out=s", + "modify", + ) || pod2usage(2); + +pod2usage(1) if ($options{help}); +pod2usage(-verbose => 2) if ($options{man}); + + +# Read all the files from the command line +my @files = @ARGV; + +# Now find which ones are real pods and convert +# directories to their contents. + +# Extract the pods from each arg since some of them might +# be directories +# This is not as efficient as using pod_find to search through +# everything at once but it allows us to preserve the order +# supplied by the user + +my @pods; +foreach my $arg (@files) { + my %pods = pod_find($arg); + push(@pods, sort keys %pods); +} - # preserve '=item' line with pod quotes as they are. - if (/^=item/) { - ($bareitem = $_) =~ s/^=item\s*//; - } +# Abort if nothing to do +if ($#pods == -1) { + warn "None of the supplied Pod files actually exist\n"; + exit; +} - # check for things that'll hosed our noremap scheme; affects $_ - &init_noremap(); - - # expand strings "func()" as pod quotes. - if (!/^=item/) { - # first hide pod escapes. - # escaped strings are mapped into the ones with the MSB's on. - s/([A-Z]<[^<>]*>)/noremap($1)/ge; - - # func() is a reference to a perl function - s{\b([:\w]+\(\))}{I<$1>}g; - # func(n) is a reference to a man page - s{(\w+)(\([^\s,\051]+\))}{I<$1>$2}g; - # convert simple variable references -# s/([\$\@%][\w:]+)/C<$1>/g; -# s/\$[\w:]+\[[0-9]+\]/C<$&>/g; - - if (m{ ([\-\w]+\([^\051]*?[\@\$,][^\051]*?\)) - }x && $` !~ /([LCI]<[^<>]*|-)$/ && !/^=\w/) - { - warn "``$1'' should be a [LCI]<$1> ref"; - } - while (/(-[a-zA-Z])\b/g && $` !~ /[\w\-]$/) { - warn "``$1'' should be [CB]<$1> ref"; - } - - # put back pod quotes so we get the inside of <> processed; - $_ = &clear_noremap($_); - } - # process TeX special characters - - # First hide HTML quotes E<> since they can be included in C<>. - s/(E<[^<>]+>)/noremap($1)/ge; - - # Then hide C<> type literal quotes. - # String inside of C<> will later be expanded into {\tt ..} strings - # with TeX special characters escaped as needed. - s/(C<[^<>]*>)/&noremap($1)/ge; - - # Next escape TeX special characters including other pod quotes B< >,... - # - # NOTE: s/re/&func($str)/e evaluates $str just once in perl5. - # (in perl4 evaluation takes place twice before getting passed to func().) - - # - hyphen => --- - s/(\S+)(\s+)-+(\s+)(\S+)/"$1".&noremap(" --- ")."$4"/ge; - # '-', '--', "-" => '{\tt -}', '{\tt --}', "{\tt -}" -## s/("|')(\s*)(-+)(\s*)\1/&noremap("$1$2\{\\tt $3\}$4$1")/ge; -## changed Wed Jan 25 15:26:39 JST 1995 - # '-', '--', "-" => '$-$', '$--$', "$-$" - s/(\s+)(['"])(-+)([^'"\-]*)\2(\s+|[,.])/"$1$2".&noremap("\$$3\$")."$4$2$5"/ge; - s/(\s+)(['"])([^'"\-]*)(-+)(\s*)\2(\s+|[,.])/"$1$2$3".&noremap("\$$4\$")."$5$2$6"/ge; - # (--|-) => ($--$|$-$) - s/(\s+)\((-+)([=@%\$\+\\\|\w]*)(-*)([=@%\$\+\\\|\w]*)\)(\s+|[,.])/"$1\(".&noremap("\$$2\$")."$3".&noremap("\$$4\$")."$5\)$6"/ge; - # numeral - => $-$ - s/(\(|[0-9]+|\s+)-(\s*\(?\s*[0-9]+)/&noremap("$1\$-\$$2")/ge; - # -- in quotes => two separate - - s/B<([^<>]*)--([^<>]*)>/&noremap("B<$1\{\\tt --\}$2>")/ge; - - # backslash escapable characters except _. - s/([$backslash_escapables2])/&noremap("\\$1")/ge; - s/_/&noremap("\\underscore{}")/ge; # a litle thicker than \_. - # quote TeX special characters |, ^, ~, \. - s/\|/&noremap("\$|\$")/ge; - s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge; - s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge; - s/\\/&noremap("\$\\backslash{}\$")/ge; - # quote [ and ] to be used in \item[] - s/([\[\]])/&noremap("{\\tt $1}")/ge; - # characters need to be treated differently in TeX - # keep * if an item heading - s/^(=item[ \t]+)[*]((.|\n)*)/"$1" . &noremap("*") . "$2"/ge; - s/[*]/&noremap("\$\\ast\$")/ge; # other * - - # hide other pod quotes. - s/([ABD-Z]<[^<>]*>)/&noremap($1)/ge; - - # escape < and > as math strings, - # now that we are done with hiding pod <> quotes. - s/</&noremap("\$<\$")/ge; - s/>/&noremap("\$>\$")/ge; - - # put it back so we get the <> processed again; - $_ = &clear_noremap($_); - - - # Expand pod quotes recursively: - # (1) type face directives [BIFS]<[^<>]*> to appropriate TeX commands, - # (2) L<[^<>]*> to reference strings, - # (3) C<[^<>]*> to TeX literal quotes, - # (4) HTML quotes E<> inside of C<> quotes. - - # Hide E<> again since they can be included in C<>. - s/(E<[^<>]+>)/noremap($1)/ge; - - $maxnest = 10; - while ($maxnest-- && /[A-Z]</) { - - # bold and italic quotes - s/B<([^<>]*)>/"{\\bf $1}"/eg; - s#I<([^<>]*)>#"{\\em $1\\/}"#eg; - - # files and filelike refs in italics - s#F<([^<>]*)>#"{\\em $1\\/}"#eg; - - # no break quote -- usually we want C<> for this - s/S<([^<>]*)>/&nobreak($1)/eg; - - # LREF: a manpage(3f) - s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))?>:the {\\em $1\\/}$2 manpage:g; - - # LREF: an =item on another manpage - s{ - L<([^/]+)/([:\w]+(\(\))?)> - } {the C<$2> entry in the I<$1> manpage}gx; - - # LREF: an =item on this manpage - s{ - ((?:L</([:\w]+(\(\))?)> - (,?\s+(and\s+)?)?)+) - } { &internal_lrefs($1) }gex; - - # LREF: a =head2 (head1?), maybe on a manpage, maybe right here - # the "func" can disambiguate - s{ - L<(?:([a-zA-Z]\S+?) /)?"?(.*?)"?> - }{ - do { - $1 # if no $1, assume it means on this page. - ? "the section on I<$2> in the I<$1> manpage" - : "the section on I<$2>" - } - }gex; - - s/X<([^<>]*)>/\\index{$1}/g; - - s/Z<>/\\&/g; # the "don't format me" thing - - # comes last because not subject to reprocessing - s{ - C<([^<>]*)> - }{ - do { - ($str = $1) =~ tr/\200-\377/\000-\177/; #normalize hidden stuff - # expand HTML escapes if any; - # WARNING: if HTML escapes other than E<amp>,E<lt>,E<gt>, - # E<quot> are in C<>, they will not be printed correctly. - $str = &expand_HTML_escapes($str); - $strverb = &alltt($str); # Tex verbatim escape of a string. - &noremap("$strverb"); - } - }gex; - -# if ( /C<([^<>]*)/ ) { -# $str = $1; -# if ($str !~ /\|/) { # if includes | -# s/C<([^<>]*)>/&noremap("\\verb|$str|")/eg; -# } else { -# print STDERR "found \| in C<.*> at paragraph $.\n"; -# # find a character not contained in $str to use it as a -# # separator of the \verb -# ($chars = $str) =~ s/(\W)/\\$1/g; -# ## ($chars = $str) =~ s/([\$<>,\|"'\-^{}()*+?\\])/\\$1/g; -# @fence = grep(!/[ $chars]/,@tex_verb_fences); -# s/C<([^<>]*)>/&noremap("\\verb$fence[0]$str$fence[0]")/eg; -# } -# } - } +# If $options{'out'} is set we are processing to a single output file +my $multi_documents; +if (exists $options{'out'} && defined $options{'out'}) { + $multi_documents = 0; +} else { + $multi_documents = 1; +} + +# If the output file is not specified it is assumed that +# a single output file is required per input file using +# a .tex extension rather than any exisiting extension + +if ($multi_documents) { + + # Case where we just generate one input per output + + foreach my $pod (@pods) { + + if (-f $pod) { + + my $output = $pod; + $output = basename($output, '.pm', '.pod','.pl') . '.tex'; + # Create a new parser object + my $parser = new Pod::LaTeX( + AddPreamble => $options{'full'}, + AddPostamble => $options{'full'}, + MakeIndex => $options{'full'}, + TableOfContents => $options{'full'}, + ReplaceNAMEwithSection => $options{'modify'}, + UniqueLabels => $options{'modify'}, + ); - # process each pod command - if (s/^=//) { # if a command - s/\n/ /g; - ($cmd, $rest) = split(' ', $_, 2); - $rest =~ s/^\s*//; - $rest =~ s/\s*$//; - - if (defined $rest) { - &escapes; - } - - $rest = &clear_noremap($rest); - $rest = &expand_HTML_escapes($rest); - - if ($cmd eq 'cut') { - $cutting = 1; - $lastcmd = 'cut'; - } - elsif ($cmd eq 'head1') { # heading type 1 - $rest =~ s/^\s*//; $rest =~ s/\s*$//; - print LATEX "\n\\subsection*{$rest}"; - # put index entry - ($index = $rest) =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The' - # index only those heads not matching the frequent patterns. - foreach $pat (@head1_freq_patterns) { - if ($index =~ /^$pat/) { - goto freqpatt; - } - } - print LATEX "%\n\\index{$index}\n" if ($index); - freqpatt: - $lastcmd = 'head1'; - } - elsif ($cmd eq 'head2') { # heading type 2 - $rest =~ s/^\s*//; $rest =~ s/\s*$//; - print LATEX "\n\\subsubsection*{$rest}"; - # put index entry - ($index = $rest) =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The' - $index =~ s/^Example\s*[1-9][0-9]*\s*:\s*//; # remove 'Example :' - print LATEX "%\n\\index{$index}\n" if ($index); - $lastcmd = 'head2'; - } - elsif ($cmd eq 'over') { # 1 level within a listing environment - push(@indent,$indent); - $indent = $rest + 0; - $lastcmd = 'over'; - } - elsif ($cmd eq 'back') { # 1 level out of a listing environment - $indent = pop(@indent); - warn "Unmatched =back\n" unless defined $indent; - $listingcmd = pop(@listingcmd); - print LATEX "\n\\end{$listingcmd}\n" if ($listingcmd); - $lastcmd = 'back'; - } - elsif ($cmd eq 'item') { # an item paragraph starts - if ($lastcmd eq 'over') { # if we have just entered listing env - # see what type of list environment we are in. - if ($rest =~ /^[0-9]\.?/) { # if numeral heading - $listingcmd = 'enumerate'; - } elsif ($rest =~ /^\*\s*/) { # if * heading - $listingcmd = 'itemize'; - } elsif ($rest =~ /^[^*]/) { # if other headings - $listingcmd = 'description'; - } else { - warn "unknown list type for item $rest"; - } - print LATEX "\n\\begin{$listingcmd}\n"; - push(@listingcmd,$listingcmd); - } elsif ( !@listingcmd ) { - warn "Illegal '=item' command without preceding 'over':"; - warn "=item $bareitem"; - } - - if ($listingcmd eq 'enumerate') { - $rest =~ s/^[0-9]+\.?\s*//; # remove numeral heading - print LATEX "\n\\item"; - print LATEX "{\\bf $rest}" if $rest; - } elsif ($listingcmd eq 'itemize') { - $rest =~ s/^\*\s*//; # remove * heading - print LATEX "\n\\item"; - print LATEX "{\\bf $rest}" if $rest; - } else { # description item - print LATEX "\n\\item[$rest]"; - } - $lastcmd = 'item'; - $rightafter_item = 'yes'; - - # check if the item heading is short or long. - ($itemhead = $rest) =~ s/{\\bf (\S*)}/$1/g; - if (length($itemhead) < 4) { - $itemshort = "yes"; - } else { - $itemshort = "no"; - } - # write index entry - if ($pod =~ "perldiag") { # skip 'perldiag.pod' - goto noindex; - } - # strip out the item of pod quotes and get a plain text entry - $bareitem =~ s/\n/ /g; # remove newlines - $bareitem =~ s/\s*$//; # remove trailing space - $bareitem =~ s/[A-Z]<([^<>]*)>/$1/g; # remove <> quotes - ($index = $bareitem) =~ s/^\*\s+//; # remove leading '*' - $index =~ s/^(An?\s+|The\s+)//i; # remove 'A' and 'The' - $index =~ s/^\s*[1-9][0-9]*\s*[.]\s*$//; # remove numeral only - $index =~ s/^\s*\w\s*$//; # remove 1 char only's - # quote ", @ and ! with " to be used in makeindex. - $index =~ s/"/""/g; # quote " - $index =~ s/@/"@/g; # quote @ - $index =~ s/!/"!/g; # quote ! - ($rest2=$rest) =~ s/^\*\s+//; # remove * - $rest2 =~ s/"/""/g; # quote " - $rest2 =~ s/@/"@/g; # quote @ - $rest2 =~ s/!/"!/g; # quote ! - if ($pod =~ "(perlfunc|perlvar)") { # when doc is perlfunc,perlvar - # take only the 1st word of item heading - $index =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/; - $rest2 =~ s/^([^{}\s]*)({.*})?([^{}\s]*)\s+.*/\1\2\3/; - } - if ($index =~ /[A-Za-z\$@%]/) { - # write \index{plain_text_entry@TeX_string_entry} - print LATEX "%\n\\index{$index\@$rest2}%\n"; - } - noindex: - ; - } - elsif ($cmd eq 'pod') { - ; # recognise the pod directive, as no op (hs) - } - elsif ($cmd eq 'pod') { - ; # recognise the pod directive, as no op (hs) - } - else { - warn "Unrecognized directive: $cmd\n"; - } + # Select sections if supplied + $parser->select(@{ $options{'sections'}}) + if @{$options{'sections'}}; + + # Derive the input file from the output file + $parser->parse_from_file($pod, $output); + + print "Written output to $output\n" if $options{'verbose'}; + + } else { + warn "File $pod not found\n"; } - else { # if not command - &escapes; - $_ = &clear_noremap($_); - $_ = &expand_HTML_escapes($_); - - # if the present paragraphs follows an =item declaration, - # put a line break. - if ($lastcmd eq 'item' && - $rightafter_item eq 'yes' && $itemshort eq "no") { - print LATEX "\\hfil\\\\"; - $rightafter_item = 'no'; - } - print LATEX "\n",$_; + + } +} else { + + # Case where we want everything to be in a single document + + # Need to open the output file ourselves + my $output = $options{'out'}; + $output .= '.tex' unless $output =~ /\.tex$/; + + # Use auto-vivified file handle in perl 5.6 + use Symbol; + my $outfh = gensym; + open ($outfh, ">$output") || die "Could not open output file: $!\n"; + + # Flag to indicate whether we have converted at least one file + # indicates how many files have been converted + my $converted = 0; + + # Loop over the input files + foreach my $pod (@pods) { + + if (-f $pod) { + + warn "Converting $pod\n" if $options{'verbose'}; + + # Open the file (need the handle) + # Use auto-vivified handle in perl 5.6 + my $podfh = gensym; + open ($podfh, "<$pod") || die "Could not open pod file $pod: $!\n"; + + # if this is the first file to be converted we may want to add + # a preamble (controlled by command line option) + if ($converted == 0 && $options{'full'}) { + $preamble = 1; + } else { + $preamble = 0; + } + + # if this is the last file to be converted may want to add + # a postamble (controlled by command line option) + # relies on a previous pass to check existence of all pods we + # are converting. + my $postamble = ( ($converted == $#pods && $options{'full'}) ? 1 : 0 ); + + # Open parser object + # May want to start with a preamble for the first one and + # end with an index for the last + my $parser = new Pod::LaTeX( + MakeIndex => $options{'full'}, + TableOfContents => $preamble, + ReplaceNAMEwithSection => $options{'modify'}, + UniqueLabels => $options{'modify'}, + StartWithNewPage => $options{'full'}, + AddPreamble => $preamble, + AddPostamble => $postamble, + ); + + # Store the file name for error messages + # This is a kluge that breaks the data hiding of the object + $parser->{_INFILE} = $pod; + + # Select sections if supplied + $parser->select(@{ $options{'sections'}}) + if @{$options{'sections'}}; + + # Parse it + $parser->parse_from_filehandle($podfh, $outfh); + + # We have converted at least one file + $converted++; + + } else { + warn "File $pod not found\n"; } -} -print LATEX "\n"; -close(POD); -close(LATEX); + } + # Should unlink the file if we didn't convert anything! + # dont check for return status of unlink + # since there is not a lot to be done if the unlink failed + # and the program does not rely upon it. + unlink "$output" unless $converted; -######################################################################### + # If verbose + warn "Converted $converted files\n" if $options{'verbose'}; -sub do_hdr { - print LATEX "% LaTeX document produced by pod2latex from \"$pod.pod\".\n"; - print LATEX "% The followings need be defined in the preamble of this document:\n"; - print LATEX "%\\def\\C++{{\\rm C\\kern-.05em\\raise.3ex\\hbox{\\footnotesize ++}}}\n"; - print LATEX "%\\def\\underscore{\\leavevmode\\kern.04em\\vbox{\\hrule width 0.4em height 0.3pt}}\n"; - print LATEX "%\\setlength{\\parindent}{0pt}\n"; - print LATEX "\n"; - $podq = &escape_tex_specials("\U$pod\E"); - print LATEX "\\section{$podq}%\n"; - print LATEX "\\index{$podq}"; - print LATEX "\n"; } -sub nobreak { - my $string = shift; - $string =~ s/ +/~/g; # TeX no line break - $string; -} +exit; -sub noremap { - local($thing_to_hide) = shift; - $thing_to_hide =~ tr/\000-\177/\200-\377/; - return $thing_to_hide; -} +__END__ -sub init_noremap { - # escape high bit characters in input stream - s/([\200-\377])/"E<".ord($1).">"/ge; -} +=head1 NAME -sub clear_noremap { - local($tmp) = shift; - $tmp =~ tr/\200-\377/\000-\177/; - return $tmp; -} +pod2latex - convert pod documentation to latex format -sub expand_HTML_escapes { - local($s) = $_[0]; - $s =~ s { E<((\d+)|([A-Za-z]+))> } - { - do { - defined($2) - ? do { chr($2) } - : - exists $HTML_Escapes{$3} - ? do { $HTML_Escapes{$3} } - : do { - warn "Unknown escape: $& in $_"; - "E<$1>"; - } - } - }egx; - return $s; -} +=head1 SYNOPSIS -sub escapes { - # make C++ into \C++, which is to be defined as - # \def\C++{{\rm C\kern-.05em\raise.3ex\hbox{\footnotesize ++}}} - s/\bC\+\+/\\C++{}/g; -} + pod2latex *.pm -# Translate a string into a TeX \tt string to obtain a verbatim print out. -# TeX special characters are escaped by \. -# This can be used inside of LaTeX command arguments. -# We don't use LaTeX \verb since it doesn't work inside of command arguments. -sub alltt { - local($str) = shift; - # other chars than #,\,$,%,&,{,},_,\,^,~ ([ and ] included). - $str =~ s/([^${backslash_escapables}\\\^\~]+)/&noremap("$&")/eg; - # chars #,\,$,%,&,{,} => \# , ... - $str =~ s/([$backslash_escapables2])/&noremap("\\$&")/eg; - # chars _,\,^,~ => \char`\_ , ... - $str =~ s/_/&noremap("\\char`\\_")/eg; - $str =~ s/\\/&noremap("\\char`\\\\")/ge; - $str =~ s/\^/\\char`\\^/g; - $str =~ s/\~/\\char`\\~/g; - - $str =~ tr/\200-\377/\000-\177/; # put back - $str = "{\\tt ".$str."}"; # make it a \tt string - return $str; -} + pod2latex -out mytex.tex *.pod -sub escape_tex_specials { - local($str) = shift; - # other chars than #,\,$,%,&,{,}, _,\,^,~ ([ and ] included). - # backslash escapable characters #,\,$,%,&,{,} except _. - $str =~ s/([$backslash_escapables2])/&noremap("\\$1")/ge; - $str =~ s/_/&noremap("\\underscore{}")/ge; # \_ is too thin. - # quote TeX special characters |, ^, ~, \. - $str =~ s/\|/&noremap("\$|\$")/ge; - $str =~ s/\^/&noremap("\$\\hat{\\hspace{0.4em}}\$")/ge; - $str =~ s/\~/&noremap("\$\\tilde{\\hspace{0.4em}}\$")/ge; - $str =~ s/\\/&noremap("\$\\backslash{}\$")/ge; - # characters need to be treated differently in TeX - # * - $str =~ s/[*]/&noremap("\$\\ast\$")/ge; - # escape < and > as math string, - $str =~ s/</&noremap("\$<\$")/ge; - $str =~ s/>/&noremap("\$>\$")/ge; - $str =~ tr/\200-\377/\000-\177/; # put back - return $str; -} + pod2latex -full -sections 'DESCRIPTION|NAME' SomeDir -sub internal_lrefs { - local($_) = shift; - - s{L</([^>]+)>}{$1}g; - my(@items) = split( /(?:,?\s+(?:and\s+)?)/ ); - my $retstr = "the "; - my $i; - for ($i = 0; $i <= $#items; $i++) { - $retstr .= "C<$items[$i]>"; - $retstr .= ", " if @items > 2 && $i != $#items; - $retstr .= " and " if $i+2 == @items; - } - $retstr .= " entr" . ( @items > 1 ? "ies" : "y" ) - . " elsewhere in this document"; +=head1 DESCRIPTION - return $retstr; -} +C<pod2latex> is a program to convert POD format documentation +(L<perlpod>) into latex. It can process multiple input documents at a +time and either generate a latex file per input document or a single +combined output file. + +=head1 OPTIONS AND ARGUMENTS + +This section describes the supported command line options. Minium +matching is supported. + +=over 4 + +=item B<-out> + +Name of the output file to be used. If there are multiple input pods +it is assumed that the intention is to write all translated output +into a single file. C<.tex> is appended if not present. If the +argument is not supplied, a single document will be created for each +input file. + +=item B<-full> + +Creates a complete C<latex> file that can be processed immediately +(unless C<=for/=begin> directives are used that rely on extra packages). +Table of contents and index generation commands are included in the +wrapper C<latex> code. + +=item B<-sections> + +Specify pod sections to include (or remove if negated) in the +translation. See L<Pod::Select/"SECTION SPECIFICATIONS"> for the +format to use for I<section-spec>. This option may be given multiple +times on the command line.This is identical to the similar option in +the C<podselect()> command. + +=item B<-modify> + +This option causes the output C<latex> to be slightly +modified from the input pod such that when a C<=head1 NAME> +is encountered a section is created containing the actual +pod name (rather than B<NAME>) and all subsequent C<=head1> +directives are treated as subsections. This has the advantage +that the description of a module will be in its own section +which is helpful for including module descriptions in documentation. +Also forces C<latex> label and index entries to be prefixed by the +name of the module. + +=item B<-help> + +Print a brief help message and exit. + +=item B<-man> + +Print the manual page and exit. + +=item B<-verbose> + +Print information messages as each document is processed. + +=back + +=head1 BUGS + +Known bugs are: + +=over 4 + +=item * + +Cross references between documents are not resolved when multiple +pod documents are converted into a single output C<latex> file. + +=item * + +Functions and variables are not automatically recognized +and they will therefore not be marked up in any special way +unless instructed by an explicit pod command. + +=back + +=head1 SEE ALSO + +L<Pod::LaTeX> + +=head1 AUTHOR + +Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> + +This program is free software; you can redistribute it +and/or modify it under the same terms as Perl itself. + +Copyright (C) 2000 Tim Jenness. + +=cut -# map of HTML escapes to TeX escapes. -BEGIN { -%HTML_Escapes = ( - 'amp' => '&', # ampersand - 'lt' => '<', # left chevron, less-than - 'gt' => '>', # right chevron, greater-than - 'quot' => '"', # double quote - - "Aacute" => "\\'{A}", # capital A, acute accent - "aacute" => "\\'{a}", # small a, acute accent - "Acirc" => "\\^{A}", # capital A, circumflex accent - "acirc" => "\\^{a}", # small a, circumflex accent - "AElig" => '\\AE', # capital AE diphthong (ligature) - "aelig" => '\\ae', # small ae diphthong (ligature) - "Agrave" => "\\`{A}", # capital A, grave accent - "agrave" => "\\`{a}", # small a, grave accent - "Aring" => '\\u{A}', # capital A, ring - "aring" => '\\u{a}', # small a, ring - "Atilde" => '\\~{A}', # capital A, tilde - "atilde" => '\\~{a}', # small a, tilde - "Auml" => '\\"{A}', # capital A, dieresis or umlaut mark - "auml" => '\\"{a}', # small a, dieresis or umlaut mark - "Ccedil" => '\\c{C}', # capital C, cedilla - "ccedil" => '\\c{c}', # small c, cedilla - "Eacute" => "\\'{E}", # capital E, acute accent - "eacute" => "\\'{e}", # small e, acute accent - "Ecirc" => "\\^{E}", # capital E, circumflex accent - "ecirc" => "\\^{e}", # small e, circumflex accent - "Egrave" => "\\`{E}", # capital E, grave accent - "egrave" => "\\`{e}", # small e, grave accent - "ETH" => '\\OE', # capital Eth, Icelandic - "eth" => '\\oe', # small eth, Icelandic - "Euml" => '\\"{E}', # capital E, dieresis or umlaut mark - "euml" => '\\"{e}', # small e, dieresis or umlaut mark - "Iacute" => "\\'{I}", # capital I, acute accent - "iacute" => "\\'{i}", # small i, acute accent - "Icirc" => "\\^{I}", # capital I, circumflex accent - "icirc" => "\\^{i}", # small i, circumflex accent - "Igrave" => "\\`{I}", # capital I, grave accent - "igrave" => "\\`{i}", # small i, grave accent - "Iuml" => '\\"{I}', # capital I, dieresis or umlaut mark - "iuml" => '\\"{i}', # small i, dieresis or umlaut mark - "Ntilde" => '\\~{N}', # capital N, tilde - "ntilde" => '\\~{n}', # small n, tilde - "Oacute" => "\\'{O}", # capital O, acute accent - "oacute" => "\\'{o}", # small o, acute accent - "Ocirc" => "\\^{O}", # capital O, circumflex accent - "ocirc" => "\\^{o}", # small o, circumflex accent - "Ograve" => "\\`{O}", # capital O, grave accent - "ograve" => "\\`{o}", # small o, grave accent - "Oslash" => "\\O", # capital O, slash - "oslash" => "\\o", # small o, slash - "Otilde" => "\\~{O}", # capital O, tilde - "otilde" => "\\~{o}", # small o, tilde - "Ouml" => '\\"{O}', # capital O, dieresis or umlaut mark - "ouml" => '\\"{o}', # small o, dieresis or umlaut mark - "szlig" => '\\ss{}', # small sharp s, German (sz ligature) - "THORN" => '\\L', # capital THORN, Icelandic - "thorn" => '\\l',, # small thorn, Icelandic - "Uacute" => "\\'{U}", # capital U, acute accent - "uacute" => "\\'{u}", # small u, acute accent - "Ucirc" => "\\^{U}", # capital U, circumflex accent - "ucirc" => "\\^{u}", # small u, circumflex accent - "Ugrave" => "\\`{U}", # capital U, grave accent - "ugrave" => "\\`{u}", # small u, grave accent - "Uuml" => '\\"{U}', # capital U, dieresis or umlaut mark - "uuml" => '\\"{u}', # small u, dieresis or umlaut mark - "Yacute" => "\\'{Y}", # capital Y, acute accent - "yacute" => "\\'{y}", # small y, acute accent - "yuml" => '\\"{y}', # small y, dieresis or umlaut mark -); -} !NO!SUBS! close OUT or die "Can't close $file: $!"; |