line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Pod::PlainText -- Convert POD data to formatted ASCII text. |
2
|
|
|
|
|
|
|
# $Id: Text.pm,v 2.1 1999/09/20 11:53:33 eagle Exp $ |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Copyright 1999-2000 by Russ Allbery |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify it |
7
|
|
|
|
|
|
|
# under the same terms as Perl itself. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# This module is intended to be a replacement for Pod::Text, and attempts to |
10
|
|
|
|
|
|
|
# match its output except for some specific circumstances where other |
11
|
|
|
|
|
|
|
# decisions seemed to produce better output. It uses Pod::Parser and is |
12
|
|
|
|
|
|
|
# designed to be very easy to subclass. |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
############################################################################ |
15
|
|
|
|
|
|
|
# Modules and declarations |
16
|
|
|
|
|
|
|
############################################################################ |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
package Pod::PlainText; |
19
|
12
|
|
|
12
|
|
140132
|
use strict; |
|
12
|
|
|
|
|
109
|
|
|
12
|
|
|
|
|
377
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
require 5.005; |
22
|
|
|
|
|
|
|
|
23
|
12
|
|
|
12
|
|
56
|
use Carp qw(carp croak); |
|
12
|
|
|
|
|
19
|
|
|
12
|
|
|
|
|
510
|
|
24
|
12
|
|
|
12
|
|
4935
|
use Pod::Select (); |
|
12
|
|
|
|
|
32
|
|
|
12
|
|
|
|
|
302
|
|
25
|
|
|
|
|
|
|
|
26
|
12
|
|
|
12
|
|
61
|
use vars qw(@ISA %ESCAPES $VERSION); |
|
12
|
|
|
|
|
19
|
|
|
12
|
|
|
|
|
920
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# We inherit from Pod::Select instead of Pod::Parser so that we can be used |
29
|
|
|
|
|
|
|
# by Pod::Usage. |
30
|
|
|
|
|
|
|
@ISA = qw(Pod::Select); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$VERSION = '2.07'; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
BEGIN { |
35
|
12
|
50
|
|
12
|
|
39743
|
if ($] < 5.006) { |
36
|
0
|
|
|
|
|
0
|
require Symbol; |
37
|
0
|
|
|
|
|
0
|
import Symbol; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
############################################################################ |
42
|
|
|
|
|
|
|
# Table of supported E<> escapes |
43
|
|
|
|
|
|
|
############################################################################ |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# This table is taken near verbatim from Pod::PlainText in Pod::Parser, |
46
|
|
|
|
|
|
|
# which got it near verbatim from the original Pod::Text. It is therefore |
47
|
|
|
|
|
|
|
# credited to Tom Christiansen, and I'm glad I didn't have to write it. :) |
48
|
|
|
|
|
|
|
%ESCAPES = ( |
49
|
|
|
|
|
|
|
'amp' => '&', # ampersand |
50
|
|
|
|
|
|
|
'lt' => '<', # left chevron, less-than |
51
|
|
|
|
|
|
|
'gt' => '>', # right chevron, greater-than |
52
|
|
|
|
|
|
|
'quot' => '"', # double quote |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
"Aacute" => "\xC1", # capital A, acute accent |
55
|
|
|
|
|
|
|
"aacute" => "\xE1", # small a, acute accent |
56
|
|
|
|
|
|
|
"Acirc" => "\xC2", # capital A, circumflex accent |
57
|
|
|
|
|
|
|
"acirc" => "\xE2", # small a, circumflex accent |
58
|
|
|
|
|
|
|
"AElig" => "\xC6", # capital AE diphthong (ligature) |
59
|
|
|
|
|
|
|
"aelig" => "\xE6", # small ae diphthong (ligature) |
60
|
|
|
|
|
|
|
"Agrave" => "\xC0", # capital A, grave accent |
61
|
|
|
|
|
|
|
"agrave" => "\xE0", # small a, grave accent |
62
|
|
|
|
|
|
|
"Aring" => "\xC5", # capital A, ring |
63
|
|
|
|
|
|
|
"aring" => "\xE5", # small a, ring |
64
|
|
|
|
|
|
|
"Atilde" => "\xC3", # capital A, tilde |
65
|
|
|
|
|
|
|
"atilde" => "\xE3", # small a, tilde |
66
|
|
|
|
|
|
|
"Auml" => "\xC4", # capital A, dieresis or umlaut mark |
67
|
|
|
|
|
|
|
"auml" => "\xE4", # small a, dieresis or umlaut mark |
68
|
|
|
|
|
|
|
"Ccedil" => "\xC7", # capital C, cedilla |
69
|
|
|
|
|
|
|
"ccedil" => "\xE7", # small c, cedilla |
70
|
|
|
|
|
|
|
"Eacute" => "\xC9", # capital E, acute accent |
71
|
|
|
|
|
|
|
"eacute" => "\xE9", # small e, acute accent |
72
|
|
|
|
|
|
|
"Ecirc" => "\xCA", # capital E, circumflex accent |
73
|
|
|
|
|
|
|
"ecirc" => "\xEA", # small e, circumflex accent |
74
|
|
|
|
|
|
|
"Egrave" => "\xC8", # capital E, grave accent |
75
|
|
|
|
|
|
|
"egrave" => "\xE8", # small e, grave accent |
76
|
|
|
|
|
|
|
"ETH" => "\xD0", # capital Eth, Icelandic |
77
|
|
|
|
|
|
|
"eth" => "\xF0", # small eth, Icelandic |
78
|
|
|
|
|
|
|
"Euml" => "\xCB", # capital E, dieresis or umlaut mark |
79
|
|
|
|
|
|
|
"euml" => "\xEB", # small e, dieresis or umlaut mark |
80
|
|
|
|
|
|
|
"Iacute" => "\xCD", # capital I, acute accent |
81
|
|
|
|
|
|
|
"iacute" => "\xED", # small i, acute accent |
82
|
|
|
|
|
|
|
"Icirc" => "\xCE", # capital I, circumflex accent |
83
|
|
|
|
|
|
|
"icirc" => "\xEE", # small i, circumflex accent |
84
|
|
|
|
|
|
|
"Igrave" => "\xCD", # capital I, grave accent |
85
|
|
|
|
|
|
|
"igrave" => "\xED", # small i, grave accent |
86
|
|
|
|
|
|
|
"Iuml" => "\xCF", # capital I, dieresis or umlaut mark |
87
|
|
|
|
|
|
|
"iuml" => "\xEF", # small i, dieresis or umlaut mark |
88
|
|
|
|
|
|
|
"Ntilde" => "\xD1", # capital N, tilde |
89
|
|
|
|
|
|
|
"ntilde" => "\xF1", # small n, tilde |
90
|
|
|
|
|
|
|
"Oacute" => "\xD3", # capital O, acute accent |
91
|
|
|
|
|
|
|
"oacute" => "\xF3", # small o, acute accent |
92
|
|
|
|
|
|
|
"Ocirc" => "\xD4", # capital O, circumflex accent |
93
|
|
|
|
|
|
|
"ocirc" => "\xF4", # small o, circumflex accent |
94
|
|
|
|
|
|
|
"Ograve" => "\xD2", # capital O, grave accent |
95
|
|
|
|
|
|
|
"ograve" => "\xF2", # small o, grave accent |
96
|
|
|
|
|
|
|
"Oslash" => "\xD8", # capital O, slash |
97
|
|
|
|
|
|
|
"oslash" => "\xF8", # small o, slash |
98
|
|
|
|
|
|
|
"Otilde" => "\xD5", # capital O, tilde |
99
|
|
|
|
|
|
|
"otilde" => "\xF5", # small o, tilde |
100
|
|
|
|
|
|
|
"Ouml" => "\xD6", # capital O, dieresis or umlaut mark |
101
|
|
|
|
|
|
|
"ouml" => "\xF6", # small o, dieresis or umlaut mark |
102
|
|
|
|
|
|
|
"szlig" => "\xDF", # small sharp s, German (sz ligature) |
103
|
|
|
|
|
|
|
"THORN" => "\xDE", # capital THORN, Icelandic |
104
|
|
|
|
|
|
|
"thorn" => "\xFE", # small thorn, Icelandic |
105
|
|
|
|
|
|
|
"Uacute" => "\xDA", # capital U, acute accent |
106
|
|
|
|
|
|
|
"uacute" => "\xFA", # small u, acute accent |
107
|
|
|
|
|
|
|
"Ucirc" => "\xDB", # capital U, circumflex accent |
108
|
|
|
|
|
|
|
"ucirc" => "\xFB", # small u, circumflex accent |
109
|
|
|
|
|
|
|
"Ugrave" => "\xD9", # capital U, grave accent |
110
|
|
|
|
|
|
|
"ugrave" => "\xF9", # small u, grave accent |
111
|
|
|
|
|
|
|
"Uuml" => "\xDC", # capital U, dieresis or umlaut mark |
112
|
|
|
|
|
|
|
"uuml" => "\xFC", # small u, dieresis or umlaut mark |
113
|
|
|
|
|
|
|
"Yacute" => "\xDD", # capital Y, acute accent |
114
|
|
|
|
|
|
|
"yacute" => "\xFD", # small y, acute accent |
115
|
|
|
|
|
|
|
"yuml" => "\xFF", # small y, dieresis or umlaut mark |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
"lchevron" => "\xAB", # left chevron (double less than) |
118
|
|
|
|
|
|
|
"rchevron" => "\xBB", # right chevron (double greater than) |
119
|
|
|
|
|
|
|
); |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
############################################################################ |
123
|
|
|
|
|
|
|
# Initialization |
124
|
|
|
|
|
|
|
############################################################################ |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Initialize the object. Must be sure to call our parent initializer. |
127
|
|
|
|
|
|
|
sub initialize { |
128
|
12
|
|
|
12
|
0
|
2809
|
my $self = shift; |
129
|
|
|
|
|
|
|
|
130
|
12
|
50
|
|
|
|
144
|
$$self{alt} = 0 unless defined $$self{alt}; |
131
|
12
|
50
|
|
|
|
46
|
$$self{indent} = 4 unless defined $$self{indent}; |
132
|
12
|
50
|
|
|
|
45
|
$$self{loose} = 0 unless defined $$self{loose}; |
133
|
12
|
50
|
|
|
|
41
|
$$self{sentence} = 0 unless defined $$self{sentence}; |
134
|
12
|
50
|
|
|
|
52
|
$$self{width} = 76 unless defined $$self{width}; |
135
|
|
|
|
|
|
|
|
136
|
12
|
|
|
|
|
28
|
$$self{INDENTS} = []; # Stack of indentations. |
137
|
12
|
|
|
|
|
28
|
$$self{MARGIN} = $$self{indent}; # Current left margin in spaces. |
138
|
|
|
|
|
|
|
|
139
|
12
|
|
|
|
|
107
|
return $self->SUPER::initialize; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
############################################################################ |
144
|
|
|
|
|
|
|
# Core overrides |
145
|
|
|
|
|
|
|
############################################################################ |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# Called for each command paragraph. Gets the command, the associated |
148
|
|
|
|
|
|
|
# paragraph, the line number, and a Pod::Paragraph object. Just dispatches |
149
|
|
|
|
|
|
|
# the command to a method named the same as the command. =cut is handled |
150
|
|
|
|
|
|
|
# internally by Pod::Parser. |
151
|
|
|
|
|
|
|
sub command { |
152
|
61
|
|
|
61
|
0
|
722
|
my $self = shift; |
153
|
61
|
|
|
|
|
81
|
my $command = shift; |
154
|
61
|
100
|
|
|
|
349
|
return if $command eq 'pod'; |
155
|
52
|
50
|
66
|
|
|
113
|
return if ($$self{EXCLUDE} && $command ne 'end'); |
156
|
52
|
100
|
|
|
|
85
|
if (defined $$self{ITEM}) { |
157
|
2
|
|
|
|
|
9
|
$self->item ("\n"); |
158
|
2
|
|
|
|
|
5
|
local $_ = "\n"; |
159
|
2
|
50
|
|
|
|
6
|
$self->output($_) if($command eq 'back'); |
160
|
|
|
|
|
|
|
} |
161
|
52
|
|
|
|
|
91
|
$command = 'cmd_' . $command; |
162
|
52
|
|
|
|
|
206
|
return $self->$command (@_); |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# Called for a verbatim paragraph. Gets the paragraph, the line number, and |
166
|
|
|
|
|
|
|
# a Pod::Paragraph object. Just output it verbatim, but with tabs converted |
167
|
|
|
|
|
|
|
# to spaces. |
168
|
|
|
|
|
|
|
sub verbatim { |
169
|
6
|
|
|
6
|
0
|
15
|
my $self = shift; |
170
|
6
|
50
|
|
|
|
22
|
return if $$self{EXCLUDE}; |
171
|
6
|
100
|
|
|
|
32
|
$self->item if defined $$self{ITEM}; |
172
|
6
|
|
|
|
|
13
|
local $_ = shift; |
173
|
6
|
100
|
|
|
|
216
|
return if /^\s*$/; |
174
|
3
|
|
|
|
|
22
|
s/^(\s*\S+)/(' ' x $$self{MARGIN}) . $1/gme; |
|
7
|
|
|
|
|
35
|
|
175
|
3
|
|
|
|
|
16
|
return $self->output($_); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Called for a regular text block. Gets the paragraph, the line number, and |
179
|
|
|
|
|
|
|
# a Pod::Paragraph object. Perform interpolation and output the results. |
180
|
|
|
|
|
|
|
sub textblock { |
181
|
81
|
|
|
81
|
0
|
134
|
my $self = shift; |
182
|
81
|
100
|
|
|
|
188
|
return if $$self{EXCLUDE}; |
183
|
78
|
100
|
|
|
|
139
|
if($$self{VERBATIM}) { |
184
|
4
|
|
|
|
|
9
|
$self->output($_[0]); |
185
|
4
|
|
|
|
|
51
|
return; |
186
|
|
|
|
|
|
|
} |
187
|
74
|
|
|
|
|
98
|
local $_ = shift; |
188
|
74
|
|
|
|
|
90
|
my $line = shift; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# Perform a little magic to collapse multiple L<> references. This is |
191
|
|
|
|
|
|
|
# here mostly for backwards-compatibility. We'll just rewrite the whole |
192
|
|
|
|
|
|
|
# thing into actual text at this part, bypassing the whole internal |
193
|
|
|
|
|
|
|
# sequence parsing thing. |
194
|
74
|
|
|
|
|
120
|
s{ |
195
|
|
|
|
|
|
|
( |
196
|
|
|
|
|
|
|
L< # A link of the form L. |
197
|
|
|
|
|
|
|
/ |
198
|
|
|
|
|
|
|
( |
199
|
|
|
|
|
|
|
[:\w]+ # The item has to be a simple word... |
200
|
|
|
|
|
|
|
(\(\))? # ...or simple function. |
201
|
|
|
|
|
|
|
) |
202
|
|
|
|
|
|
|
> |
203
|
|
|
|
|
|
|
( |
204
|
|
|
|
|
|
|
,?\s+(and\s+)? # Allow lots of them, conjuncted. |
205
|
|
|
|
|
|
|
L< |
206
|
|
|
|
|
|
|
/ |
207
|
|
|
|
|
|
|
( |
208
|
|
|
|
|
|
|
[:\w]+ |
209
|
|
|
|
|
|
|
(\(\))? |
210
|
|
|
|
|
|
|
) |
211
|
|
|
|
|
|
|
> |
212
|
|
|
|
|
|
|
)+ |
213
|
|
|
|
|
|
|
) |
214
|
|
|
|
|
|
|
} { |
215
|
0
|
|
|
|
|
0
|
local $_ = $1; |
216
|
0
|
|
|
|
|
0
|
s%L([^>]+)>%$1%g; |
217
|
0
|
|
|
|
|
0
|
my @items = split /(?:,?\s+(?:and\s+)?)/; |
218
|
0
|
|
|
|
|
0
|
my $string = "the "; |
219
|
0
|
|
|
|
|
0
|
my $i; |
220
|
0
|
|
|
|
|
0
|
for ($i = 0; $i < @items; $i++) { |
221
|
0
|
|
|
|
|
0
|
$string .= $items[$i]; |
222
|
0
|
0
|
0
|
|
|
0
|
$string .= ", " if @items > 2 && $i != $#items; |
223
|
0
|
0
|
|
|
|
0
|
$string .= " and " if ($i == $#items - 1); |
224
|
|
|
|
|
|
|
} |
225
|
0
|
|
|
|
|
0
|
$string .= " entries elsewhere in this document"; |
226
|
0
|
|
|
|
|
0
|
$string; |
227
|
|
|
|
|
|
|
}gex; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Now actually interpolate and output the paragraph. |
230
|
74
|
|
|
|
|
4552
|
$_ = $self->interpolate ($_, $line); |
231
|
74
|
|
|
|
|
821
|
s/\s*$/\n/s; |
232
|
74
|
100
|
|
|
|
184
|
if (defined $$self{ITEM}) { |
233
|
13
|
|
|
|
|
54
|
$self->item ($_ . "\n"); |
234
|
|
|
|
|
|
|
} else { |
235
|
61
|
|
|
|
|
265
|
$self->output ($self->reformat ($_ . "\n")); |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Called for an interior sequence. Gets the command, argument, and a |
240
|
|
|
|
|
|
|
# Pod::InteriorSequence object and is expected to return the resulting text. |
241
|
|
|
|
|
|
|
# Calls code, bold, italic, file, and link to handle those types of |
242
|
|
|
|
|
|
|
# sequences, and handles S<>, E<>, X<>, and Z<> directly. |
243
|
|
|
|
|
|
|
sub interior_sequence { |
244
|
107
|
|
|
107
|
0
|
228
|
my $self = shift; |
245
|
107
|
|
|
|
|
121
|
my $command = shift; |
246
|
107
|
|
|
|
|
137
|
local $_ = shift; |
247
|
107
|
50
|
33
|
|
|
356
|
return '' if ($command eq 'X' || $command eq 'Z'); |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# Expand escapes into the actual character now, carping if invalid. |
250
|
107
|
100
|
|
|
|
166
|
if ($command eq 'E') { |
251
|
10
|
50
|
|
|
|
342
|
return $ESCAPES{$_} if defined $ESCAPES{$_}; |
252
|
0
|
|
|
|
|
0
|
carp "Unknown escape: E<$_>"; |
253
|
0
|
|
|
|
|
0
|
return "E<$_>"; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# For all the other sequences, empty content produces no output. |
257
|
97
|
100
|
|
|
|
211
|
return if $_ eq ''; |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
# For S<>, compress all internal whitespace and then map spaces to \01. |
260
|
|
|
|
|
|
|
# When we output the text, we'll map this back. |
261
|
96
|
100
|
|
|
|
163
|
if ($command eq 'S') { |
262
|
3
|
|
|
|
|
4
|
s/\s{2,}/ /g; |
263
|
3
|
|
|
|
|
3
|
tr/ /\01/; |
264
|
3
|
|
|
|
|
99
|
return $_; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Anything else needs to get dispatched to another method. |
268
|
93
|
100
|
|
|
|
220
|
if ($command eq 'B') { return $self->seq_b ($_) } |
|
28
|
100
|
|
|
|
77
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
269
|
26
|
|
|
|
|
93
|
elsif ($command eq 'C') { return $self->seq_c ($_) } |
270
|
2
|
|
|
|
|
23
|
elsif ($command eq 'F') { return $self->seq_f ($_) } |
271
|
14
|
|
|
|
|
49
|
elsif ($command eq 'I') { return $self->seq_i ($_) } |
272
|
23
|
|
|
|
|
58
|
elsif ($command eq 'L') { return $self->seq_l ($_) } |
273
|
0
|
|
|
|
|
0
|
else { carp "Unknown sequence $command<$_>" } |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# Called for each paragraph that's actually part of the POD. We take |
277
|
|
|
|
|
|
|
# advantage of this opportunity to untabify the input. |
278
|
|
|
|
|
|
|
sub preprocess_paragraph { |
279
|
158
|
|
|
158
|
0
|
5745
|
my $self = shift; |
280
|
158
|
|
|
|
|
240
|
local $_ = shift; |
281
|
158
|
|
|
|
|
408
|
1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me; |
|
0
|
|
|
|
|
0
|
|
282
|
158
|
|
|
|
|
3785
|
return $_; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
############################################################################ |
287
|
|
|
|
|
|
|
# Command paragraphs |
288
|
|
|
|
|
|
|
############################################################################ |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# All command paragraphs take the paragraph and the line number. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# First level heading. |
293
|
|
|
|
|
|
|
sub cmd_head1 { |
294
|
16
|
|
|
16
|
0
|
24
|
my $self = shift; |
295
|
16
|
|
|
|
|
28
|
local $_ = shift; |
296
|
16
|
|
|
|
|
62
|
s/\s+$//s; |
297
|
16
|
|
|
|
|
967
|
$_ = $self->interpolate ($_, shift); |
298
|
16
|
50
|
|
|
|
58
|
if ($$self{alt}) { |
299
|
0
|
|
|
|
|
0
|
$self->output ("\n==== $_ ====\n\n"); |
300
|
|
|
|
|
|
|
} else { |
301
|
16
|
50
|
|
|
|
41
|
$_ .= "\n" if $$self{loose}; |
302
|
16
|
|
|
|
|
68
|
$self->output ($_ . "\n"); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# Second level heading. |
307
|
|
|
|
|
|
|
sub cmd_head2 { |
308
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
309
|
0
|
|
|
|
|
0
|
local $_ = shift; |
310
|
0
|
|
|
|
|
0
|
s/\s+$//s; |
311
|
0
|
|
|
|
|
0
|
$_ = $self->interpolate ($_, shift); |
312
|
0
|
0
|
|
|
|
0
|
if ($$self{alt}) { |
313
|
0
|
|
|
|
|
0
|
$self->output ("\n== $_ ==\n\n"); |
314
|
|
|
|
|
|
|
} else { |
315
|
0
|
0
|
|
|
|
0
|
$_ .= "\n" if $$self{loose}; |
316
|
0
|
|
|
|
|
0
|
$self->output (' ' x ($$self{indent} / 2) . $_ . "\n"); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# third level heading - not strictly perlpodspec compliant |
321
|
|
|
|
|
|
|
sub cmd_head3 { |
322
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
323
|
0
|
|
|
|
|
0
|
local $_ = shift; |
324
|
0
|
|
|
|
|
0
|
s/\s+$//s; |
325
|
0
|
|
|
|
|
0
|
$_ = $self->interpolate ($_, shift); |
326
|
0
|
0
|
|
|
|
0
|
if ($$self{alt}) { |
327
|
0
|
|
|
|
|
0
|
$self->output ("\n= $_ =\n"); |
328
|
|
|
|
|
|
|
} else { |
329
|
0
|
0
|
|
|
|
0
|
$_ .= "\n" if $$self{loose}; |
330
|
0
|
|
|
|
|
0
|
$self->output (' ' x ($$self{indent}) . $_ . "\n"); |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# fourth level heading - not strictly perlpodspec compliant |
335
|
|
|
|
|
|
|
# just like head3 |
336
|
|
|
|
|
|
|
*cmd_head4 = \&cmd_head3; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# Start a list. |
339
|
|
|
|
|
|
|
sub cmd_over { |
340
|
7
|
|
|
7
|
0
|
15
|
my $self = shift; |
341
|
7
|
|
|
|
|
15
|
local $_ = shift; |
342
|
7
|
50
|
|
|
|
44
|
unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} } |
|
0
|
|
|
|
|
0
|
|
343
|
7
|
|
|
|
|
22
|
push (@{ $$self{INDENTS} }, $$self{MARGIN}); |
|
7
|
|
|
|
|
34
|
|
344
|
7
|
|
|
|
|
145
|
$$self{MARGIN} += ($_ + 0); |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# End a list. |
348
|
|
|
|
|
|
|
sub cmd_back { |
349
|
7
|
|
|
7
|
0
|
21
|
my $self = shift; |
350
|
7
|
|
|
|
|
13
|
$$self{MARGIN} = pop @{ $$self{INDENTS} }; |
|
7
|
|
|
|
|
23
|
|
351
|
7
|
50
|
|
|
|
138
|
unless (defined $$self{MARGIN}) { |
352
|
0
|
|
|
|
|
0
|
carp 'Unmatched =back'; |
353
|
0
|
|
|
|
|
0
|
$$self{MARGIN} = $$self{indent}; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# An individual list item. |
358
|
|
|
|
|
|
|
sub cmd_item { |
359
|
16
|
|
|
16
|
0
|
29
|
my $self = shift; |
360
|
16
|
50
|
|
|
|
44
|
if (defined $$self{ITEM}) { $self->item } |
|
0
|
|
|
|
|
0
|
|
361
|
16
|
|
|
|
|
24
|
local $_ = shift; |
362
|
16
|
|
|
|
|
56
|
s/\s+$//s; |
363
|
16
|
|
|
|
|
847
|
$$self{ITEM} = $self->interpolate ($_); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# Begin a block for a particular translator. Setting VERBATIM triggers |
367
|
|
|
|
|
|
|
# special handling in textblock(). |
368
|
|
|
|
|
|
|
sub cmd_begin { |
369
|
2
|
|
|
2
|
0
|
3
|
my $self = shift; |
370
|
2
|
|
|
|
|
3
|
local $_ = shift; |
371
|
2
|
50
|
|
|
|
18
|
my ($kind) = /^(\S+)/ or return; |
372
|
2
|
100
|
|
|
|
6
|
if ($kind eq 'text') { |
373
|
1
|
|
|
|
|
20
|
$$self{VERBATIM} = 1; |
374
|
|
|
|
|
|
|
} else { |
375
|
1
|
|
|
|
|
14
|
$$self{EXCLUDE} = 1; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# End a block for a particular translator. We assume that all =begin/=end |
380
|
|
|
|
|
|
|
# pairs are properly closed. |
381
|
|
|
|
|
|
|
sub cmd_end { |
382
|
2
|
|
|
2
|
0
|
5
|
my $self = shift; |
383
|
2
|
|
|
|
|
3
|
$$self{EXCLUDE} = 0; |
384
|
2
|
|
|
|
|
30
|
$$self{VERBATIM} = 0; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# One paragraph for a particular translator. Ignore it unless it's intended |
388
|
|
|
|
|
|
|
# for text, in which case we treat it as a verbatim text block. |
389
|
|
|
|
|
|
|
sub cmd_for { |
390
|
2
|
|
|
2
|
0
|
3
|
my $self = shift; |
391
|
2
|
|
|
|
|
2
|
local $_ = shift; |
392
|
2
|
|
|
|
|
4
|
my $line = shift; |
393
|
2
|
100
|
|
|
|
28
|
return unless s/^text\b[ \t]*\r?\n?//; |
394
|
1
|
|
|
|
|
6
|
$self->verbatim ($_, $line); |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# just a dummy method for the time being |
398
|
|
|
|
|
|
|
sub cmd_encoding { |
399
|
0
|
|
|
0
|
0
|
0
|
return; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
############################################################################ |
403
|
|
|
|
|
|
|
# Interior sequences |
404
|
|
|
|
|
|
|
############################################################################ |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
# The simple formatting ones. These are here mostly so that subclasses can |
407
|
|
|
|
|
|
|
# override them and do more complicated things. |
408
|
28
|
50
|
|
28
|
0
|
1200
|
sub seq_b { return $_[0]{alt} ? "``$_[1]''" : $_[1] } |
409
|
26
|
50
|
|
26
|
0
|
1152
|
sub seq_c { return $_[0]{alt} ? "``$_[1]''" : "`$_[1]'" } |
410
|
2
|
50
|
|
2
|
0
|
57
|
sub seq_f { return $_[0]{alt} ? "\"$_[1]\"" : $_[1] } |
411
|
14
|
|
|
14
|
0
|
605
|
sub seq_i { return '*' . $_[1] . '*' } |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
# The complicated one. Handle links. Since this is plain text, we can't |
414
|
|
|
|
|
|
|
# actually make any real links, so this is all to figure out what text we |
415
|
|
|
|
|
|
|
# print out. |
416
|
|
|
|
|
|
|
sub seq_l { |
417
|
23
|
|
|
23
|
0
|
33
|
my $self = shift; |
418
|
23
|
|
|
|
|
25
|
local $_ = shift; |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# Smash whitespace in case we were split across multiple lines. |
421
|
23
|
|
|
|
|
81
|
s/\s+/ /g; |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
# If we were given any explicit text, just output it. |
424
|
23
|
100
|
|
|
|
64
|
if (/^([^|]+)\|/) { return $1 } |
|
9
|
|
|
|
|
211
|
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# Okay, leading and trailing whitespace isn't important; get rid of it. |
427
|
14
|
|
|
|
|
34
|
s/^\s+//; |
428
|
14
|
|
|
|
|
23
|
s/\s+$//; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# Default to using the whole content of the link entry as a section |
431
|
|
|
|
|
|
|
# name. Note that L forces a manpage interpretation, as does |
432
|
|
|
|
|
|
|
# something looking like L. The latter is an |
433
|
|
|
|
|
|
|
# enhancement over the original Pod::Text. |
434
|
14
|
|
|
|
|
27
|
my ($manpage, $section) = ('', $_); |
435
|
14
|
100
|
|
|
|
90
|
if (/^(?:https?|ftp|news):/) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# a URL |
437
|
1
|
|
|
|
|
24
|
return $_; |
438
|
|
|
|
|
|
|
} elsif (/^"\s*(.*?)\s*"$/) { |
439
|
1
|
|
|
|
|
4
|
$section = '"' . $1 . '"'; |
440
|
|
|
|
|
|
|
} elsif (m/^[-:.\w]+(?:\(\S+\))?$/) { |
441
|
2
|
|
|
|
|
53
|
($manpage, $section) = ($_, ''); |
442
|
|
|
|
|
|
|
} elsif (m{/}) { |
443
|
10
|
|
|
|
|
50
|
($manpage, $section) = split (/\s*\/\s*/, $_, 2); |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
13
|
|
|
|
|
21
|
my $text = ''; |
447
|
|
|
|
|
|
|
# Now build the actual output text. |
448
|
13
|
100
|
|
|
|
48
|
if (!length $section) { |
|
|
100
|
|
|
|
|
|
449
|
2
|
50
|
|
|
|
8
|
$text = "the $manpage manpage" if length $manpage; |
450
|
|
|
|
|
|
|
} elsif ($section =~ /^[:\w]+(?:\(\))?/) { |
451
|
8
|
|
|
|
|
20
|
$text .= 'the ' . $section . ' entry'; |
452
|
8
|
50
|
|
|
|
20
|
$text .= (length $manpage) ? " in the $manpage manpage" |
453
|
|
|
|
|
|
|
: ' elsewhere in this document'; |
454
|
|
|
|
|
|
|
} else { |
455
|
3
|
|
|
|
|
12
|
$section =~ s/^\"\s*//; |
456
|
3
|
|
|
|
|
12
|
$section =~ s/\s*\"$//; |
457
|
3
|
|
|
|
|
9
|
$text .= 'the section on "' . $section . '"'; |
458
|
3
|
100
|
|
|
|
11
|
$text .= " in the $manpage manpage" if length $manpage; |
459
|
|
|
|
|
|
|
} |
460
|
13
|
|
|
|
|
378
|
return $text; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
############################################################################ |
465
|
|
|
|
|
|
|
# List handling |
466
|
|
|
|
|
|
|
############################################################################ |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# This method is called whenever an =item command is complete (in other |
469
|
|
|
|
|
|
|
# words, we've seen its associated paragraph or know for certain that it |
470
|
|
|
|
|
|
|
# doesn't have one). It gets the paragraph associated with the item as an |
471
|
|
|
|
|
|
|
# argument. If that argument is empty, just output the item tag; if it |
472
|
|
|
|
|
|
|
# contains a newline, output the item tag followed by the newline. |
473
|
|
|
|
|
|
|
# Otherwise, see if there's enough room for us to output the item tag in the |
474
|
|
|
|
|
|
|
# margin of the text or if we have to put it on a separate line. |
475
|
|
|
|
|
|
|
sub item { |
476
|
16
|
|
|
16
|
1
|
28
|
my $self = shift; |
477
|
16
|
|
|
|
|
71
|
local $_ = shift; |
478
|
16
|
|
|
|
|
23
|
my $tag = $$self{ITEM}; |
479
|
16
|
50
|
|
|
|
38
|
unless (defined $tag) { |
480
|
0
|
|
|
|
|
0
|
carp 'item called without tag'; |
481
|
0
|
|
|
|
|
0
|
return; |
482
|
|
|
|
|
|
|
} |
483
|
16
|
|
|
|
|
27
|
undef $$self{ITEM}; |
484
|
16
|
|
|
|
|
41
|
my $indent = $$self{INDENTS}[-1]; |
485
|
16
|
50
|
|
|
|
39
|
unless (defined $indent) { $indent = $$self{indent} } |
|
0
|
|
|
|
|
0
|
|
486
|
16
|
|
|
|
|
34
|
my $space = ' ' x $indent; |
487
|
16
|
50
|
|
|
|
40
|
$space =~ s/^ /:/ if $$self{alt}; |
488
|
16
|
100
|
100
|
|
|
110
|
if (!$_ || /^\s+$/ || ($$self{MARGIN} - $indent < length ($tag) + 1)) { |
|
|
|
100
|
|
|
|
|
489
|
6
|
|
|
|
|
15
|
my $margin = $$self{MARGIN}; |
490
|
6
|
|
|
|
|
10
|
$$self{MARGIN} = $indent; |
491
|
6
|
|
|
|
|
30
|
my $output = $self->reformat ($tag); |
492
|
6
|
|
|
|
|
33
|
$output =~ s/[\r\n]*$/\n/; |
493
|
6
|
|
|
|
|
24
|
$self->output ($output); |
494
|
6
|
|
|
|
|
10
|
$$self{MARGIN} = $margin; |
495
|
6
|
100
|
100
|
|
|
60
|
$self->output ($self->reformat ($_)) if defined && /\S/; |
496
|
|
|
|
|
|
|
} else { |
497
|
10
|
|
|
|
|
41
|
$_ = $self->reformat ($_); |
498
|
10
|
50
|
33
|
|
|
23
|
s/^ /:/ if ($$self{alt} && $indent > 0); |
499
|
10
|
|
|
|
|
17
|
my $tagspace = ' ' x length $tag; |
500
|
10
|
50
|
|
|
|
152
|
s/^($space)$tagspace/$1$tag/ or carp 'Bizarre space in item'; |
501
|
10
|
|
|
|
|
34
|
$self->output ($_); |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
############################################################################ |
507
|
|
|
|
|
|
|
# Output formatting |
508
|
|
|
|
|
|
|
############################################################################ |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
# Wrap a line, indenting by the current left margin. We can't use |
511
|
|
|
|
|
|
|
# Text::Wrap because it plays games with tabs. We can't use formline, even |
512
|
|
|
|
|
|
|
# though we'd really like to, because it screws up non-printing characters. |
513
|
|
|
|
|
|
|
# So we have to do the wrapping ourselves. |
514
|
|
|
|
|
|
|
sub wrap { |
515
|
80
|
|
|
80
|
0
|
101
|
my $self = shift; |
516
|
80
|
|
|
|
|
103
|
local $_ = shift; |
517
|
80
|
|
|
|
|
102
|
my $output = ''; |
518
|
80
|
|
|
|
|
159
|
my $spaces = ' ' x $$self{MARGIN}; |
519
|
80
|
|
|
|
|
120
|
my $width = $$self{width} - $$self{MARGIN}; |
520
|
80
|
|
|
|
|
185
|
while (length > $width) { |
521
|
49
|
50
|
33
|
|
|
751
|
if (s/^([^\r\n]{0,$width})\s+// || s/^([^\r\n]{$width})//) { |
522
|
49
|
|
|
|
|
200
|
$output .= $spaces . $1 . "\n"; |
523
|
|
|
|
|
|
|
} else { |
524
|
0
|
|
|
|
|
0
|
last; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
} |
527
|
80
|
|
|
|
|
165
|
$output .= $spaces . $_; |
528
|
80
|
|
|
|
|
361
|
$output =~ s/\s+$/\n\n/; |
529
|
80
|
|
|
|
|
275
|
return $output; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
# Reformat a paragraph of text for the current margin. Takes the text to |
533
|
|
|
|
|
|
|
# reformat and returns the formatted text. |
534
|
|
|
|
|
|
|
sub reformat { |
535
|
80
|
|
|
80
|
0
|
119
|
my $self = shift; |
536
|
80
|
|
|
|
|
105
|
local $_ = shift; |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# If we're trying to preserve two spaces after sentences, do some |
539
|
|
|
|
|
|
|
# munging to support that. Otherwise, smash all repeated whitespace. |
540
|
80
|
50
|
|
|
|
144
|
if ($$self{sentence}) { |
541
|
0
|
|
|
|
|
0
|
s/ +$//mg; |
542
|
0
|
|
|
|
|
0
|
s/\.\r?\n/. \n/g; |
543
|
0
|
|
|
|
|
0
|
s/[\r\n]+/ /g; |
544
|
0
|
|
|
|
|
0
|
s/ +/ /g; |
545
|
|
|
|
|
|
|
} else { |
546
|
80
|
|
|
|
|
557
|
s/\s+/ /g; |
547
|
|
|
|
|
|
|
} |
548
|
80
|
|
|
|
|
223
|
return $self->wrap($_); |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
# Output text to the output device. |
552
|
103
|
|
|
103
|
0
|
183
|
sub output { $_[1] =~ tr/\01/ /; print { $_[0]->output_handle } $_[1] } |
|
103
|
|
|
|
|
134
|
|
|
103
|
|
|
|
|
2940
|
|
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
############################################################################ |
556
|
|
|
|
|
|
|
# Backwards compatibility |
557
|
|
|
|
|
|
|
############################################################################ |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
# The old Pod::Text module did everything in a pod2text() function. This |
560
|
|
|
|
|
|
|
# tries to provide the same interface for legacy applications. |
561
|
|
|
|
|
|
|
sub pod2text { |
562
|
0
|
|
|
0
|
0
|
|
my @args; |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
# This is really ugly; I hate doing option parsing in the middle of a |
565
|
|
|
|
|
|
|
# module. But the old Pod::Text module supported passing flags to its |
566
|
|
|
|
|
|
|
# entry function, so handle -a and -. |
567
|
0
|
|
|
|
|
|
while ($_[0] =~ /^-/) { |
568
|
0
|
|
|
|
|
|
my $flag = shift; |
569
|
0
|
0
|
|
|
|
|
if ($flag eq '-a') { push (@args, alt => 1) } |
|
0
|
0
|
|
|
|
|
|
570
|
0
|
|
|
|
|
|
elsif ($flag =~ /^-(\d+)$/) { push (@args, width => $1) } |
571
|
|
|
|
|
|
|
else { |
572
|
0
|
|
|
|
|
|
unshift (@_, $flag); |
573
|
0
|
|
|
|
|
|
last; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
# Now that we know what arguments we're using, create the parser. |
578
|
0
|
|
|
|
|
|
my $parser = Pod::PlainText->new (@args); |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
# If two arguments were given, the second argument is going to be a file |
581
|
|
|
|
|
|
|
# handle. That means we want to call parse_from_filehandle(), which |
582
|
|
|
|
|
|
|
# means we need to turn the first argument into a file handle. Magic |
583
|
|
|
|
|
|
|
# open will handle the <&STDIN case automagically. |
584
|
0
|
0
|
|
|
|
|
if (defined $_[1]) { |
585
|
0
|
|
|
|
|
|
my $infh; |
586
|
0
|
0
|
|
|
|
|
if ($] < 5.006) { |
587
|
0
|
|
|
|
|
|
$infh = gensym(); |
588
|
|
|
|
|
|
|
} |
589
|
0
|
0
|
|
|
|
|
unless (open ($infh, $_[0])) { |
590
|
0
|
|
|
|
|
|
croak ("Can't open $_[0] for reading: $!\n"); |
591
|
|
|
|
|
|
|
} |
592
|
0
|
|
|
|
|
|
$_[0] = $infh; |
593
|
0
|
|
|
|
|
|
return $parser->parse_from_filehandle (@_); |
594
|
|
|
|
|
|
|
} else { |
595
|
0
|
|
|
|
|
|
return $parser->parse_from_file (@_); |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
############################################################################ |
601
|
|
|
|
|
|
|
# Module return value and documentation |
602
|
|
|
|
|
|
|
############################################################################ |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
1; |
605
|
|
|
|
|
|
|
__END__ |