From bc9c751170bc3ae5aa8c6bbdbe4c1e970b6ad2a6 Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Mon, 15 Sep 2008 10:56:23 +0000 Subject: [PATCH] Upgrade to podlators 2.1.3 p4raw-id: //depot/perl@34364 --- MANIFEST | 1 + lib/Pod/Man.pm | 27 ++++++----- lib/Pod/ParseLink.pm | 4 +- lib/Pod/Text.pm | 19 ++++++-- lib/Pod/t/man-options.t | 91 ++++++++++++++++++++++++++++++++++- lib/Pod/t/pod-spelling.t | 2 +- lib/Pod/t/text-options.t | 82 ++++++++++++++++++++++++++++++- lib/Pod/t/text-utf8.t | 122 +++++++++++++++++++++++++++++++++++++++++++++++ lib/Pod/t/text.t | 1 - pod/pod2man.PL | 31 +++++++----- pod/pod2text.PL | 14 ++++-- 11 files changed, 358 insertions(+), 36 deletions(-) create mode 100755 lib/Pod/t/text-utf8.t diff --git a/MANIFEST b/MANIFEST index 7eaab54..186f1f7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -2772,6 +2772,7 @@ lib/Pod/t/pod.t podlators test lib/Pod/t/Select.t See if Pod::Select works lib/Pod/t/termcap.t podlators test lib/Pod/t/text-options.t podlators test +lib/Pod/t/text-utf8.t podlators test lib/Pod/t/text.t podlators test lib/Pod/t/Usage.t See if Pod::Usage works lib/Pod/t/user.t See if Pod::LaTeX works diff --git a/lib/Pod/Man.pm b/lib/Pod/Man.pm index 9af59bb..4eca872 100644 --- a/lib/Pod/Man.pm +++ b/lib/Pod/Man.pm @@ -36,7 +36,7 @@ use POSIX qw(strftime); @ISA = qw(Pod::Simple); -$VERSION = '2.18'; +$VERSION = '2.19'; # Set the debugging level. If someone has inserted a debug function into this # class already, use that. Otherwise, use any Pod::Simple debug function @@ -70,8 +70,6 @@ sub new { my $self = $class->SUPER::new; # Tell Pod::Simple not to handle S<> by automatically inserting  . - # Note that this messes up Unicode output by embedding explicit ISO 8859-1 - # non-breaking spaces that we have to clean up later. $self->nbsp_for_S (1); # Tell Pod::Simple to keep whitespace whenever possible. @@ -94,6 +92,13 @@ sub new { # variables. %$self = (%$self, @_); + # Send errors to stderr if requested. + if ($$self{stderr}) { + $self->no_errata_section (1); + $self->complain_stderr (1); + delete $$self{stderr}; + } + # Initialize various other internal constants based on our arguments. $self->init_fonts; $self->init_quotes; @@ -362,13 +367,6 @@ sub format_text { $text =~ s/([^\x00-\x7F])/$ESCAPES{ord ($1)} || "X"/eg; } - # For Unicode output, unconditionally remap ISO 8859-1 non-breaking spaces - # to the correct code point. This is really a bug in Pod::Simple to be - # embedding ISO 8859-1 characters in the output stream that we see. - if ($$self{utf8} && ASCII) { - $text =~ s/\xA0/\xC2\xA0/g; - } - # Ensure that *roff doesn't convert literal quotes to UTF-8 single quotes, # but don't mess up our accept escapes. if ($literal) { @@ -1451,8 +1449,8 @@ __END__ Pod::Man - Convert POD data to formatted *roff input =for stopwords -en em ALLCAPS teeny fixedbold fixeditalic fixedbolditalic utf8 UTF-8 -Allbery Sean Burke Ossanna +en em ALLCAPS teeny fixedbold fixeditalic fixedbolditalic stderr utf8 +UTF-8 Allbery Sean Burke Ossanna Solaris =head1 SYNOPSIS @@ -1588,6 +1586,11 @@ that are reliably consistent are 1, 2, and 3. By default, section 1 will be used unless the file ends in C<.pm> in which case section 3 will be selected. +=item stderr + +Send error messages about invalid POD to standard error instead of +appending a POD ERRORS section to the generated *roff output. + =item utf8 By default, Pod::Man produces the most conservative possible *roff output diff --git a/lib/Pod/ParseLink.pm b/lib/Pod/ParseLink.pm index 18dd47e..d354788 100644 --- a/lib/Pod/ParseLink.pm +++ b/lib/Pod/ParseLink.pm @@ -30,7 +30,7 @@ use Exporter; @ISA = qw(Exporter); @EXPORT = qw(parselink); -$VERSION = 1.07; +$VERSION = 1.08; ############################################################################## # Implementation @@ -108,7 +108,7 @@ __END__ Pod::ParseLink - Parse an LEE formatting code in POD text =for stopwords -markup Allbery +markup Allbery URL =head1 SYNOPSIS diff --git a/lib/Pod/Text.pm b/lib/Pod/Text.pm index 18edb70..f0da802 100644 --- a/lib/Pod/Text.pm +++ b/lib/Pod/Text.pm @@ -37,7 +37,7 @@ use Pod::Simple (); # We have to export pod2text for backward compatibility. @EXPORT = qw(pod2text); -$VERSION = 3.09; +$VERSION = 3.10; ############################################################################## # Initialization @@ -85,6 +85,13 @@ sub new { my @opts = map { ("opt_$_", $opts{$_}) } keys %opts; %$self = (%$self, @opts); + # Send errors to stderr if requested. + if ($$self{opt_stderr}) { + $self->no_errata_section (1); + $self->complain_stderr (1); + delete $$self{opt_stderr}; + } + # Initialize various things from our parameters. $$self{opt_alt} = 0 unless defined $$self{opt_alt}; $$self{opt_indent} = 4 unless defined $$self{opt_indent}; @@ -238,7 +245,8 @@ sub reformat { return $self->wrap ($_); } -# Output text to the output device. +# Output text to the output device. Replace non-breaking spaces with spaces +# and soft hyphens with nothing. sub output { my ($self, $text) = @_; $text =~ tr/\240\255/ /d; @@ -632,7 +640,7 @@ __END__ Pod::Text - Convert POD data to formatted ASCII text =for stopwords -alt Allbery Sean Burke's +alt stderr Allbery Sean Burke's =head1 SYNOPSIS @@ -712,6 +720,11 @@ spaces, and will try to preserve that spacing. If set to false, all consecutive whitespace in non-verbatim paragraphs is compressed into a single space. Defaults to true. +=item stderr + +Send error messages about invalid POD to standard error instead of +appending a POD ERRORS section to the generated output. + =item width The column at which to wrap text on the right-hand side. Defaults to 76. diff --git a/lib/Pod/t/man-options.t b/lib/Pod/t/man-options.t index f00e7d1..0d86cb8 100644 --- a/lib/Pod/t/man-options.t +++ b/lib/Pod/t/man-options.t @@ -16,7 +16,7 @@ BEGIN { } unshift (@INC, '../blib/lib'); $| = 1; - print "1..7\n"; + print "1..16\n"; } END { @@ -25,10 +25,24 @@ END { use Pod::Man; +# Redirect stderr to a file. +sub stderr_save { + open (OLDERR, '>&STDERR') or die "Can't dup STDERR: $!\n"; + open (STDERR, '> out.err') or die "Can't redirect STDERR: $!\n"; +} + +# Restore stderr. +sub stderr_restore { + close STDERR; + open (STDERR, '>&OLDERR') or die "Can't dup STDERR: $!\n"; + close OLDERR; +} + $loaded = 1; print "ok 1\n"; my $n = 2; +eval { binmode (\*DATA, ':encoding(utf-8)') }; while () { my %options; next until $_ eq "###\n"; @@ -38,6 +52,8 @@ while () { $options{$option} = $value; } open (TMP, '> tmp.pod') or die "Cannot create tmp.pod: $!\n"; + eval { binmode (\*TMP, ':encoding(utf-8)') }; + print TMP "=encoding utf-8\n\n"; while () { last if $_ eq "###\n"; print TMP $_; @@ -45,10 +61,14 @@ while () { close TMP; my $parser = Pod::Man->new (%options) or die "Cannot create parser\n"; open (OUT, '> out.tmp') or die "Cannot create out.tmp: $!\n"; + eval { binmode (\*OUT, ':encoding(utf-8)') }; + stderr_save; $parser->parse_from_file ('tmp.pod', \*OUT); + stderr_restore; close OUT; my $accents = 0; open (TMP, 'out.tmp') or die "Cannot open out.tmp: $!\n"; + eval { binmode (\*TMP, ':encoding(utf-8)') }; while () { $accents = 1 if /Accent mark definitions/; last if /^\.nh/; @@ -80,6 +100,26 @@ while () { print "Expected\n========\n$expected\nOutput\n======\n$output\n"; } $n++; + open (ERR, 'out.err') or die "Cannot open out.err: $!\n"; + my $errors; + { + local $/; + $errors = ; + } + close ERR; + unlink ('out.err'); + $expected = ''; + while () { + last if $_ eq "###\n"; + $expected .= $_; + } + if ($errors eq $expected) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + print "Expected errors:\n ${expected}Errors:\n $errors"; + } + $n++; } # Below the marker are bits of POD and corresponding expected text output. @@ -113,6 +153,7 @@ Beyoncé! Beyoncé! Beyoncé!! .PP Older versions did not convert Beyoncé in verbatim. ### +### ### utf8 1 @@ -123,7 +164,8 @@ This is S. ### .SH "S<> output with UTF\-8" .IX Header "S<> output with UTF-8" -This is non\-breaking output. +This is non-breaking output. +### ### ### @@ -140,3 +182,48 @@ C> I> .IX Header "FIXED FONTS" \&\f(CR\*(C`foo \f(CYbar \f(CXbaz\f(CY\f(CR \f(CWbay\f(CR\*(C'\fR ### +### + +### +### +=over 4 + +=item Foo + +Bar. + +=head1 NEXT +### +.IP "Foo" 4 +.IX Item "Foo" +Bar. +.SH "NEXT" +.IX Header "NEXT" +.SH "POD ERRORS" +.IX Header "POD ERRORS" +Hey! \fBThe above document had some coding errors, which are explained below:\fR +.IP "Around line 9:" 4 +.IX Item "Around line 9:" +You forgot a '=back' before '=head1' +### +### + +### +stderr 1 +### +=over 4 + +=item Foo + +Bar. + +=head1 NEXT +### +.IP "Foo" 4 +.IX Item "Foo" +Bar. +.SH "NEXT" +.IX Header "NEXT" +### +tmp.pod around line 9: You forgot a '=back' before '=head1' +### diff --git a/lib/Pod/t/pod-spelling.t b/lib/Pod/t/pod-spelling.t index 3ac4f75..9c6bfbd 100644 --- a/lib/Pod/t/pod-spelling.t +++ b/lib/Pod/t/pod-spelling.t @@ -18,7 +18,7 @@ skip_all "Pod::Spell required to test POD spelling" if $@; my @spell; for my $dir (split ':', $ENV{PATH}) { if (-x "$dir/ispell") { - @spell = ("$dir/ispell", '-d', 'american', '-l'); + @spell = ("$dir/ispell", '-d', 'american', '-l', '-p', '/dev/null'); } last if @spell; } diff --git a/lib/Pod/t/text-options.t b/lib/Pod/t/text-options.t index 5eb05d3..24843e4 100644 --- a/lib/Pod/t/text-options.t +++ b/lib/Pod/t/text-options.t @@ -16,7 +16,7 @@ BEGIN { } unshift (@INC, '../blib/lib'); $| = 1; - print "1..5\n"; + print "1..13\n"; } END { @@ -25,6 +25,19 @@ END { use Pod::Text; +# Redirect stderr to a file. +sub stderr_save { + open (OLDERR, '>&STDERR') or die "Can't dup STDERR: $!\n"; + open (STDERR, '> out.err') or die "Can't redirect STDERR: $!\n"; +} + +# Restore stderr. +sub stderr_restore { + close STDERR; + open (STDERR, '>&OLDERR') or die "Can't dup STDERR: $!\n"; + close OLDERR; +} + $loaded = 1; print "ok 1\n"; @@ -45,7 +58,9 @@ while () { close TMP; my $parser = Pod::Text->new (%options) or die "Cannot create parser\n"; open (OUT, '> out.tmp') or die "Cannot create out.tmp: $!\n"; + stderr_save; $parser->parse_from_file ('tmp.pod', \*OUT); + stderr_restore; close OUT; open (TMP, 'out.tmp') or die "Cannot open out.tmp: $!\n"; my $output; @@ -67,6 +82,26 @@ while () { print "Expected\n========\n$expected\nOutput\n======\n$output\n"; } $n++; + open (ERR, 'out.err') or die "Cannot open out.err: $!\n"; + my $errors; + { + local $/; + $errors = ; + } + close ERR; + unlink ('out.err'); + $expected = ''; + while () { + last if $_ eq "###\n"; + $expected .= $_; + } + if ($errors eq $expected) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + print "Expected errors:\n ${expected}Errors:\n $errors"; + } + $n++; } # Below the marker are bits of POD and corresponding expected text output. @@ -111,6 +146,7 @@ Paragraph. Paragraph. ### +### ### margin 4 @@ -143,6 +179,7 @@ This is another indented paragraph. This is another indented paragraph. ### +### ### code 1 @@ -173,6 +210,7 @@ SAMPLE This is more random text. ### +### ### sentence 1 @@ -189,3 +227,45 @@ EXAMPLE eat all of the space in front of it. ### +### + +### +### +=over 4 + +=item Foo + +Bar. + +=head1 NEXT +### + Foo Bar. + +NEXT +POD ERRORS + Hey! The above document had some coding errors, which are explained + below: + + Around line 7: + You forgot a '=back' before '=head1' + +### +### + +### +stderr 1 +### +=over 4 + +=item Foo + +Bar. + +=head1 NEXT +### + Foo Bar. + +NEXT +### +tmp.pod around line 7: You forgot a '=back' before '=head1' +### diff --git a/lib/Pod/t/text-utf8.t b/lib/Pod/t/text-utf8.t new file mode 100755 index 0000000..7572825 --- /dev/null +++ b/lib/Pod/t/text-utf8.t @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w +# +# text-utf8.t -- Test Pod::Text with UTF-8 input. +# +# Copyright 2002, 2004, 2006, 2007, 2008 by Russ Allbery +# +# This program is free software; you may redistribute it and/or modify it +# under the same terms as Perl itself. + +BEGIN { + chdir 't' if -d 't'; + if ($ENV{PERL_CORE}) { + @INC = '../lib'; + } else { + unshift (@INC, '../blib/lib'); + } + unshift (@INC, '../blib/lib'); + $| = 1; + print "1..3\n"; +} + +END { + print "not ok 1\n" unless $loaded; +} + +use Pod::Text; +use Pod::Simple; + +$loaded = 1; +print "ok 1\n"; + +my $parser = Pod::Text->new or die "Cannot create parser\n"; +my $n = 2; +eval { binmode (\*DATA, ':encoding(utf-8)') }; +eval { binmode (\*STDOUT, ':encoding(utf-8)') }; +while () { + next until $_ eq "###\n"; + open (TMP, '> tmp.pod') or die "Cannot create tmp.pod: $!\n"; + eval { binmode (\*TMP, ':encoding(utf-8)') }; + print TMP "=encoding UTF-8\n\n"; + while () { + last if $_ eq "###\n"; + print TMP $_; + } + close TMP; + open (OUT, '> out.tmp') or die "Cannot create out.tmp: $!\n"; + eval { binmode (\*OUT, ':encoding(utf-8)') }; + $parser->parse_from_file ('tmp.pod', \*OUT); + close OUT; + open (TMP, 'out.tmp') or die "Cannot open out.tmp: $!\n"; + eval { binmode (\*TMP, ':encoding(utf-8)') }; + my $output; + { + local $/; + $output = ; + } + close TMP; + unlink ('tmp.pod', 'out.tmp'); + my $expected = ''; + while () { + last if $_ eq "###\n"; + $expected .= $_; + } + if ($output eq $expected) { + print "ok $n\n"; + } else { + print "not ok $n\n"; + print "Expected\n========\n$expected\nOutput\n======\n$output\n"; + } + $n++; +} + +# Below the marker are bits of POD and corresponding expected text output. +# This is used to test specific features or problems with Pod::Text. The +# input and output are separated by lines containing only ###. + +__DATA__ + +### +=head1 Test of SEE + +This is S. +### +Test of S<> + This is some whitespace. + +### + +### +=head1 I can eat glass + +=over 4 + +=item Esperanto + +Mi povas manĝi vitron, ĝi ne damaĝas min. + +=item Braille + +⠊⠀⠉⠁⠝⠀⠑⠁⠞⠀⠛⠇⠁⠎⠎⠀⠁⠝⠙⠀⠊⠞⠀⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑ + +=item Hindi + +मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती. + +=back + +See L +### +I can eat glass + Esperanto + Mi povas manĝi vitron, ĝi ne damaĝas min. + + Braille + ⠊⠀⠉⠁⠝⠀⠑⠁⠞⠀⠛⠇⠁⠎⠎⠀⠁⠝⠙⠀⠊⠞⠀⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑ + + Hindi + मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती. + + See + +### diff --git a/lib/Pod/t/text.t b/lib/Pod/t/text.t index 185e944..b4c7727 100644 --- a/lib/Pod/t/text.t +++ b/lib/Pod/t/text.t @@ -101,4 +101,3 @@ Test of S<> This is some whitespace. ### -== diff --git a/pod/pod2man.PL b/pod/pod2man.PL index c98f8de..58e3f21 100644 --- a/pod/pod2man.PL +++ b/pod/pod2man.PL @@ -61,11 +61,12 @@ my $stdin; # Parse our options, trying to retain backwards compatibility with pod2man but # allowing short forms as well. --lax is currently ignored. my %options; +$options{errors} = 'pod'; Getopt::Long::config ('bundling_override'); -GetOptions (\%options, 'section|s=s', 'release|r:s', 'center|c=s', - 'date|d=s', 'fixed=s', 'fixedbold=s', 'fixeditalic=s', - 'fixedbolditalic=s', 'name|n=s', 'official|o', 'quotes|q=s', - 'lax|l', 'help|h', 'verbose|v', 'utf8|u') or exit 1; +GetOptions (\%options, 'center|c=s', 'date|d=s', 'fixed=s', 'fixedbold=s', + 'fixeditalic=s', 'fixedbolditalic=s', 'help|h', 'lax|l', + 'name|n=s', 'official|o', 'quotes|q=s', 'release|r:s', + 'section|s=s', 'stderr', 'verbose|v', 'utf8|u') or exit 1; pod2usage (0) if $options{help}; # Official sets --center, but don't override things explicitly set. @@ -98,15 +99,16 @@ __END__ pod2man - Convert POD data to formatted *roff input =for stopwords -en em --utf8 UTF-8 overdo markup MT-LEVEL Allbery +en em --stderr stderr --utf8 UTF-8 overdo markup MT-LEVEL Allbery Solaris +URL =head1 SYNOPSIS -pod2man [B<--section>=I] [B<--release>[=I]] - [B<--center>=I] [B<--date>=I] [B<--fixed>=I] - [B<--fixedbold>=I] [B<--fixeditalic>=I] +pod2man [B<--center>=I] [B<--date>=I] + [B<--fixed>=I] [B<--fixedbold>=I] [B<--fixeditalic>=I] [B<--fixedbolditalic>=I] [B<--name>=I] [B<--official>] - [B<--lax>] [B<--quotes>=I] [B<--verbose>] + [B<--quotes>=I] [B<--release>[=I]] + [B<--section>=I] [B<--stderr>] [B<--utf8>] [B<--verbose>] [I [I] ...] pod2man B<--help> @@ -125,8 +127,8 @@ files can be processed in the same B invocation (saving module load and compile times) by providing multiple pairs of I and I files on the command line. -B<--section>, B<--release>, B<--center>, B<--date>, and B<--official> can be -used to set the headers and footers to use; if not given, Pod::Man will +B<--section>, B<--release>, B<--center>, B<--date>, and B<--official> can +be used to set the headers and footers to use; if not given, Pod::Man will assume various defaults. See below or L for details. B assumes that your *roff formatters have a fixed-width font @@ -246,6 +248,13 @@ that are reliably consistent are 1, 2, and 3. By default, section 1 will be used unless the file ends in C<.pm>, in which case section 3 will be selected. +=item B<--stderr> + +By default, B puts any errors detected in the POD input in a POD +ERRORS section in the output manual page. If B<--stderr> is given, errors +are sent to standard error instead and the POD ERRORS section is +suppressed. + =item B<-u>, B<--utf8> By default, B produces the most conservative possible *roff diff --git a/pod/pod2text.PL b/pod/pod2text.PL index 81d29a6..f9eb462 100644 --- a/pod/pod2text.PL +++ b/pod/pod2text.PL @@ -79,7 +79,8 @@ $options{sentence} = 0; Getopt::Long::config ('bundling'); GetOptions (\%options, 'alt|a', 'code', 'color|c', 'help|h', 'indent|i=i', 'loose|l', 'margin|left-margin|m=i', 'overstrike|o', - 'quotes|q=s', 'sentence|s', 'termcap|t', 'width|w=i') or exit 1; + 'quotes|q=s', 'sentence|s', 'stderr', 'termcap|t', 'width|w=i') + or exit 1; pod2usage (1) if $options{help}; # Figure out what formatter we're going to use. -c overrides -t. @@ -112,12 +113,12 @@ __END__ pod2text - Convert POD data to formatted ASCII text =for stopwords --aclost --alt Allbery +-aclost --alt --stderr Allbery =head1 SYNOPSIS pod2text [B<-aclost>] [B<--code>] [B<-i> I] S<[B<-q> I]> - S<[B<-w> I]> [I [I ...]] + [B<--stderr>] S<[B<-w> I]> [I [I ...]] pod2text B<-h> @@ -202,6 +203,13 @@ Assume each sentence ends with two spaces and try to preserve that spacing. Without this option, all consecutive whitespace in non-verbatim paragraphs is compressed into a single space. +=item B<--stderr> + +By default, B puts any errors detected in the POD input in a POD +ERRORS section in the output manual page. If B<--stderr> is given, errors +are sent to standard error instead and the POD ERRORS section is +suppressed. + =item B<-t>, B<--termcap> Try to determine the width of the screen and the bold and underline -- 2.7.4