[Darshan-commits] [Git][darshan/darshan][master] 2 commits: include LaTeX Perl module and install them
Shane Snyder
xgitlab at cels.anl.gov
Wed Sep 2 13:05:39 CDT 2020
Shane Snyder pushed to branch master at darshan / darshan
Commits:
6915b32f by Shane Snyder at 2020-09-02T18:00:57+00:00
include LaTeX Perl module and install them
- - - - -
01f3672e by Shane Snyder at 2020-09-02T13:05:28-05:00
Merge branch 'dev-darshanutil-perl-pod-install' into 'master'
include LaTeX Perl module and install with darshan-util
Closes #279
See merge request darshan/darshan!61
- - - - -
3 changed files:
- darshan-util/Makefile.in
- + darshan-util/darshan-job-summary/lib/Pod/Constants.pm
- + darshan-util/darshan-job-summary/lib/Pod/LaTeX.pm
Changes:
=====================================
darshan-util/Makefile.in
=====================================
@@ -224,6 +224,9 @@ endif
install -d $(DESTDIR)$(libdir)/Number
install -d $(DESTDIR)$(libdir)/Number/Bytes
install -m 644 $(srcdir)/darshan-job-summary/lib/Number/Bytes/Human.pm $(DESTDIR)$(libdir)/Number/Bytes
+ install -d $(DESTDIR)$(libdir)/Pod
+ install -m 644 $(srcdir)/darshan-job-summary/lib/Pod/Constants.pm $(DESTDIR)$(libdir)/Pod/
+ install -m 644 $(srcdir)/darshan-job-summary/lib/Pod/LaTeX.pm $(DESTDIR)$(libdir)/Pod/
install -d $(DESTDIR)$(datarootdir)
install -m 644 $(srcdir)/darshan-job-summary/share/* $(DESTDIR)$(datarootdir)
install -d $(DESTDIR)$(libdir)/pkgconfig
=====================================
darshan-util/darshan-job-summary/lib/Pod/Constants.pm
=====================================
@@ -0,0 +1,468 @@
+package Pod::Constants;
+
+use 5.006002;
+use strict;
+use warnings;
+
+use base qw(Pod::Parser Exporter);
+use Carp;
+
+our $VERSION = 0.19;
+
+# An ugly hack to go from caller() to the relevant parser state
+# variable
+my %parsers;
+
+sub end_input {
+ #my ($parser, $command, $paragraph, $line_num) = (@_);
+ my $parser = shift;
+
+ return unless $parser->{active};
+
+ print "Found end of $parser->{active}\n" if $parser->{DEBUG};
+ my $whereto = $parser->{wanted_pod_tags}->{$parser->{active}};
+ print "\$_ will be set to:\n---\n$parser->{paragraphs}\n---\n" if $parser->{DEBUG};
+
+ $parser->{paragraphs} =~ s/^\s*|\s*$//gs if $parser->{trimmed_tags}->{$parser->{active}};
+
+ if (ref $whereto eq 'CODE') {
+ print "calling sub\n" if $parser->{DEBUG};
+ local ($_) = $parser->{paragraphs};
+ $whereto->();
+ print "done\n" if $parser->{DEBUG};
+ } elsif (ref $whereto eq 'SCALAR') {
+ print "inserting into scalar\n" if $parser->{DEBUG};
+ $$whereto = $parser->{paragraphs};
+ } elsif (ref $whereto eq 'ARRAY') {
+ print "inserting into array\n" if $parser->{DEBUG};
+ @$whereto = split /\n/, $parser->{paragraphs};
+ } elsif (ref $whereto eq 'HASH') {
+ print "inserting into hash\n" if $parser->{DEBUG};
+ # Oh, sorry, should I be in LISP101?
+ %$whereto = (
+ map { map { s/^\s*|\s*$//g; $_ } split /=>/ } grep m/^
+ ( (?:[^=]|=[^>])+ ) # scan up to "=>"
+ =>
+ ( (?:[^=]|=[^>])+ =? )# don't allow more "=>"'s
+ $/x, split /\n/, $parser->{paragraphs},);
+ } else { die $whereto }
+ $parser->{active} = undef;
+}
+
+# Pod::Parser overloaded command
+sub command {
+ my ($parser, $command, $paragraph, $line_num) = @_;
+
+ $paragraph =~ s/(?:\r\n|\n\r)/\n/g;
+
+ print "Got command =$command, value=$paragraph\n" if $parser->{DEBUG};
+
+ $parser->end_input() if $parser->{active};
+
+ my ($lookup);
+ # first check for a catch-all for this command type
+ if ( exists $parser->{wanted_pod_tags}->{"*$command"} ) {
+ $parser->{paragraphs} = $paragraph;
+ $parser->{active} = "*$command";
+ } elsif ($command =~ m/^(head\d+|item|(for|begin))$/) {
+ if ( $2 ) {
+ # if it's a "for" or "begin" section, the title is the
+ # first word only
+ ($lookup, $parser->{paragraphs}) = $paragraph =~ m/^\s*(\S*)\s*(.*)/s;
+ } else {
+ # otherwise, it's up to the end of the line
+ ($lookup, $parser->{paragraphs}) = $paragraph =~ m/^\s*(\S[^\n]*?)\s*\n(.*)$/s;
+ }
+
+ # Look for a match by name
+ if (defined $lookup && exists $parser->{wanted_pod_tags}->{$lookup}) {
+ print "Found $lookup\n" if ($parser->{DEBUG});
+ $parser->{active} = $lookup;
+ } elsif ($parser->{DEBUG}) {
+ local $^W = 0;
+ print "Ignoring =$command $paragraph (lookup = $lookup)\n"
+ }
+
+ } else {
+ # nothing
+ print "Ignoring =$command (not known)\n" if $parser->{DEBUG};
+ }
+}
+
+# Pod::Parser overloaded verbatim
+sub verbatim {
+ my ($parser, $paragraph, $line_num) = @_;
+ $paragraph =~ s/(?:\r\n|\n\r)/\n/g;
+
+ my $status = $parser->{active} ? 'using' : 'ignoring';
+ print "Got paragraph: $paragraph ($status)\n" if $parser->{DEBUG};
+
+ $parser->{paragraphs} .= $paragraph if defined $parser->{active}
+}
+
+# Pod::Parser overloaded textblock
+sub textblock { goto \&verbatim }
+
+sub import {
+ my $class = shift;
+
+ # if no args, just return
+ return unless (@_);
+
+ # try to guess the source file of the caller
+ my $source_file;
+ if (caller ne 'main') {
+ (my $module = caller.'.pm') =~ s|::|/|g;
+ $source_file = $INC{$module};
+ }
+ $source_file ||= $0;
+
+ croak "Cannot find source file (guessed $source_file) for package ".caller unless -f $source_file;
+
+ # nasty tricks with the stack so we don't have to be silly with
+ # caller()
+ unshift @_, $source_file;
+ goto \&import_from_file;
+}
+
+sub import_from_file {
+ my $filename = shift;
+
+ my $parser = __PACKAGE__->new();
+
+ $parser->{wanted_pod_tags} = {};
+ $parser->{trimmed_tags} = {};
+ $parser->{trim_next} = 0;
+ $parser->{DEBUG} = 0;
+ $parser->{active} = undef;
+ $parsers{caller()} = $parser;
+
+ $parser->add_hook(@_);
+
+ print "Pod::Parser: DEBUG: Opening $filename for reading\n" if $parser->{DEBUG};
+ open my $fh, '<', $filename or croak "cannot open $filename for reading; $!";
+
+ $parser->parse_from_filehandle($fh, \*STDOUT);
+
+ close $fh;
+}
+
+sub add_hook {
+ my $parser;
+ if (eval { $_[0]->isa(__PACKAGE__) }) {
+ $parser = shift;
+ } else {
+ $parser = $parsers{caller()} or croak 'add_hook called, but don\'t know what for - caller = '.caller;
+ }
+ while (my ($pod_tag, $var) = splice @_, 0, 2) {
+ #print "$pod_tag: $var\n";
+ if (lc($pod_tag) eq '-trim') {
+ $parser->{trim_next} = $var;
+ } elsif ( lc($pod_tag) eq '-debug' ) {
+ $parser->{DEBUG} = $var;
+ } elsif (lc($pod_tag) eq '-usage') {
+ # an idea for later - automatic "usage"
+ #%wanted_pod_tags{@tags}
+ } else {
+ if ((ref $var) =~ /^(?:SCALAR|CODE|ARRAY|HASH)$/) {
+ print "Will look for $pod_tag.\n" if $parser->{DEBUG};
+ $parser->{wanted_pod_tags}->{$pod_tag} = $var;
+ $parser->{trimmed_tags}->{$pod_tag} = 1 if $parser->{trim_next};
+ } else {
+ croak "Sorry - need a reference to import POD sections into, not the scalar value $var"
+ }
+ }
+ }
+}
+
+sub delete_hook {
+ my $parser;
+ if (eval { $_[0]->isa(__PACKAGE__) }) {
+ $parser = shift;
+ } else {
+ $parser = $parsers{caller()} or croak 'delete_hook called, but don\'t know what for - caller = '.caller;
+ }
+ while ( my $label = shift ) {
+ delete $parser->{wanted_pod_tags}->{$label};
+ delete $parser->{trimmed_tags}->{$label};
+ }
+}
+
+1;
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+Pod::Constants - Include constants from POD
+
+=head1 SYNOPSIS
+
+ our ($myvar, $VERSION, @myarray, $html, %myhash);
+
+ use Pod::Constants -trim => 1,
+ 'Pod Section Name' => \$myvar,
+ 'Version' => sub { eval },
+ 'Some list' => \@myarray,
+ html => \$html,
+ 'Some hash' => \%myhash;
+
+ =head2 Pod Section Name
+
+ This string will be loaded into $myvar
+
+ =head2 Version
+
+ # This is an example of using a closure. $_ is set to the
+ # contents of the paragraph. In this example, "eval" is
+ # used to execute this code at run time.
+ $VERSION = 0.19;
+
+ =head2 Some list
+
+ Each line from this section of the file
+ will be placed into a separate array element.
+ For example, this is $myarray[2].
+
+ =head2 Some hash
+
+ This text will not go into the hash, because
+ it doesn't look like a definition list.
+ key1 => Some value (this will go into the hash)
+ var2 => Some Other value (so will this)
+ wtf = This won't make it in.
+
+ =head2 %myhash's value after the above:
+
+ ( key1 => "Some value (this will go into the hash)",
+ var2 => "Some Other value (so will this)" )
+
+ =begin html <p>This text will be in $html</p>
+
+ =cut
+
+=head1 DESCRIPTION
+
+This module allows you to specify those constants that should be
+documented in your POD, and pull them out a run time in a fairly
+arbitrary fashion.
+
+Pod::Constants uses Pod::Parser to do the parsing of the source file.
+It has to open the source file it is called from, and does so directly
+either by lookup in %INC or by assuming it is $0 if the caller is
+"main" (or it can't find %INC{caller()})
+
+=head2 ARBITARY DECISIONS
+
+I have made this code only allow the "Pod Section Name" to match
+`headN', `item', `for' and `begin' POD sections. If you have a good
+reason why you think it should match other POD sections, drop me a
+line and if I'm convinced I'll put it in the standard version.
+
+For `for' and `begin' sections, only the first word is counted as
+being a part of the specifier, as opposed to `headN' and `item', where
+the entire rest of the line counts.
+
+=head1 FUNCTIONS
+
+=head2 import(@args)
+
+This function is called when we are "use"'d. It determines the source
+file by inspecting the value of caller() or $0.
+
+The form of @args is HOOK => $where.
+
+$where may be a scalar reference, in which case the contents of the
+POD section called "HOOK" will be loaded into $where.
+
+$where may be an array reference, in which case the contents of the
+array will be the contents of the POD section called "HOOK", split
+into lines.
+
+$where may be a hash reference, in which case any lines with a "=>"
+symbol present will have everything on the left have side of the =>
+operator as keys and everything on the right as values. You do not
+need to quote either, nor have trailing commas at the end of the
+lines.
+
+$where may be a code reference (sub { }), in which case the sub is
+called when the hook is encountered. $_ is set to the value of the
+POD paragraph.
+
+You may also specify the behaviour of whitespace trimming; by default,
+no trimming is done except on the HOOK names. Setting "-trim => 1"
+turns on a package "global" (until the next time import is called)
+that will trim the $_ sent for processing by the hook processing
+function (be it a given function, or the built-in array/hash
+splitters) for leading and trailing whitespace.
+
+The name of HOOK is matched against any "=head1", "=head2", "=item",
+"=for", "=begin" value. If you specify the special hooknames "*item",
+"*head1", etc, then you will get a function that is run for every
+
+Note that the supplied functions for array and hash splitting are
+exactly equivalent to fairly simple Perl blocks:
+
+Array:
+
+ HOOK => sub { @array = split /\n/, $_ }
+
+Hash:
+
+ HOOK => sub {
+ %hash =
+ (map { map { s/^\s+|\s+$//g; $_ } split /=>/, $_ }
+ (grep m/^
+ ( (?:[^=]|=[^>])+ ) # scan up to "=>"
+ =>
+ ( (?:[^=]|=[^>])+ =? )# don't allow more "=>"'s
+ $/x, split /\n/, $_));
+ }
+
+Well, they're simple if you can grok map, a regular expression like
+that and a functional programming style. If you can't I'm sure it is
+probably voodoo to you.
+
+Here's the procedural equivalent:
+
+ HOOK => sub {
+ for my $line (split /\n/, $_) {
+ my ($key, $value, $junk) = split /=>/, $line;
+ next if $junk;
+ $key =~ s/^\s+|\s+$//g
+ $value =~ s/^\s+|\s+$//g
+ $hash{$key} = $value;
+ }
+ },
+
+=head2 import_from_file($filename, @args)
+
+Very similar to straight "import", but you specify the source filename
+explicitly.
+
+=head2 add_hook(NAME => value)
+
+This function adds another hook, it is useful for dynamic updating of
+parsing through the document.
+
+For an example, please see t/01-constants.t in the source
+distribution. More detailed examples will be added in a later
+release.
+
+=head2 delete_hook(@list)
+
+Deletes the named hooks. Companion function to add_hook
+
+=head2 CLOSURES AS DESTINATIONS
+
+If the given value is a ref CODE, then that function is called, with
+$_ set to the value of the paragraph. This can be very useful for
+applying your own custom mutations to the POD to change it from human
+readable text into something your program can use.
+
+After I added this function, I just kept on thinking of cool uses for
+it. The nice, succinct code you can make with it is one of
+Pod::Constant's strongest features.
+
+Below are some examples.
+
+=head1 EXAMPLES
+
+=head2 Module Makefile.PL maintenance
+
+Tired of keeping those module Makefile.PL's up to date? Note: This
+method seems to break dh-make-perl.
+
+=head2 Example Makefile.PL
+
+ eval "use Pod::Constants";
+ ($Pod::Constants::VERSION >= 0.11)
+ or die <<EOF
+ ####
+ #### ERROR: This module requires Pod::Constants 0.11 or
+ #### higher to be installed.
+ ####
+ EOF
+
+ my ($VERSION, $NAME, $PREREQ_PM, $ABSTRACT, $AUTHOR);
+ Pod::Constants::import_from_file
+ (
+ 'MyTestModule.pm',
+ 'MODULE RELEASE' => sub { ($VERSION) = m/(\d+\.\d+)/ },
+ 'DEPENDENCIES' => ($PREREQ_PM = { }),
+ -trim => 1,
+ 'NAME' => sub { $ABSTRACT=$_; ($NAME) = m/(\S+)/ },
+ 'AUTHOR' => \$AUTHOR,
+ );
+
+ WriteMakefile
+ (
+ 'NAME' => $NAME,
+ 'PREREQ_PM' => $PREREQ_PM,
+ 'VERSION' => $VERSION,
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT => $ABSTRACT,
+ AUTHOR => $AUTHOR) : ()),
+ );
+
+=head2 Corresponding Module
+
+ =head1 NAME
+
+ MyTestModule - Demonstrate Pod::Constant's Makefile.PL usefulness
+
+ =head2 MODULE RELEASE
+
+ This is release 1.05 of this module.
+
+ =head2 DEPENDENCIES
+
+ The following modules are required to make this module:
+
+ Some::Module => 0.02
+
+ =head2 AUTHOR
+
+ Ima Twat <ima at twat.name>
+
+ =cut
+
+ our $VERSION;
+ use Pod::Constants -trim => 1,
+ 'MODULE RELEASE' => sub { ($VERSION) = m/(\d+\.\d+) or die };
+
+=head1 AUTHOR
+
+Sam Vilain, <samv at cpan.org>
+
+Maintained by Marius Gavrilescu, <marius at ieval.ro> since July 2015
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2001, 2002, 2007 Sam Vilain. All Rights Reserved.
+
+Copyright (C) 2015-2016 by Marius Gavrilescu <marius at ieval.ro>.
+
+This module is free software. It may be used, redistributed and/or
+modified under the terms of the Perl Artistic License, version 2.
+
+See the LICENSE file in the root of this distribution for a copy of
+the Perl Artistic License, version 2.
+
+=head1 BUGS/TODO
+
+I keep thinking it would be nice to be able to import an =item list
+into an array or something, eg for a program argument list. But I'm
+not too sure how it would be all that useful in practice; you'd end up
+putting the function names for callbacks in the pod or something
+(perhaps not all that bad).
+
+Would this be useful?
+
+ Pod::Constants::import(Foo::SECTION => \$myvar);
+
+Debug output is not very readable
+
+
+=cut
=====================================
darshan-util/darshan-job-summary/lib/Pod/LaTeX.pm
=====================================
@@ -0,0 +1,1883 @@
+package Pod::LaTeX;
+
+=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 if $] > 5.017, 'deprecate';
+
+# use Data::Dumper; # for debugging
+use Carp;
+
+use vars qw/ $VERSION %HTML_Escapes @LatexSections /;
+
+$VERSION = '0.61';
+
+# Definitions of =headN -> latex mapping
+ at LatexSections = (qw/
+ chapter
+ section
+ subsection
+ subsubsection
+ paragraph
+ subparagraph
+ /);
+
+# Standard escape sequences converted to Latex.
+# The Unicode name of each character is given in the comments.
+# Complete LaTeX set added by Peter Acklam.
+
+%HTML_Escapes = (
+ 'sol' => '\textfractionsolidus{}', # xxx - or should it be just '/'
+ 'verbar' => '|',
+
+ # The stuff below is based on the information available at
+ # http://www.w3.org/TR/html401/sgml/entities.html
+
+ # All characters in the range 0xA0-0xFF of the ISO 8859-1 character set.
+ # Several of these characters require the `textcomp' LaTeX package.
+ 'nbsp' => q|~|, # 0xA0 - no-break space = non-breaking space
+ 'iexcl' => q|\textexclamdown{}|, # 0xA1 - inverted exclamation mark
+ 'cent' => q|\textcent{}|, # 0xA2 - cent sign
+ 'pound' => q|\textsterling{}|, # 0xA3 - pound sign
+ 'curren' => q|\textcurrency{}|, # 0xA4 - currency sign
+ 'yen' => q|\textyen{}|, # 0xA5 - yen sign = yuan sign
+ 'brvbar' => q|\textbrokenbar{}|, # 0xA6 - broken bar = broken vertical bar
+ 'sect' => q|\textsection{}|, # 0xA7 - section sign
+ 'uml' => q|\textasciidieresis{}|, # 0xA8 - diaeresis = spacing diaeresis
+ 'copy' => q|\textcopyright{}|, # 0xA9 - copyright sign
+ 'ordf' => q|\textordfeminine{}|, # 0xAA - feminine ordinal indicator
+ 'laquo' => q|\guillemotleft{}|, # 0xAB - left-pointing double angle quotation mark = left pointing guillemet
+ 'not' => q|\textlnot{}|, # 0xAC - not sign
+ 'shy' => q|\-|, # 0xAD - soft hyphen = discretionary hyphen
+ 'reg' => q|\textregistered{}|, # 0xAE - registered sign = registered trade mark sign
+ 'macr' => q|\textasciimacron{}|, # 0xAF - macron = spacing macron = overline = APL overbar
+ 'deg' => q|\textdegree{}|, # 0xB0 - degree sign
+ 'plusmn' => q|\textpm{}|, # 0xB1 - plus-minus sign = plus-or-minus sign
+ 'sup2' => q|\texttwosuperior{}|, # 0xB2 - superscript two = superscript digit two = squared
+ 'sup3' => q|\textthreesuperior{}|, # 0xB3 - superscript three = superscript digit three = cubed
+ 'acute' => q|\textasciiacute{}|, # 0xB4 - acute accent = spacing acute
+ 'micro' => q|\textmu{}|, # 0xB5 - micro sign
+ 'para' => q|\textparagraph{}|, # 0xB6 - pilcrow sign = paragraph sign
+ 'middot' => q|\textperiodcentered{}|, # 0xB7 - middle dot = Georgian comma = Greek middle dot
+ 'cedil' => q|\c{}|, # 0xB8 - cedilla = spacing cedilla
+ 'sup1' => q|\textonesuperior{}|, # 0xB9 - superscript one = superscript digit one
+ 'ordm' => q|\textordmasculine{}|, # 0xBA - masculine ordinal indicator
+ 'raquo' => q|\guillemotright{}|, # 0xBB - right-pointing double angle quotation mark = right pointing guillemet
+ 'frac14' => q|\textonequarter{}|, # 0xBC - vulgar fraction one quarter = fraction one quarter
+ 'frac12' => q|\textonehalf{}|, # 0xBD - vulgar fraction one half = fraction one half
+ 'frac34' => q|\textthreequarters{}|, # 0xBE - vulgar fraction three quarters = fraction three quarters
+ 'iquest' => q|\textquestiondown{}|, # 0xBF - inverted question mark = turned question mark
+ 'Agrave' => q|\`A|, # 0xC0 - latin capital letter A with grave = latin capital letter A grave
+ 'Aacute' => q|\'A|, # 0xC1 - latin capital letter A with acute
+ 'Acirc' => q|\^A|, # 0xC2 - latin capital letter A with circumflex
+ 'Atilde' => q|\~A|, # 0xC3 - latin capital letter A with tilde
+ 'Auml' => q|\"A|, # 0xC4 - latin capital letter A with diaeresis
+ 'Aring' => q|\AA{}|, # 0xC5 - latin capital letter A with ring above = latin capital letter A ring
+ 'AElig' => q|\AE{}|, # 0xC6 - latin capital letter AE = latin capital ligature AE
+ 'Ccedil' => q|\c{C}|, # 0xC7 - latin capital letter C with cedilla
+ 'Egrave' => q|\`E|, # 0xC8 - latin capital letter E with grave
+ 'Eacute' => q|\'E|, # 0xC9 - latin capital letter E with acute
+ 'Ecirc' => q|\^E|, # 0xCA - latin capital letter E with circumflex
+ 'Euml' => q|\"E|, # 0xCB - latin capital letter E with diaeresis
+ 'Igrave' => q|\`I|, # 0xCC - latin capital letter I with grave
+ 'Iacute' => q|\'I|, # 0xCD - latin capital letter I with acute
+ 'Icirc' => q|\^I|, # 0xCE - latin capital letter I with circumflex
+ 'Iuml' => q|\"I|, # 0xCF - latin capital letter I with diaeresis
+ 'ETH' => q|\DH{}|, # 0xD0 - latin capital letter ETH
+ 'Ntilde' => q|\~N|, # 0xD1 - latin capital letter N with tilde
+ 'Ograve' => q|\`O|, # 0xD2 - latin capital letter O with grave
+ 'Oacute' => q|\'O|, # 0xD3 - latin capital letter O with acute
+ 'Ocirc' => q|\^O|, # 0xD4 - latin capital letter O with circumflex
+ 'Otilde' => q|\~O|, # 0xD5 - latin capital letter O with tilde
+ 'Ouml' => q|\"O|, # 0xD6 - latin capital letter O with diaeresis
+ 'times' => q|\texttimes{}|, # 0xD7 - multiplication sign
+ 'Oslash' => q|\O{}|, # 0xD8 - latin capital letter O with stroke = latin capital letter O slash
+ 'Ugrave' => q|\`U|, # 0xD9 - latin capital letter U with grave
+ 'Uacute' => q|\'U|, # 0xDA - latin capital letter U with acute
+ 'Ucirc' => q|\^U|, # 0xDB - latin capital letter U with circumflex
+ 'Uuml' => q|\"U|, # 0xDC - latin capital letter U with diaeresis
+ 'Yacute' => q|\'Y|, # 0xDD - latin capital letter Y with acute
+ 'THORN' => q|\TH{}|, # 0xDE - latin capital letter THORN
+ 'szlig' => q|\ss{}|, # 0xDF - latin small letter sharp s = ess-zed
+ 'agrave' => q|\`a|, # 0xE0 - latin small letter a with grave = latin small letter a grave
+ 'aacute' => q|\'a|, # 0xE1 - latin small letter a with acute
+ 'acirc' => q|\^a|, # 0xE2 - latin small letter a with circumflex
+ 'atilde' => q|\~a|, # 0xE3 - latin small letter a with tilde
+ 'auml' => q|\"a|, # 0xE4 - latin small letter a with diaeresis
+ 'aring' => q|\aa{}|, # 0xE5 - latin small letter a with ring above = latin small letter a ring
+ 'aelig' => q|\ae{}|, # 0xE6 - latin small letter ae = latin small ligature ae
+ 'ccedil' => q|\c{c}|, # 0xE7 - latin small letter c with cedilla
+ 'egrave' => q|\`e|, # 0xE8 - latin small letter e with grave
+ 'eacute' => q|\'e|, # 0xE9 - latin small letter e with acute
+ 'ecirc' => q|\^e|, # 0xEA - latin small letter e with circumflex
+ 'euml' => q|\"e|, # 0xEB - latin small letter e with diaeresis
+ 'igrave' => q|\`i|, # 0xEC - latin small letter i with grave
+ 'iacute' => q|\'i|, # 0xED - latin small letter i with acute
+ 'icirc' => q|\^i|, # 0xEE - latin small letter i with circumflex
+ 'iuml' => q|\"i|, # 0xEF - latin small letter i with diaeresis
+ 'eth' => q|\dh{}|, # 0xF0 - latin small letter eth
+ 'ntilde' => q|\~n|, # 0xF1 - latin small letter n with tilde
+ 'ograve' => q|\`o|, # 0xF2 - latin small letter o with grave
+ 'oacute' => q|\'o|, # 0xF3 - latin small letter o with acute
+ 'ocirc' => q|\^o|, # 0xF4 - latin small letter o with circumflex
+ 'otilde' => q|\~o|, # 0xF5 - latin small letter o with tilde
+ 'ouml' => q|\"o|, # 0xF6 - latin small letter o with diaeresis
+ 'divide' => q|\textdiv{}|, # 0xF7 - division sign
+ 'oslash' => q|\o{}|, # 0xF8 - latin small letter o with stroke, = latin small letter o slash
+ 'ugrave' => q|\`u|, # 0xF9 - latin small letter u with grave
+ 'uacute' => q|\'u|, # 0xFA - latin small letter u with acute
+ 'ucirc' => q|\^u|, # 0xFB - latin small letter u with circumflex
+ 'uuml' => q|\"u|, # 0xFC - latin small letter u with diaeresis
+ 'yacute' => q|\'y|, # 0xFD - latin small letter y with acute
+ 'thorn' => q|\th{}|, # 0xFE - latin small letter thorn
+ 'yuml' => q|\"y|, # 0xFF - latin small letter y with diaeresis
+
+ # Latin Extended-B
+ 'fnof' => q|\textflorin{}|, # latin small f with hook = function = florin
+
+ # Greek
+ 'Alpha' => q|$\mathrm{A}$|, # greek capital letter alpha
+ 'Beta' => q|$\mathrm{B}$|, # greek capital letter beta
+ 'Gamma' => q|$\Gamma$|, # greek capital letter gamma
+ 'Delta' => q|$\Delta$|, # greek capital letter delta
+ 'Epsilon' => q|$\mathrm{E}$|, # greek capital letter epsilon
+ 'Zeta' => q|$\mathrm{Z}$|, # greek capital letter zeta
+ 'Eta' => q|$\mathrm{H}$|, # greek capital letter eta
+ 'Theta' => q|$\Theta$|, # greek capital letter theta
+ 'Iota' => q|$\mathrm{I}$|, # greek capital letter iota
+ 'Kappa' => q|$\mathrm{K}$|, # greek capital letter kappa
+ 'Lambda' => q|$\Lambda$|, # greek capital letter lambda
+ 'Mu' => q|$\mathrm{M}$|, # greek capital letter mu
+ 'Nu' => q|$\mathrm{N}$|, # greek capital letter nu
+ 'Xi' => q|$\Xi$|, # greek capital letter xi
+ 'Omicron' => q|$\mathrm{O}$|, # greek capital letter omicron
+ 'Pi' => q|$\Pi$|, # greek capital letter pi
+ 'Rho' => q|$\mathrm{R}$|, # greek capital letter rho
+ 'Sigma' => q|$\Sigma$|, # greek capital letter sigma
+ 'Tau' => q|$\mathrm{T}$|, # greek capital letter tau
+ 'Upsilon' => q|$\Upsilon$|, # greek capital letter upsilon
+ 'Phi' => q|$\Phi$|, # greek capital letter phi
+ 'Chi' => q|$\mathrm{X}$|, # greek capital letter chi
+ 'Psi' => q|$\Psi$|, # greek capital letter psi
+ 'Omega' => q|$\Omega$|, # greek capital letter omega
+
+ 'alpha' => q|$\alpha$|, # greek small letter alpha
+ 'beta' => q|$\beta$|, # greek small letter beta
+ 'gamma' => q|$\gamma$|, # greek small letter gamma
+ 'delta' => q|$\delta$|, # greek small letter delta
+ 'epsilon' => q|$\epsilon$|, # greek small letter epsilon
+ 'zeta' => q|$\zeta$|, # greek small letter zeta
+ 'eta' => q|$\eta$|, # greek small letter eta
+ 'theta' => q|$\theta$|, # greek small letter theta
+ 'iota' => q|$\iota$|, # greek small letter iota
+ 'kappa' => q|$\kappa$|, # greek small letter kappa
+ 'lambda' => q|$\lambda$|, # greek small letter lambda
+ 'mu' => q|$\mu$|, # greek small letter mu
+ 'nu' => q|$\nu$|, # greek small letter nu
+ 'xi' => q|$\xi$|, # greek small letter xi
+ 'omicron' => q|$o$|, # greek small letter omicron
+ 'pi' => q|$\pi$|, # greek small letter pi
+ 'rho' => q|$\rho$|, # greek small letter rho
+# 'sigmaf' => q||, # greek small letter final sigma
+ 'sigma' => q|$\sigma$|, # greek small letter sigma
+ 'tau' => q|$\tau$|, # greek small letter tau
+ 'upsilon' => q|$\upsilon$|, # greek small letter upsilon
+ 'phi' => q|$\phi$|, # greek small letter phi
+ 'chi' => q|$\chi$|, # greek small letter chi
+ 'psi' => q|$\psi$|, # greek small letter psi
+ 'omega' => q|$\omega$|, # greek small letter omega
+# 'thetasym' => q||, # greek small letter theta symbol
+# 'upsih' => q||, # greek upsilon with hook symbol
+# 'piv' => q||, # greek pi symbol
+
+ # General Punctuation
+ 'bull' => q|\textbullet{}|, # bullet = black small circle
+ # bullet is NOT the same as bullet operator
+ 'hellip' => q|\textellipsis{}|, # horizontal ellipsis = three dot leader
+ 'prime' => q|\textquotesingle{}|, # prime = minutes = feet
+ 'Prime' => q|\textquotedbl{}|, # double prime = seconds = inches
+ 'oline' => q|\textasciimacron{}|, # overline = spacing overscore
+ 'frasl' => q|\textfractionsolidus{}|, # fraction slash
+
+ # Letterlike Symbols
+ 'weierp' => q|$\wp$|, # script capital P = power set = Weierstrass p
+ 'image' => q|$\Re$|, # blackletter capital I = imaginary part
+ 'real' => q|$\Im$|, # blackletter capital R = real part symbol
+ 'trade' => q|\texttrademark{}|, # trade mark sign
+# 'alefsym' => q||, # alef symbol = first transfinite cardinal
+ # alef symbol is NOT the same as hebrew letter alef, although the same
+ # glyph could be used to depict both characters
+
+ # Arrows
+ 'larr' => q|\textleftarrow{}|, # leftwards arrow
+ 'uarr' => q|\textuparrow{}|, # upwards arrow
+ 'rarr' => q|\textrightarrow{}|, # rightwards arrow
+ 'darr' => q|\textdownarrow{}|, # downwards arrow
+ 'harr' => q|$\leftrightarrow$|, # left right arrow
+# 'crarr' => q||, # downwards arrow with corner leftwards = carriage return
+ 'lArr' => q|$\Leftarrow$|, # leftwards double arrow
+ # ISO 10646 does not say that lArr is the same as the 'is implied by'
+ # arrow but also does not have any other character for that function. So
+ # lArr can be used for 'is implied by' as ISOtech suggests
+ 'uArr' => q|$\Uparrow$|, # upwards double arrow
+ 'rArr' => q|$\Rightarrow$|, # rightwards double arrow
+ # ISO 10646 does not say this is the 'implies' character but does not
+ # have another character with this function so ? rArr can be used for
+ # 'implies' as ISOtech suggests
+ 'dArr' => q|$\Downarrow$|, # downwards double arrow
+ 'hArr' => q|$\Leftrightarrow$|, # left right double arrow
+
+ # Mathematical Operators.
+ # Some of these require the `amssymb' package.
+ 'forall' => q|$\forall$|, # for all
+ 'part' => q|$\partial$|, # partial differential
+ 'exist' => q|$\exists$|, # there exists
+ 'empty' => q|$\emptyset$|, # empty set = null set = diameter
+ 'nabla' => q|$\nabla$|, # nabla = backward difference
+ 'isin' => q|$\in$|, # element of
+ 'notin' => q|$\notin$|, # not an element of
+ 'ni' => q|$\ni$|, # contains as member
+ 'prod' => q|$\prod$|, # n-ary product = product sign
+ # prod is NOT the same character as 'greek capital letter pi' though the
+ # same glyph might be used for both
+ 'sum' => q|$\sum$|, # n-ary summation
+ # sum is NOT the same character as 'greek capital letter sigma' though
+ # the same glyph might be used for both
+ 'minus' => q|$-$|, # minus sign
+ 'lowast' => q|$\ast$|, # asterisk operator
+ 'radic' => q|$\surd$|, # square root = radical sign
+ 'prop' => q|$\propto$|, # proportional to
+ 'infin' => q|$\infty$|, # infinity
+ 'ang' => q|$\angle$|, # angle
+ 'and' => q|$\wedge$|, # logical and = wedge
+ 'or' => q|$\vee$|, # logical or = vee
+ 'cap' => q|$\cap$|, # intersection = cap
+ 'cup' => q|$\cup$|, # union = cup
+ 'int' => q|$\int$|, # integral
+ 'there4' => q|$\therefore$|, # therefore
+ 'sim' => q|$\sim$|, # tilde operator = varies with = similar to
+ # tilde operator is NOT the same character as the tilde
+ 'cong' => q|$\cong$|, # approximately equal to
+ 'asymp' => q|$\asymp$|, # almost equal to = asymptotic to
+ 'ne' => q|$\neq$|, # not equal to
+ 'equiv' => q|$\equiv$|, # identical to
+ 'le' => q|$\leq$|, # less-than or equal to
+ 'ge' => q|$\geq$|, # greater-than or equal to
+ 'sub' => q|$\subset$|, # subset of
+ 'sup' => q|$\supset$|, # superset of
+ # note that nsup, 'not a superset of' is not covered by the Symbol font
+ # encoding and is not included.
+ 'nsub' => q|$\not\subset$|, # not a subset of
+ 'sube' => q|$\subseteq$|, # subset of or equal to
+ 'supe' => q|$\supseteq$|, # superset of or equal to
+ 'oplus' => q|$\oplus$|, # circled plus = direct sum
+ 'otimes' => q|$\otimes$|, # circled times = vector product
+ 'perp' => q|$\perp$|, # up tack = orthogonal to = perpendicular
+ 'sdot' => q|$\cdot$|, # dot operator
+ # dot operator is NOT the same character as middle dot
+
+ # Miscellaneous Technical
+ 'lceil' => q|$\lceil$|, # left ceiling = apl upstile
+ 'rceil' => q|$\rceil$|, # right ceiling
+ 'lfloor' => q|$\lfloor$|, # left floor = apl downstile
+ 'rfloor' => q|$\rfloor$|, # right floor
+ 'lang' => q|$\langle$|, # left-pointing angle bracket = bra
+ # lang is NOT the same character as 'less than' or 'single left-pointing
+ # angle quotation mark'
+ 'rang' => q|$\rangle$|, # right-pointing angle bracket = ket
+ # rang is NOT the same character as 'greater than' or 'single
+ # right-pointing angle quotation mark'
+
+ # Geometric Shapes
+ 'loz' => q|$\lozenge$|, # lozenge
+
+ # Miscellaneous Symbols
+ 'spades' => q|$\spadesuit$|, # black spade suit
+ 'clubs' => q|$\clubsuit$|, # black club suit = shamrock
+ 'hearts' => q|$\heartsuit$|, # black heart suit = valentine
+ 'diams' => q|$\diamondsuit$|, # black diamond suit
+
+ # C0 Controls and Basic Latin
+ 'quot' => q|"|, # quotation mark = APL quote ["]
+ 'amp' => q|\&|, # ampersand
+ 'lt' => q|<|, # less-than sign
+ 'gt' => q|>|, # greater-than sign
+ 'OElig' => q|\OE{}|, # latin capital ligature OE
+ 'oelig' => q|\oe{}|, # latin small ligature oe
+ 'Scaron' => q|\v{S}|, # latin capital letter S with caron
+ 'scaron' => q|\v{s}|, # latin small letter s with caron
+ 'Yuml' => q|\"Y|, # latin capital letter Y with diaeresis
+ 'circ' => q|\textasciicircum{}|, # modifier letter circumflex accent
+ 'tilde' => q|\textasciitilde{}|, # small tilde
+ 'ensp' => q|\phantom{n}|, # en space
+ 'emsp' => q|\hspace{1em}|, # em space
+ 'thinsp' => q|\,|, # thin space
+ 'zwnj' => q|{}|, # zero width non-joiner
+# 'zwj' => q||, # zero width joiner
+# 'lrm' => q||, # left-to-right mark
+# 'rlm' => q||, # right-to-left mark
+ 'ndash' => q|--|, # en dash
+ 'mdash' => q|---|, # em dash
+ 'lsquo' => q|\textquoteleft{}|, # left single quotation mark
+ 'rsquo' => q|\textquoteright{}|, # right single quotation mark
+ 'sbquo' => q|\quotesinglbase{}|, # single low-9 quotation mark
+ 'ldquo' => q|\textquotedblleft{}|, # left double quotation mark
+ 'rdquo' => q|\textquotedblright{}|, # right double quotation mark
+ 'bdquo' => q|\quotedblbase{}|, # double low-9 quotation mark
+ 'dagger' => q|\textdagger{}|, # dagger
+ 'Dagger' => q|\textdaggerdbl{}|, # double dagger
+ 'permil' => q|\textperthousand{}|, # per mille sign
+ 'lsaquo' => q|\guilsinglleft{}|, # single left-pointing angle quotation mark
+ 'rsaquo' => q|\guilsinglright{}|, # single right-pointing angle quotation mark
+ 'euro' => q|\texteuro{}|, # euro sign
+);
+
+=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->{_dont_modify_any_para}=0; # For =begin 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 relevant 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 arbitrary 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}
+ \usepackage[T1]{fontenc}
+ \usepackage{textcomp}
+ \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>.
+
+For some pod escapes it may be necessary to include the amsmath
+package. This is not yet added to the preamble automatically.
+
+=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 list 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. Only writes something
+if AddPreamble is true. Writes a standard header unless a UserPreamble
+is defined.
+
+=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 ($self->AddPreamble) {
+
+ if (defined $self->UserPreamble) {
+
+ $preamble = $self->UserPreamble;
+
+ # Add the description of where this came from
+ $preamble .= "\n$comment\n%% Preamble supplied by user.\n\n";
+
+ } else {
+
+ # 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", at makeidx) . "\n";
+
+ # Table of contents
+ my $tableofcontents = '\tableofcontents';
+
+ $tableofcontents = '%% ' . $tableofcontents
+ unless $self->TableOfContents;
+
+ # Roll our own
+ $preamble = << "__TEX_HEADER__";
+\\documentclass{article}
+\\usepackage[T1]{fontenc}
+\\usepackage{textcomp}
+
+$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. Only writes something if AddPostamble
+is true. Writes a standard header unless a UserPostamble is defined.
+
+=cut
+
+sub end_pod {
+ my $self = shift;
+
+ # End string
+ my $end = '';
+
+ # Use the user version of the postamble if defined
+ if ($self->AddPostamble) {
+
+ if (defined $self->UserPostamble) {
+ $end = $self->UserPostamble;
+
+ } else {
+
+ # 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';
+
+ # Store a copy of the raw text in case we are in a =for
+ # block and need to preserve the existing latex
+ my $rawpara = $paragraph;
+
+ # Do the latex escapes
+ $paragraph = $self->_replace_special_chars($paragraph);
+
+ # Interpolate pod sequences in paragraph
+ $paragraph = $self->interpolate($paragraph, $line_num);
+ $paragraph =~ s/\s+$//;
+
+ # Replace characters that can only be done after
+ # interpolation of interior sequences
+ $paragraph = $self->_replace_special_chars_late($paragraph);
+
+ # 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 explicitly intended for latex
+ $self->{_suppress_all_para} = 1;
+ }
+
+ } elsif ($command eq 'for') {
+
+ # =for latex
+ # some latex
+
+ # With =for we will get the text for the full paragraph
+ # as well as the format name.
+ # We do not get an additional paragraph later on. The next
+ # paragraph is not governed by the =for
+
+ # The first line contains the format and the rest is the
+ # raw code.
+ my ($format, $chunk) = split(/\n/, $rawpara, 2);
+
+ # If we have got some latex code print it out immediately
+ # unmodified. Else do nothing.
+ if ($format =~ /^latex/i) {
+ # Make sure that next paragraph is not modfied before printing
+ $self->_output( $chunk );
+
+ }
+
+ } 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 =begin block
+ if ($self->{_dont_modify_any_para}) {
+ # Just print as is
+ $self->_output($paragraph);
+
+ } else {
+
+ return if $paragraph =~ /^\s+$/;
+
+ # Clean trailing space
+ $paragraph =~ s/\s+$//;
+
+ # Clean tabs. Routine taken from Tabs.pm
+ # by David Muir Sharnoff muir at idiom.com,
+ # slightly modified by hsmyers at sdragons.com 10/22/01
+ my @l = split("\n",$paragraph);
+ foreach (@l) {
+ 1 while s/(^|\n)([^\t\n]*)(\t+)/
+ $1. $2 . (" " x
+ (8 * length($3)
+ - (length($2) % 8)))
+ /sex;
+ }
+ $paragraph = join("\n", at l);
+ # End of change.
+
+
+
+ $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 =begin block
+ if ($self->{_dont_modify_any_para}) {
+ # Just print as is
+ $self->_output($paragraph);
+
+ return;
+ }
+
+
+ # Escape latex special characters
+ $paragraph = $self->_replace_special_chars($paragraph);
+
+ # Interpolate interior sequences
+ my $expansion = $self->interpolate($paragraph, $line_num);
+ $expansion =~ s/\s+$//;
+
+ # Escape special characters that can not be done earlier
+ $expansion = $self->_replace_special_chars_late($expansion);
+
+ # 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 / - but not sure if I want to do this
+ # any more.
+ 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}";
+
+ } 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;
+
+ # Don't 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 whatever
+ # simply return immediately
+ return if $self->{_suppress_all_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 (substr($paragraph, 0,1) 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') {
+ # Handle long items - long items do not wrap
+ # If the string is longer than 40 characters we split
+ # it into a real item header and some bold text.
+ my $maxlen = 40;
+ my ($hunk1, $hunk2) = $self->_split_delimited( $paragraph, $maxlen );
+
+ # Print the first hunk
+ $self->_output("\n\\item[{$hunk1}] ");
+
+ # and the second hunk if it is defined
+ if ($hunk2) {
+ $self->_output("\\textbf{$hunk2}");
+ } else {
+ # Not there so make sure we have a new line
+ $self->_output("\\mbox{}");
+ }
+
+ } else {
+ # If the item was '* Something' or '\d+ something' we still need to write
+ # out the something. Also allow 1) and 1.
+ my $extra_info = $paragraph;
+ $extra_info =~ s/^(\*|\d+[\.\)]?)\s*//;
+ $self->_output("\n\\item $extra_info");
+ }
+
+ # 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."}}\n");
+
+}
+
+
+=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 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};
+
+}
+
+
+=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. It must be called before interpolation of interior
+sequences so that curly brackets and special latex characters inserted
+during interpolation are not themselves escaped. This means that < and
+> can not be modified here since the text still contains interior
+sequences.
+
+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;
+
+ # Replace tilde (~) with \texttt{\~{}}
+ $paragraph =~ s/~/\\texttt\{\\~\{\}\}/g;
+
+ # Now add the dollars around each \backslash
+ $paragraph =~ s/(\\backslash)/\$$1\$/g;
+
+ # Convert ------ to -{}-{}-{}-{}-{}-
+ $paragraph =~ s/-(?=-)/-{}/g;
+
+ return $paragraph;
+}
+
+=item B<_replace_special_chars_late>
+
+Replace special characters that can not be replaced before interior
+sequence interpolation. See C<_replace_special_chars> for a routine
+to replace special characters prior to interpolation of interior
+sequences.
+
+Does the following transformation:
+
+ < $<$
+ > $>$
+ | $|$
+
+
+=cut
+
+sub _replace_special_chars_late {
+ my $self = shift;
+ my $paragraph = shift;
+
+ # < and >
+ $paragraph =~ s/(<|>)/\$$1\$/g;
+
+ # Replace | with $|$
+ $paragraph =~ s'\|'$|$'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
+}
+
+=item B<_split_delimited>
+
+Split the supplied string into two parts at approximately the
+specified word boundary. Special care is made to make sure that it
+does not split in the middle of some curly brackets.
+
+e.g. "this text is \textbf{very bold}" would not be split into
+"this text is \textbf{very" and " bold".
+
+ ($hunk1, $hunk2) = $self->_split_delimited( $para, $length);
+
+The length indicates the maximum length of hunk1.
+
+=cut
+
+# initially Supplied by hsmyers at sdragons.com
+# 10/25/01, utility to split \hbox
+# busting lines. Reformatted by TimJ to match module style.
+sub _split_delimited {
+ my $self = shift;
+ my $input = shift;
+ my $limit = shift;
+
+ # Return immediately if already small
+ return ($input, '') if length($input) < $limit;
+
+ my @output;
+ my $s = '';
+ my $t = '';
+ my $depth = 0;
+ my $token;
+
+ $input =~ s/\n/ /gm;
+ $input .= ' ';
+ foreach ( split ( //, $input ) ) {
+ $token .= $_;
+ if (/\{/) {
+ $depth++;
+ } elsif ( /}/ ) {
+ $depth--;
+ } elsif ( / / and $depth == 0) {
+ push @output, $token if ( $token and $token ne ' ' );
+ $token = '';
+ }
+ }
+
+ foreach (@output) {
+ if (length($s) < $limit) {
+ $s .= $_;
+ } else {
+ $t .= $_;
+ }
+ }
+
+ # Tidy up
+ $s =~ s/\s+$//;
+ $t =~ s/\s+$//;
+ return ($s,$t);
+}
+
+=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>, L<Pod::Simple>.
+
+=head1 AUTHORS
+
+Tim Jenness E<lt>tjenness at cpan.orgE<gt>
+
+Bug fixes and improvements have been received from: Simon Cozens
+E<lt>simon at cozens.netE<gt>, Mark A. Hershberger
+E<lt>mah at everybody.orgE<gt>, Marcel Grunauer
+E<lt>marcel at codewerk.comE<gt>, Hugh S Myers
+E<lt>hsmyers at sdragons.comE<gt>, Peter J Acklam
+E<lt>jacklam at math.uio.noE<gt>, Sudhi Herle E<lt>sudhi at herle.netE<gt>,
+Ariel Scolnicov E<lt>ariels at compugen.co.ilE<gt>,
+Adriano Rodrigues Ferreira E<lt>ferreira at triang.com.brE<gt>,
+R. de Vries E<lt>r.de.vries at dutchspace.nlE<gt> and
+Dave Mitchell E<lt>davem at iabyn.comE<gt>.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011 Tim Jenness.
+Copyright (C) 2000-2004 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$
+
+=end __PRIVATE__
+
+=cut
+
+1;
View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/-/compare/ba3aa87711921cb3cf0ad3d0d8d9e8f36108c7da...01f3672e3b08bbbceecbb19be33f56404e15f92c
--
View it on GitLab: https://xgitlab.cels.anl.gov/darshan/darshan/-/compare/ba3aa87711921cb3cf0ad3d0d8d9e8f36108c7da...01f3672e3b08bbbceecbb19be33f56404e15f92c
You're receiving this email because of your account on xgitlab.cels.anl.gov.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/darshan-commits/attachments/20200902/de5d1490/attachment-0001.html>
More information about the Darshan-commits
mailing list