File Coverage

blib/lib/Pod/Simple/LaTeX.pm
Criterion Covered Total %
statement 17 109 15.6
branch 1 54 1.8
condition 0 23 0.0
subroutine 7 17 41.1
pod 1 10 10.0
total 26 213 12.2


line stmt bran cond sub pod time code
1            
2             require 5;
3             package Pod::Simple::LaTeX;
4            
5             #use utf8;
6            
7             #sub DEBUG () {4};
8             #sub Pod::Simple::DEBUG () {4};
9             #sub Pod::Simple::PullParser::DEBUG () {4};
10            
11 1     1   38915 use strict;
  1         4  
  1         52  
12 1     1   7 use vars qw($VERSION @ISA %Escape $WRAP %Tagmap);
  1         2  
  1         119  
13             $VERSION = '0.06';
14 1     1   1205 use Pod::Simple::PullParser ();
  1         481512  
  1         33  
15 1     1   35 BEGIN {@ISA = ('Pod::Simple::PullParser')}
16            
17 1     1   12 use Carp ();
  1         1  
  1         34  
18 1 50   1   7515 BEGIN { *DEBUG = \&Pod::Simple::DEBUG unless defined &DEBUG }
19            
20             $WRAP = 1 unless defined $WRAP;
21            
22             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23             sub new {
24 0     0 1   my $new = shift->SUPER::new(@_);
25 0           $new->nix_X_codes(1);
26 0           $new->nbsp_for_S(1);
27 0           $new->accept_targets( qw( tex TeX TEX latex LaTeX LATEX ) );
28            
29             # $new->{'Tagmap'} = {%Tagmap};
30            
31             # $new->accept_codes(@_to_accept);
32             # $new->accept_codes('VerbatimFormatted');
33             # DEBUG > 2 and print "To accept: ", join(' ',@_to_accept), "\n";
34            
35 0           return $new;
36             }
37            
38             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39             sub run {
40 0     0 0   my $self = $_[0];
41 0 0         return $self->do_middle if $self->bare_output;
42             return
43 0   0       $self->do_beginning && $self->do_middle && $self->do_end;
44             }
45            
46            
47             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48             sub accent {
49 0     0 0   my $str_ref = shift;
50 0           my %latin_1 = (
51             "\xa0" => '~', #(no-break space)
52             "\xa1" => '!`',
53            
54             "\xa3" => q(\pounds{}),
55            
56             "\xa7" => q(\S{}),
57            
58             "\xa9" => q(\copyright{}),
59            
60             "\xac" => '\neg',
61            
62             "\xb1" => q($\pm$),
63            
64             "\xb4" => q($\prime$),
65             "\xb5" => q($\mu$),
66             "\xb6" => q(\P{}),
67             "\xb7" => q($\cdot{}$),
68            
69             "\xbf" => '?`',
70             "\xc0" => q(\`A),
71             "\xc1" => q(\'A),
72             "\xc2" => q(\^A),
73             "\xc3" => q(\~A),
74             "\xc4" => q(\"A),
75             "\xc5" => q(\AA{}),
76             "\xc6" => q(\AE{}),
77             "\xc7" => q(\cC),
78             "\xc8" => q(\`E),
79             "\xc9" => q(\'E),
80             "\xca" => q(\^E),
81             "\xcb" => q(\"E),
82             "\xcc" => q(\`I),
83             "\xcd" => q(\'I),
84             "\xce" => q(\^I),
85             "\xcf" => q(\"I),
86             #"\xd0" => q(\Dh), # Requires wasysym package
87             "\xd1" => q(\~N),
88             "\xd2" => q(\`O),
89             "\xd3" => q(\'O),
90             "\xd4" => q(\^O),
91             "\xd5" => q(\~O),
92             "\xd6" => q(\"O),
93             "\xd7" => q(\times{}),
94             "\xd8" => q(\O{}),
95             "\xd9" => q(\`U),
96             "\xda" => q(\'U),
97             "\xdb" => q(\^U),
98             "\xdc" => q(\"U),
99             "\xdd" => q(\'Y),
100             #"\xde" => q(\thorn), # Requires wasysym package
101             "\xdf" => q(\ss{}),
102             "\xe0" => q(\`a),
103             "\xe1" => q(\'a),
104             "\xe2" => q(\^a),
105             "\xe3" => q(\~a),
106             "\xe4" => q(\"a),
107             "\xe5" => q(\aa{}),
108             "\xe6" => q(\ae{}),
109             "\xe7" => q(\cc{}),
110             "\xe8" => q(\`e),
111             "\xe9" => q(\'e),
112             "\xea" => q(\^e),
113             "\xeb" => q(\"e),
114             "\xec" => q(\`{\i}),
115             "\xed" => q(\'{\i}),
116             "\xee" => q(\^{\i}),
117             "\xef" => q(\"{\i}),
118             #"\xf0" => q(\dh), # Requires wasysym package
119             "\xf1" => q(\~n),
120             "\xf2" => q(\`o),
121             "\xf3" => q(\'o),
122             "\xf4" => q(\^o),
123             "\xf5" => q(\~o),
124             "\xf6" => q(\"o),
125             "\xf7" => q(\div{}),
126             "\xf8" => q(\o{}),
127             "\xf9" => q(\`u),
128             "\xfa" => q(\'u),
129             "\xfb" => q(\^u),
130             "\xfc" => q(\"u),
131             "\xfd" => q(\'y),
132             #"\xfe" => q(\thorn), # Requires wasysym package
133             "\xff" => q(\"y),
134             );
135            
136 0           $$str_ref =~ s/$_/$latin_1{$_}/eg for keys %latin_1;
  0            
137             #$$str_ref =~ s{\\(\d)}{"FIXME XXX $1\$"}eg; # XXX Aiyee, s/// escaping and $ madness ensues
138             }
139             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140            
141             sub do_middle { # the main work
142 0     0 0   my $self = $_[0];
143 0           my $fh = $self->{'output_fh'};
144            
145 0   0       $self->{in_section} ||= 0; # Note when entering/leaving section
146            
147 0           my %default_tags = (
148             B => [ "\\textbf{","}\n" ],
149             Data => [ "\n","\n" ],
150             Document => [ "\\begin{document}\n","\\end{document}\n" ],
151             F => [ "\\textsl{","}\n" ],
152             I => [ "\\textsl{","}\n" ],
153             Para => [ "\n\n","\n\n" ],
154             L => [ "\\textsl{","}\n" ],
155             Verbatim => [ "\\begin{verbatim}\n","\\end{verbatim}\n" ],
156             VerbatimFormatted => [ "\\begin{verbatim}\n","\\end{verbatim}\n" ],
157             VerbatimI => [ "\\begin{verbatim}\\textsl{","}\\end{verbatim}" ],
158             VerbatimB => [ "\\begin{verbatim}\\textbf{","}\\end{verbatim}" ],
159             VerbatimBI => [ "\\begin{verbatim}\\textsl{\\textbf{","}}\\end{verbatim}" ],
160            
161             head1 => [ "\\section{","}\n" ],
162             head2 => [ "\\subsection{","}\n" ],
163             head3 => [ "\\subsubsection{","}\n" ],
164             head4 => [ "\\paragraph{","}\n" ],
165             head5 => [ "\\subparagraph{","}\n" ],
166            
167             'item-block' => [ '','' ],
168             'item-bullet' => [ "\\item{}\n",'' ],
169             'item-number' => [ "\\item{}\n",'' ],
170             'item-text' => [ "\\item{}\n",'' ],
171            
172             'over-block' => [ "\\begin{verbatim}\n","\\end{verbatim}" ],
173             'over-bullet' => [ "\\begin{itemize}\n","\\end{itemize}\n" ],
174             'over-number' => [ "\\begin{enumerate}\n","\\end{enumerate}\n" ],
175             'over-text' => [ "\\begin{itemize}\n","\\end{itemize}\n" ],
176             );
177            
178 0           while (my $token = $self->get_token) {
179 0           my $type = $token->type;
180 0 0         if($type eq 'start') {
    0          
    0          
181 0           my $name = $token->tagname;
182             DEBUG > 1 and print "+$type <", $token->tagname,
183 0           "> ( ", map("<$_> ", %{$token->attr_hash}), ")\n";
184 0 0         print $fh $default_tags{$name}[0] if exists $default_tags{$name};
185            
186 0 0         $self->{in_section}++ if $name =~ /^head/;
187 0 0         $self->{verbatim}++ if $name =~/^Verbatim/;
188 0 0 0       $self->{in_c}++ if $name eq 'C' or $name eq 'F';
189 0 0 0       if($name eq 'C' or $name eq 'F') {
190 0 0         if($self->{in_section} > 0) {
191 0           print $fh "\\texttt{" # Just use \textsl{} inside \section{} et al
192             }
193             else {
194 0           $self->{verbatim}++;
195 0           print $fh "\\texttt{" # Just use \textsl{} inside \section{} et al
196             }
197             }
198             }
199             elsif($type eq 'end') {
200 0           my $name = $token->tagname;
201 0           DEBUG > 1 and print "-$type <", $token->tagname, ">\n";
202 0 0         print $fh $default_tags{$name}[1] if exists $default_tags{$name};
203            
204 0 0         $self->{in_section}-- if $name =~ /^head/;
205 0 0         $self->{verbatim}-- if $name =~/^Verbatim/;
206 0 0 0       $self->{in_c}-- if $name eq 'C' or $name eq 'F';
207 0 0 0       if($name eq 'C' or $name eq 'F') {
208 0 0         if($self->{in_section} > 0) {
209 0           print $fh "}\n" # Just use \textsl{} inside \section{} et al
210             }
211             else {
212 0           $self->{verbatim}--;
213 0           print $fh "}\n" # Skip verbatim inside \section{}
214             }
215             }
216             }
217             elsif($type eq 'text') {
218 0           my $text = $token->text;
219 0           DEBUG > 1 and print "=$type <$text>\n";
220            
221 0 0         $self->{in_section} > 0 and do { print $fh texesc($text); next };
  0            
  0            
222 0 0         $self->{in_c} > 0 and do { print $fh texesc($text); next };
  0            
  0            
223 0 0         if($self->{verbatim} > 0) {
224 0           print $fh $text;
225             }
226             else {
227 0           print $fh texesc($text);
228             }
229             }
230             else {
231 0           die "Unknown tag type <$type> encountered!\n";
232             }
233             }
234 0           return 1;
235             }
236            
237             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
238             sub do_beginning {
239 0     0 0   my $self = $_[0];
240 0           my $fh = $self->{'output_fh'};
241 0           return print $fh join '',
242             $self->doc_init,
243             $self->doc_info,
244             $self->doc_start,
245             "\n"
246             ;
247             }
248            
249             sub do_end {
250 0     0 0   my $self = $_[0];
251 0           my $fh = $self->{'output_fh'};
252             }
253            
254             ###########################################################################
255             # Override these as necessary for further customization
256            
257            
258             sub doc_init {
259 0     0 0   return <<'END';
260             \documentclass{article}
261             %\usepackage{alltt}
262            
263             END
264             }
265            
266             sub doc_info {
267 0     0 0   my $self = $_[0];
268            
269 0   0       my $class = ref($self) || $self;
270            
271 0           my $tag = __PACKAGE__ . ' ' . $VERSION;
272            
273 0 0         unless($class eq __PACKAGE__) {
274 0           $tag = " ($tag)";
275 0 0         $tag = " v" . $self->VERSION . $tag if defined $self->VERSION;
276 0           $tag = $class . $tag;
277             }
278            
279 0           return sprintf "%% %s using %s v%s under Perl v%s at %s GMT\n",
280             $tag,
281             $ISA[0], $ISA[0]->VERSION(),
282             $], scalar(gmtime),
283             ;
284             }
285            
286             sub doc_start {
287 0     0 0   my $self = $_[0];
288 0           my $title = $self->get_short_title();
289 0           DEBUG and print "Short Title: <$title>\n";
290 0 0         $title .= ' ' if length $title;
291            
292 0           $title =~ s/ *$/ /s;
293 0           $title =~ s/^ //s;
294 0           $title =~ s/ $//s;
295            
296 0           DEBUG and print "Title0: <$title>\n";
297 0           $title = texesc($title);
298 0           DEBUG and print "Title1: <$title>\n";
299            
300 0           return '';
301             }
302            
303             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304             #-------------------------------------------------------------------------
305            
306 1     1   14 use integer;
  1         3  
  1         11  
307             my $escaperange;
308             sub texesc {
309 0 0   0 0   if(!defined wantarray) { # alter in place! -- just leave @_
    0          
310             } elsif(wantarray) { # return an array
311 0           @_ = map "$_", @_;
312             } else { # return a single scalar
313 0           @_ = (join '', @_);
314             }
315            
316 0 0         unless($escaperange) {
317 0   0       $escaperange =
318             join '', '([',
319             '\\\\', grep( not($_ eq '.' or $_ eq '//'), keys %Escape ),
320             '])';
321 0           $Escape{'\\\\'} = '\\\\';
322 0           $escaperange = qr/$escaperange/;
323             }
324 0           for(@_) { s/$escaperange/$Escape{$1}/g }
  0            
325 0           for(@_) { accent(\$_); }
  0            
326            
327 0 0         return $_[0] unless wantarray;
328 0           return @_;
329             }
330            
331             %Escape = ( # Backslashes have to be taken care of specially
332             '\#' => '\\#',
333             '%' => '\%', # LaTeX comments
334             '<' => '\textless{}',
335             '>' => '\textgreater{}',
336             # '~' => '\textasciitilde{}',
337             '{' => '\{',
338             '}' => '\}',
339             '&' => '\&',
340             '$' => '\$', # Math-mode
341             '^' => '\^{}', # Math-mode superscript
342             '_' => '\_', # Math-mode subscript
343             # "\cm" => "\n", # Newlines
344             # "\cj" => "\n",
345             );
346            
347             1;
348            
349             __END__