xref: /openbsd-src/gnu/usr.bin/perl/cpan/Pod-Perldoc/lib/Pod/Perldoc/ToMan.pm (revision fac98b93b71777a71b1e912ccaf68ce33d7b87c4)
1898184e3Ssthenrequire 5.006;
2898184e3Ssthenpackage Pod::Perldoc::ToMan;
3898184e3Ssthenuse strict;
4898184e3Ssthenuse warnings;
5898184e3Ssthenuse parent qw(Pod::Perldoc::BaseTo);
6898184e3Ssthen
7898184e3Ssthenuse vars qw($VERSION);
89f11ffb7Safresh1$VERSION = '3.28';
9898184e3Ssthen
10898184e3Ssthenuse File::Spec::Functions qw(catfile);
11898184e3Ssthenuse Pod::Man 2.18;
12898184e3Ssthen# This class is unlike ToText.pm et al, because we're NOT paging thru
13898184e3Ssthen# the output in our particular format -- we make the output and
14898184e3Ssthen# then we run nroff (or whatever) on it, and then page thru the
15898184e3Ssthen# (plaintext) output of THAT!
16898184e3Ssthen
17898184e3Ssthensub SUCCESS () { 1 }
18898184e3Ssthensub FAILED  () { 0 }
19898184e3Ssthen
20898184e3Ssthensub is_pageable        { 1 }
21898184e3Ssthensub write_with_binmode { 0 }
22898184e3Ssthensub output_extension   { 'txt' }
23898184e3Ssthen
24898184e3Ssthensub __filter_nroff  { shift->_perldoc_elem('__filter_nroff'  , @_) }
25898184e3Ssthensub __nroffer       { shift->_perldoc_elem('__nroffer'       , @_) }
26898184e3Ssthensub __bindir        { shift->_perldoc_elem('__bindir'        , @_) }
27898184e3Ssthensub __pod2man       { shift->_perldoc_elem('__pod2man'       , @_) }
28898184e3Ssthensub __output_file   { shift->_perldoc_elem('__output_file'   , @_) }
29898184e3Ssthen
30898184e3Ssthensub center          { shift->_perldoc_elem('center'         , @_) }
31898184e3Ssthensub date            { shift->_perldoc_elem('date'           , @_) }
32898184e3Ssthensub fixed           { shift->_perldoc_elem('fixed'          , @_) }
33898184e3Ssthensub fixedbold       { shift->_perldoc_elem('fixedbold'      , @_) }
34898184e3Ssthensub fixeditalic     { shift->_perldoc_elem('fixeditalic'    , @_) }
35898184e3Ssthensub fixedbolditalic { shift->_perldoc_elem('fixedbolditalic', @_) }
36898184e3Ssthensub name            { shift->_perldoc_elem('name'           , @_) }
37898184e3Ssthensub quotes          { shift->_perldoc_elem('quotes'         , @_) }
38898184e3Ssthensub release         { shift->_perldoc_elem('release'        , @_) }
39898184e3Ssthensub section         { shift->_perldoc_elem('section'        , @_) }
40898184e3Ssthen
41898184e3Ssthensub new {
42898184e3Ssthen	my( $either ) = shift;
43898184e3Ssthen	my $self = bless {}, ref($either) || $either;
44898184e3Ssthen	$self->init( @_ );
45898184e3Ssthen	return $self;
46898184e3Ssthen	}
47898184e3Ssthen
48898184e3Ssthensub init {
49898184e3Ssthen	my( $self, @args ) = @_;
50898184e3Ssthen
51898184e3Ssthen	unless( $self->__nroffer ) {
52898184e3Ssthen		my $roffer = $self->_find_roffer( $self->_roffer_candidates );
53898184e3Ssthen		$self->debug( "Using $roffer\n" );
54898184e3Ssthen		$self->__nroffer( $roffer );
55898184e3Ssthen		}
56898184e3Ssthen    else {
57898184e3Ssthen	    $self->debug( "__nroffer is " . $self->__nroffer() . "\n" );
58898184e3Ssthen        }
59898184e3Ssthen
60898184e3Ssthen	$self->_check_nroffer;
61898184e3Ssthen	}
62898184e3Ssthen
63898184e3Ssthensub _roffer_candidates {
64898184e3Ssthen	my( $self ) = @_;
65898184e3Ssthen
669f11ffb7Safresh1	if( $self->is_openbsd || $self->is_freebsd || $self->is_bitrig ) { qw( mandoc groff nroff ) }
67898184e3Ssthen	else                    { qw( groff nroff mandoc ) }
68898184e3Ssthen	}
69898184e3Ssthen
70898184e3Ssthensub _find_roffer {
71898184e3Ssthen	my( $self, @candidates ) = @_;
72898184e3Ssthen
73898184e3Ssthen	my @found = ();
74898184e3Ssthen	foreach my $candidate ( @candidates ) {
75898184e3Ssthen		push @found, $self->_find_executable_in_path( $candidate );
76898184e3Ssthen		}
77898184e3Ssthen
78898184e3Ssthen	return wantarray ? @found : $found[0];
79898184e3Ssthen	}
80898184e3Ssthen
81898184e3Ssthensub _check_nroffer {
82898184e3Ssthen	return 1;
83898184e3Ssthen	# where is it in the PATH?
84898184e3Ssthen
85898184e3Ssthen	# is it executable?
86898184e3Ssthen
87898184e3Ssthen	# what is its real name?
88898184e3Ssthen
89898184e3Ssthen	# what is its version?
90898184e3Ssthen
91898184e3Ssthen	# does it support the flags we need?
92898184e3Ssthen
93898184e3Ssthen	# is it good enough for us?
94898184e3Ssthen	}
95898184e3Ssthen
96898184e3Ssthensub _get_stty { `stty -a` }
97898184e3Ssthen
98898184e3Ssthensub _get_columns_from_stty {
99898184e3Ssthen	my $output = $_[0]->_get_stty;
100898184e3Ssthen
101898184e3Ssthen	if(    $output =~ /\bcolumns\s+(\d+)/ )    { return $1 }
102898184e3Ssthen	elsif( $output =~ /;\s*(\d+)\s+columns;/ ) { return $1 }
103898184e3Ssthen	else                                       { return  0 }
104898184e3Ssthen	}
105898184e3Ssthen
106898184e3Ssthensub _get_columns_from_manwidth {
107898184e3Ssthen	my( $self ) = @_;
108898184e3Ssthen
109898184e3Ssthen	return 0 unless defined $ENV{MANWIDTH};
110898184e3Ssthen
111898184e3Ssthen	unless( $ENV{MANWIDTH} =~ m/\A\d+\z/ ) {
112898184e3Ssthen		$self->warn( "Ignoring non-numeric MANWIDTH ($ENV{MANWIDTH})\n" );
113898184e3Ssthen		return 0;
114898184e3Ssthen		}
115898184e3Ssthen
116898184e3Ssthen	if( $ENV{MANWIDTH} == 0 ) {
117898184e3Ssthen		$self->warn( "Ignoring MANWIDTH of 0. Really? Why even run the program? :)\n" );
118898184e3Ssthen		return 0;
119898184e3Ssthen		}
120898184e3Ssthen
121898184e3Ssthen	if( $ENV{MANWIDTH} =~ m/\A(\d+)\z/ ) { return $1 }
122898184e3Ssthen
123898184e3Ssthen	return 0;
124898184e3Ssthen	}
125898184e3Ssthen
126898184e3Ssthensub _get_default_width {
127898184e3Ssthen	73
128898184e3Ssthen	}
129898184e3Ssthen
130898184e3Ssthensub _get_columns {
131898184e3Ssthen	$_[0]->_get_columns_from_manwidth ||
132898184e3Ssthen	$_[0]->_get_columns_from_stty     ||
133898184e3Ssthen	$_[0]->_get_default_width;
134898184e3Ssthen	}
135898184e3Ssthen
136898184e3Ssthensub _get_podman_switches {
137898184e3Ssthen	my( $self ) = @_;
138898184e3Ssthen
139e5157e49Safresh1	my @switches = map { $_, $self->{$_} } grep !m/^_/s, keys %$self;
140898184e3Ssthen
141af9ddab1Sschwarze    # There needs to be a cleaner way to handle setting
142af9ddab1Sschwarze    # the UTF-8 flag, but for now, comment out this
143af9ddab1Sschwarze    # line because it often does the wrong thing.
144af9ddab1Sschwarze    #
145af9ddab1Sschwarze    # See RT #77465
146af9ddab1Sschwarze    #
147*fac98b93Safresh1    # Then again, do *not* comment it out on OpenBSD:
148*fac98b93Safresh1    # mandoc handles UTF-8 input just fine.
149*fac98b93Safresh1    push @switches, 'utf8' => 1;
150af9ddab1Sschwarze
151898184e3Ssthen	$self->debug( "Pod::Man switches are [@switches]\n" );
152898184e3Ssthen
153898184e3Ssthen	return @switches;
154898184e3Ssthen	}
155898184e3Ssthen
156898184e3Ssthensub _parse_with_pod_man {
157898184e3Ssthen	my( $self, $file ) = @_;
158898184e3Ssthen
159898184e3Ssthen	#->output_fh and ->output_string from Pod::Simple aren't
160898184e3Ssthen	# working, apparently, so there's this ugly hack:
161898184e3Ssthen	local *STDOUT;
162898184e3Ssthen	open STDOUT, '>', $self->{_text_ref};
163898184e3Ssthen	my $parser = Pod::Man->new( $self->_get_podman_switches );
164898184e3Ssthen	$self->debug( "Parsing $file\n" );
165898184e3Ssthen	$parser->parse_from_file( $file );
166898184e3Ssthen	$self->debug( "Done parsing $file\n" );
167898184e3Ssthen	close STDOUT;
168898184e3Ssthen
169898184e3Ssthen	$self->die( "No output from Pod::Man!\n" )
170898184e3Ssthen		unless length $self->{_text_ref};
171898184e3Ssthen
172898184e3Ssthen	$self->_save_pod_man_output if $self->debugging;
173898184e3Ssthen
174898184e3Ssthen	return SUCCESS;
175898184e3Ssthen	}
176898184e3Ssthen
177898184e3Ssthensub _save_pod_man_output {
178898184e3Ssthen	my( $self, $fh ) = @_;
179898184e3Ssthen
180898184e3Ssthen	$fh = do {
181898184e3Ssthen		my $file = "podman.out.$$.txt";
182898184e3Ssthen		$self->debug( "Writing $file with Pod::Man output\n" );
183898184e3Ssthen		open my $fh2, '>', $file;
184898184e3Ssthen		$fh2;
185898184e3Ssthen		} unless $fh;
186898184e3Ssthen
187898184e3Ssthen	print { $fh } ${ $self->{_text_ref} };
188898184e3Ssthen	}
189898184e3Ssthen
190898184e3Ssthensub _have_groff_with_utf8 {
191898184e3Ssthen	my( $self ) = @_;
192898184e3Ssthen
193898184e3Ssthen	return 0 unless $self->_is_groff;
194898184e3Ssthen	my $roffer = $self->__nroffer;
195898184e3Ssthen
196898184e3Ssthen	my $minimum_groff_version = '1.20.1';
197898184e3Ssthen
198898184e3Ssthen	my $version_string = `$roffer -v`;
199898184e3Ssthen	my( $version ) = $version_string =~ /\(?groff\)? version (\d+\.\d+(?:\.\d+)?)/;
200898184e3Ssthen	$self->debug( "Found groff $version\n" );
201898184e3Ssthen
202898184e3Ssthen	# is a string comparison good enough?
203898184e3Ssthen	if( $version lt $minimum_groff_version ) {
204898184e3Ssthen		$self->warn(
205898184e3Ssthen			"You have an old groff." .
206898184e3Ssthen			" Update to version $minimum_groff_version for good Unicode support.\n" .
207898184e3Ssthen			"If you don't upgrade, wide characters may come out oddly.\n"
208898184e3Ssthen			 );
209898184e3Ssthen		}
210898184e3Ssthen
211898184e3Ssthen	$version ge $minimum_groff_version;
212898184e3Ssthen	}
213898184e3Ssthen
214898184e3Ssthensub _collect_nroff_switches {
215898184e3Ssthen	my( $self ) = shift;
216898184e3Ssthen
217e5157e49Safresh1    my @render_switches = ('-man', $self->_get_device_switches);
218898184e3Ssthen
219898184e3Ssthen	# Thanks to Brendan O'Dea for contributing the following block
220e5157e49Safresh1	if( $self->_is_roff and -t STDOUT and my ($cols) = $self->_get_columns ) {
221898184e3Ssthen		my $c = $cols * 39 / 40;
222898184e3Ssthen		$cols = $c > $cols - 2 ? $c : $cols -2;
223898184e3Ssthen		push @render_switches, '-rLL=' . (int $c) . 'n' if $cols > 80;
224898184e3Ssthen		}
225898184e3Ssthen
226*fac98b93Safresh1	if( $self->_is_mandoc ) {
227*fac98b93Safresh1		push @render_switches, '-Owidth=' . $self->_get_columns;
228*fac98b93Safresh1		}
229*fac98b93Safresh1
230898184e3Ssthen	# I hear persistent reports that adding a -c switch to $render
231898184e3Ssthen	# solves many people's problems.  But I also hear that some mans
232898184e3Ssthen	# don't have a -c switch, so that unconditionally adding it here
233898184e3Ssthen	# would presumably be a Bad Thing   -- sburke@cpan.org
234898184e3Ssthen    push @render_switches, '-c' if( $self->_is_roff and $self->is_cygwin );
235898184e3Ssthen
236898184e3Ssthen	return @render_switches;
237898184e3Ssthen	}
238898184e3Ssthen
239898184e3Ssthensub _get_device_switches {
240898184e3Ssthen	my( $self ) = @_;
241898184e3Ssthen
242898184e3Ssthen	   if( $self->_is_nroff  )             { qw()              }
243898184e3Ssthen	elsif( $self->_have_groff_with_utf8 )  { qw(-Kutf8 -Tutf8) }
244898184e3Ssthen	elsif( $self->_is_ebcdic )             { qw(-Tcp1047)      }
245898184e3Ssthen	elsif( $self->_is_mandoc )             { qw()              }
246898184e3Ssthen	else                                   { qw(-Tlatin1)      }
247898184e3Ssthen	}
248898184e3Ssthen
249898184e3Ssthensub _is_roff {
250898184e3Ssthen	my( $self ) = @_;
251898184e3Ssthen
252898184e3Ssthen	$self->_is_nroff or $self->_is_groff;
253898184e3Ssthen	}
254898184e3Ssthen
255898184e3Ssthensub _is_nroff {
256898184e3Ssthen	my( $self ) = @_;
257898184e3Ssthen
258898184e3Ssthen	$self->__nroffer =~ /\bnroff\b/;
259898184e3Ssthen	}
260898184e3Ssthen
261898184e3Ssthensub _is_groff {
262898184e3Ssthen	my( $self ) = @_;
263898184e3Ssthen
264898184e3Ssthen	$self->__nroffer =~ /\bgroff\b/;
265898184e3Ssthen	}
266898184e3Ssthen
267898184e3Ssthensub _is_mandoc {
268898184e3Ssthen	my ( $self ) = @_;
269898184e3Ssthen
270898184e3Ssthen	$self->__nroffer =~ /\bmandoc\b/;
271898184e3Ssthen	}
272898184e3Ssthen
273898184e3Ssthensub _is_ebcdic {
274898184e3Ssthen	my( $self ) = @_;
275898184e3Ssthen
276898184e3Ssthen	return 0;
277898184e3Ssthen	}
278898184e3Ssthen
279898184e3Ssthensub _filter_through_nroff {
280898184e3Ssthen	my( $self ) = shift;
281898184e3Ssthen	$self->debug( "Filtering through " . $self->__nroffer() . "\n" );
282898184e3Ssthen
283898184e3Ssthen    # Maybe someone set rendering switches as part of the opt_n value
284898184e3Ssthen    # Deal with that here.
285898184e3Ssthen
286e9ce3842Safresh1    my ($render, $switches) = $self->__nroffer() =~ /\A([\/a-zA-Z0-9_\.-]+)\b(.+)?\z/;
287898184e3Ssthen
288898184e3Ssthen    $self->die("no nroffer!?") unless $render;
289898184e3Ssthen    my @render_switches = $self->_collect_nroff_switches;
290898184e3Ssthen
291898184e3Ssthen    if ( $switches ) {
292898184e3Ssthen        # Eliminate whitespace
293898184e3Ssthen        $switches =~ s/\s//g;
294898184e3Ssthen
295e5157e49Safresh1        # Then separate the switches with a zero-width positive
296898184e3Ssthen        # lookahead on the dash.
297898184e3Ssthen        #
298898184e3Ssthen        # See:
299898184e3Ssthen        # http://www.effectiveperlprogramming.com/blog/1411
300898184e3Ssthen        # for a good discussion of this technique
301898184e3Ssthen
302898184e3Ssthen        push @render_switches, split(/(?=-)/, $switches);
303898184e3Ssthen        }
304898184e3Ssthen
305898184e3Ssthen	$self->debug( "render is $render\n" );
306898184e3Ssthen	$self->debug( "render options are @render_switches\n" );
307898184e3Ssthen
308898184e3Ssthen	require Symbol;
309898184e3Ssthen	require IPC::Open3;
310898184e3Ssthen	require IO::Handle;
311898184e3Ssthen
312898184e3Ssthen	my $pid = IPC::Open3::open3(
313898184e3Ssthen		my $writer,
314898184e3Ssthen		my $reader,
315898184e3Ssthen		my $err = Symbol::gensym(),
316898184e3Ssthen		$render,
317898184e3Ssthen		@render_switches
318898184e3Ssthen		);
319898184e3Ssthen
320898184e3Ssthen	$reader->autoflush(1);
321898184e3Ssthen
322898184e3Ssthen	use IO::Select;
323898184e3Ssthen	my $selector = IO::Select->new( $reader );
324898184e3Ssthen
325898184e3Ssthen	$self->debug( "Writing to pipe to $render\n" );
326898184e3Ssthen
327898184e3Ssthen	my $offset = 0;
328898184e3Ssthen	my $chunk_size = 4096;
329898184e3Ssthen	my $length = length( ${ $self->{_text_ref} } );
330898184e3Ssthen	my $chunks = $length / $chunk_size;
331898184e3Ssthen	my $done;
332898184e3Ssthen	my $buffer;
333898184e3Ssthen	while( $offset <= $length ) {
334898184e3Ssthen		$self->debug( "Writing chunk $chunks\n" ); $chunks++;
335898184e3Ssthen		syswrite $writer, ${ $self->{_text_ref} }, $chunk_size, $offset
336898184e3Ssthen			or $self->die( $! );
337898184e3Ssthen		$offset += $chunk_size;
338898184e3Ssthen		$self->debug( "Checking read\n" );
339898184e3Ssthen		READ: {
340898184e3Ssthen			last READ unless $selector->can_read( 0.01 );
341898184e3Ssthen			$self->debug( "Reading\n" );
342898184e3Ssthen			my $bytes = sysread $reader, $buffer, 4096;
343898184e3Ssthen			$self->debug( "Read $bytes bytes\n" );
344898184e3Ssthen			$done .= $buffer;
345898184e3Ssthen			$self->debug( sprintf "Output is %d bytes\n",
346898184e3Ssthen				length $done
347898184e3Ssthen				);
348898184e3Ssthen			next READ;
349898184e3Ssthen			}
350898184e3Ssthen		}
351898184e3Ssthen	close $writer;
352898184e3Ssthen	$self->debug( "Done writing\n" );
353898184e3Ssthen
354898184e3Ssthen	# read any leftovers
355898184e3Ssthen	$done .= do { local $/; <$reader> };
356898184e3Ssthen	$self->debug( sprintf "Done reading. Output is %d bytes\n",
357898184e3Ssthen		length $done
358898184e3Ssthen		);
359898184e3Ssthen
360*fac98b93Safresh1	# wait for it to exit
361*fac98b93Safresh1	waitpid( $pid, 0 );
362*fac98b93Safresh1
363898184e3Ssthen	if( $? ) {
364898184e3Ssthen		$self->warn( "Error from pipe to $render!\n" );
365898184e3Ssthen		$self->debug( 'Error: ' . do { local $/; <$err> } );
366898184e3Ssthen		}
367898184e3Ssthen
368898184e3Ssthen
369898184e3Ssthen	close $reader;
370898184e3Ssthen	if( my $err = $? ) {
371898184e3Ssthen		$self->debug(
372898184e3Ssthen			"Nonzero exit ($?) while running `$render @render_switches`.\n" .
373898184e3Ssthen			"Falling back to Pod::Perldoc::ToPod\n"
374898184e3Ssthen			);
375898184e3Ssthen		return $self->_fallback_to_pod( @_ );
376898184e3Ssthen		}
377898184e3Ssthen
378898184e3Ssthen	$self->debug( "Output:\n----\n$done\n----\n" );
379898184e3Ssthen
380898184e3Ssthen	${ $self->{_text_ref} } = $done;
381898184e3Ssthen
382898184e3Ssthen	return length ${ $self->{_text_ref} } ? SUCCESS : FAILED;
383898184e3Ssthen	}
384898184e3Ssthen
385898184e3Ssthensub parse_from_file {
386898184e3Ssthen	my( $self, $file, $outfh) = @_;
387898184e3Ssthen
388898184e3Ssthen	# We have a pipeline of filters each affecting the reference
389898184e3Ssthen	# in $self->{_text_ref}
390898184e3Ssthen	$self->{_text_ref} = \my $output;
391898184e3Ssthen
392898184e3Ssthen	$self->_parse_with_pod_man( $file );
393898184e3Ssthen	# so far, nroff is an external command so we ensure it worked
394898184e3Ssthen	my $result = $self->_filter_through_nroff;
395898184e3Ssthen	return $self->_fallback_to_pod( @_ ) unless $result == SUCCESS;
396898184e3Ssthen
397898184e3Ssthen	$self->_post_nroff_processing;
398898184e3Ssthen
399898184e3Ssthen	print { $outfh } $output or
400898184e3Ssthen		$self->die( "Can't print to $$self{__output_file}: $!" );
401898184e3Ssthen
402898184e3Ssthen	return;
403898184e3Ssthen	}
404898184e3Ssthen
405898184e3Ssthensub _fallback_to_pod {
406898184e3Ssthen	my( $self, @args ) = @_;
407898184e3Ssthen	$self->warn( "Falling back to Pod because there was a problem!\n" );
408898184e3Ssthen	require Pod::Perldoc::ToPod;
409898184e3Ssthen	return  Pod::Perldoc::ToPod->new->parse_from_file(@_);
410898184e3Ssthen	}
411898184e3Ssthen
412898184e3Ssthen# maybe there's a user setting we should check?
413898184e3Ssthensub _get_tab_width { 4 }
414898184e3Ssthen
415898184e3Ssthensub _expand_tabs {
416898184e3Ssthen	my( $self ) = @_;
417898184e3Ssthen
418898184e3Ssthen	my $tab_width = ' ' x $self->_get_tab_width;
419898184e3Ssthen
420898184e3Ssthen	${ $self->{_text_ref} } =~ s/\t/$tab_width/g;
421898184e3Ssthen	}
422898184e3Ssthen
423898184e3Ssthensub _post_nroff_processing {
424898184e3Ssthen	my( $self ) = @_;
425898184e3Ssthen
426898184e3Ssthen	if( $self->is_hpux ) {
427898184e3Ssthen	    $self->debug( "On HP-UX, I'm going to expand tabs for you\n" );
428898184e3Ssthen		# this used to be a pipe to `col -x` for HP-UX
429898184e3Ssthen		$self->_expand_tabs;
430898184e3Ssthen		}
431898184e3Ssthen
432898184e3Ssthen	if( $self->{'__filter_nroff'} ) {
433898184e3Ssthen		$self->debug( "filter_nroff is set, so filtering\n" );
434898184e3Ssthen		$self->_remove_nroff_header;
435898184e3Ssthen		$self->_remove_nroff_footer;
436898184e3Ssthen		}
437898184e3Ssthen	else {
438898184e3Ssthen		$self->debug( "filter_nroff is not set, so not filtering\n" );
439898184e3Ssthen		}
440898184e3Ssthen
441898184e3Ssthen	$self->_handle_unicode;
442898184e3Ssthen
443898184e3Ssthen	return 1;
444898184e3Ssthen	}
445898184e3Ssthen
446898184e3Ssthen# I don't think this does anything since there aren't two consecutive
447898184e3Ssthen# newlines in the Pod::Man output
448898184e3Ssthensub _remove_nroff_header {
449898184e3Ssthen	my( $self ) = @_;
450898184e3Ssthen	$self->debug( "_remove_nroff_header is still a stub!\n" );
451898184e3Ssthen	return 1;
452898184e3Ssthen
453898184e3Ssthen#  my @data = split /\n{2,}/, shift;
454898184e3Ssthen#  shift @data while @data and $data[0] !~ /\S/; # Go to header
455898184e3Ssthen#  shift @data if @data and $data[0] =~ /Contributed\s+Perl/; # Skip header
456898184e3Ssthen	}
457898184e3Ssthen
458898184e3Ssthen# I don't think this does anything since there aren't two consecutive
459898184e3Ssthen# newlines in the Pod::Man output
460898184e3Ssthensub _remove_nroff_footer {
461898184e3Ssthen	my( $self ) = @_;
462898184e3Ssthen	$self->debug( "_remove_nroff_footer is still a stub!\n" );
463898184e3Ssthen	return 1;
464898184e3Ssthen	${ $self->{_text_ref} } =~ s/\n\n+.*\w.*\Z//m;
465898184e3Ssthen
466898184e3Ssthen#  my @data = split /\n{2,}/, shift;
467898184e3Ssthen#  pop @data if @data and $data[-1] =~ /^\w/; # Skip footer, like
468898184e3Ssthen        # 28/Jan/99 perl 5.005, patch 53 1
469898184e3Ssthen	}
470898184e3Ssthen
471898184e3Ssthensub _unicode_already_handled {
472898184e3Ssthen	my( $self ) = @_;
473898184e3Ssthen
474898184e3Ssthen	$self->_have_groff_with_utf8 ||
475898184e3Ssthen	1  # so, we don't have a case that needs _handle_unicode
476898184e3Ssthen	;
477898184e3Ssthen	}
478898184e3Ssthen
479898184e3Ssthensub _handle_unicode {
480898184e3Ssthen# this is the job of preconv
481898184e3Ssthen# we don't need this with groff 1.20 and later.
482898184e3Ssthen	my( $self ) = @_;
483898184e3Ssthen
484898184e3Ssthen	return 1 if $self->_unicode_already_handled;
485898184e3Ssthen
486898184e3Ssthen	require Encode;
487898184e3Ssthen
488898184e3Ssthen	# it's UTF-8 here, but we need character data
489898184e3Ssthen	my $text = Encode::decode( 'UTF-8', ${ $self->{_text_ref} } ) ;
490898184e3Ssthen
491898184e3Ssthen# http://www.mail-archive.com/groff@gnu.org/msg01378.html
492898184e3Ssthen# http://linux.die.net/man/7/groff_char
493898184e3Ssthen# http://www.gnu.org/software/groff/manual/html_node/Using-Symbols.html
494898184e3Ssthen# http://lists.gnu.org/archive/html/groff/2011-05/msg00007.html
495898184e3Ssthen# http://www.simplicidade.org/notes/archives/2009/05/fixing_the_pod.html
496898184e3Ssthen# http://lists.freebsd.org/pipermail/freebsd-questions/2011-July/232239.html
497898184e3Ssthen	$text =~ s/(\P{ASCII})/
498898184e3Ssthen		sprintf '\\[u%04X]', ord $1
499898184e3Ssthen	     /eg;
500898184e3Ssthen
501898184e3Ssthen	# should we encode?
502898184e3Ssthen	${ $self->{_text_ref} } = $text;
503898184e3Ssthen	}
504898184e3Ssthen
505898184e3Ssthen1;
506898184e3Ssthen
507898184e3Ssthen__END__
508898184e3Ssthen
509898184e3Ssthen=head1 NAME
510898184e3Ssthen
511898184e3SsthenPod::Perldoc::ToMan - let Perldoc render Pod as man pages
512898184e3Ssthen
513898184e3Ssthen=head1 SYNOPSIS
514898184e3Ssthen
515898184e3Ssthen  perldoc -o man Some::Modulename
516898184e3Ssthen
517898184e3Ssthen=head1 DESCRIPTION
518898184e3Ssthen
519898184e3SsthenThis is a "plug-in" class that allows Perldoc to use
520898184e3SsthenPod::Man and C<groff> for reading Pod pages.
521898184e3Ssthen
522898184e3SsthenThe following options are supported:  center, date, fixed, fixedbold,
523898184e3Ssthenfixeditalic, fixedbolditalic, quotes, release, section
524898184e3Ssthen
525898184e3Ssthen(Those options are explained in L<Pod::Man>.)
526898184e3Ssthen
527898184e3SsthenFor example:
528898184e3Ssthen
529898184e3Ssthen  perldoc -o man -w center:Pod Some::Modulename
530898184e3Ssthen
531898184e3Ssthen=head1 CAVEAT
532898184e3Ssthen
533898184e3SsthenThis module may change to use a different pod-to-nroff formatter class
534898184e3Ssthenin the future, and this may change what options are supported.
535898184e3Ssthen
536898184e3Ssthen=head1 SEE ALSO
537898184e3Ssthen
538898184e3SsthenL<Pod::Man>, L<Pod::Perldoc>, L<Pod::Perldoc::ToNroff>
539898184e3Ssthen
540898184e3Ssthen=head1 COPYRIGHT AND DISCLAIMERS
541898184e3Ssthen
542898184e3SsthenCopyright (c) 2011 brian d foy. All rights reserved.
543898184e3Ssthen
544898184e3SsthenCopyright (c) 2002,3,4 Sean M. Burke.  All rights reserved.
545898184e3Ssthen
546898184e3SsthenThis library is free software; you can redistribute it and/or modify it
547898184e3Ssthenunder the same terms as Perl itself.
548898184e3Ssthen
549898184e3SsthenThis program is distributed in the hope that it will be useful, but
550898184e3Ssthenwithout any warranty; without even the implied warranty of
551898184e3Ssthenmerchantability or fitness for a particular purpose.
552898184e3Ssthen
553898184e3Ssthen=head1 AUTHOR
554898184e3Ssthen
555898184e3SsthenCurrent maintainer: Mark Allen C<< <mallen@cpan.org> >>
556898184e3Ssthen
557898184e3SsthenPast contributions from:
558898184e3Ssthenbrian d foy C<< <bdfoy@cpan.org> >>
559898184e3SsthenAdriano R. Ferreira C<< <ferreira@cpan.org> >>,
560898184e3SsthenSean M. Burke C<< <sburke@cpan.org> >>
561898184e3Ssthen
562898184e3Ssthen=cut
563898184e3Ssthen
564