3 # Generate a short man page from --help and --version output.
4 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
5 # 2010, 2011, 2012 Free Software Foundation, Inc.
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, see <http://www.gnu.org/licenses/>.
20 # Written by Brendan O'Dea <bod@debian.org>
21 # Available from ftp://ftp.gnu.org/gnu/help2man/
26 use Text::Tabs qw(expand);
27 use POSIX qw(strftime setlocale LC_ALL);
29 my $this_program = 'help2man';
30 my $this_version = '1.40.12';
36 die "$this_program: no locale support (Locale::gettext required)\n"
37 unless $locale eq 'C';
42 sub enc_user { $_[0] }
43 sub kark { die +(sprintf shift, @_), "\n" }
46 my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
49 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010,
50 2011, 2012 Free Software Foundation, Inc.
51 This is free software; see the source for copying conditions. There is NO
52 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
54 Written by Brendan O'Dea <bod@debian.org>
57 my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
58 `%s' generates a man page out of `--help' and `--version' output.
60 Usage: %s [OPTION]... EXECUTABLE
62 -n, --name=STRING description for the NAME paragraph
63 -s, --section=SECTION section number for manual page (1, 6, 8)
64 -m, --manual=TEXT name of manual (User Commands, ...)
65 -S, --source=TEXT source of program (FSF, Debian, ...)
66 -L, --locale=STRING select locale (default "C")
67 -i, --include=FILE include material from `FILE'
68 -I, --opt-include=FILE include material from `FILE' if it exists
69 -o, --output=FILE send output to `FILE'
70 -p, --info-page=TEXT name of Texinfo manual
71 -N, --no-info suppress pointer to Texinfo manual
72 -l, --libtool exclude the `lt-' from the program name
73 --help print this help, then exit
74 --version print version number, then exit
76 EXECUTABLE should accept `--help' and `--version' options and produce output on
77 stdout although alternatives may be specified using:
79 -h, --help-option=STRING help option string
80 -v, --version-option=STRING version option string
81 --version-string=STRING version string
82 --no-discard-stderr include stderr when parsing option output
84 Report bugs to <bug-help2man@gnu.org>.
90 my $help_option = '--help';
91 my $version_option = '--version';
92 my $discard_stderr = 1;
93 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
97 'n|name=s' => \$opt_name,
98 's|section=s' => \$section,
99 'm|manual=s' => \$manual,
100 'S|source=s' => \$source,
101 'L|locale=s' => sub { configure_locale pop },
102 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
103 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
104 'o|output=s' => \$opt_output,
105 'p|info-page=s' => \$opt_info,
106 'N|no-info' => \$opt_no_info,
107 'l|libtool' => \$opt_libtool,
108 'help' => sub { print $help_info; exit },
109 'version' => sub { print $version_info; exit },
110 'h|help-option=s' => \$help_option,
111 'v|version-option=s' => \$version_option,
112 'version-string=s' => \$version_text,
113 'discard-stderr!' => \$discard_stderr,
117 Getopt::Long::config('bundling');
118 die $help_info unless GetOptions %opt_def and @ARGV == 1;
122 my @include = (); # retain order given in include file
124 # Process include file (if given). Format is:
137 my ($inc, $required) = @{shift @opt_include};
139 next unless -f $inc or $required;
140 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
141 unless open INC, $inc;
144 my $hash = \%include;
148 # Convert input to internal Perl format, so that multibyte
149 # sequences are treated as single characters.
153 if (/^\[([^]]+)\]\s*$/)
159 push @include, $key unless $include{$key};
164 if (m!^/(.*)/([ims]*)\s*$!)
166 my $pat = $2 ? "(?$2)$1" : $1;
169 eval { $key = qr($pat) };
172 $@ =~ s/ at .*? line \d.*//;
180 # Check for options before the first section--anything else is
181 # silently ignored, allowing the first for comments and
195 $hash->{$key} ||= '';
201 kark N_("%s: no valid information found in `%s'"), $this_program, $inc
205 # Compress trailing blank lines.
206 for my $hash (\(%include, %append))
208 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
211 sub get_option_value;
213 # Grab help and version info from executable.
214 my $help_text = get_option_value $ARGV[0], $help_option;
215 $version_text ||= get_option_value $ARGV[0], $version_option;
217 # Translators: the following message is a strftime(3) format string, which in
218 # the English version expands to the month as a word and the full year. It
219 # is used on the footer of the generated manual pages. If in doubt, you may
220 # just use %x as the value (which should be the full locale-specific date).
221 my $date = enc strftime _("%B %Y"), localtime;
222 (my $program = $ARGV[0]) =~ s!.*/!!;
223 my $package = $program;
228 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
229 $this_program, $opt_output, $! if -e $opt_output;
231 open STDOUT, ">$opt_output"
232 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
235 # The first line of the --version information is assumed to be in one
236 # of the following formats:
239 # <program> <version>
240 # {GNU,Free} <program> <version>
241 # <program> ({GNU,Free} <package>) <version>
242 # <program> - {GNU,Free} <package> <version>
244 # and separated from any copyright/author details by a blank line.
246 ($_, $version_text) = ((split /\n+/, $version_text, 2), '');
248 if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
249 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
255 elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
258 $package = $1 ? "$1$2" : $2;
268 # No info for `info' itself.
269 $opt_no_info = 1 if $program eq 'info';
271 # Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
272 # upper case are manual page section headings. The man(1) manual page in your
273 # language, if available should provide the conventional translations.
274 for ($include{_('NAME')})
276 if ($opt_name) # --name overrides --include contents.
278 $_ = "$program \\- $opt_name\n";
280 elsif ($_) # Use first name given as $program
282 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
284 else # Set a default (useless) NAME paragraph.
286 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
291 # Man pages traditionally have the page title in caps.
292 my $PROGRAM = uc $program;
294 # Set default page head/footers
295 $source ||= "$program $version";
300 if (/^(1[Mm]|8)/) { $manual = enc _('System Administration Utilities') }
301 elsif (/^6/) { $manual = enc _('Games') }
302 else { $manual = enc _('User Commands') }
306 # Extract usage clause(s) [if any] for SYNOPSIS.
307 # Translators: "Usage" and "or" here are patterns (regular expressions) which
308 # are used to match the usage synopsis in program output. An example from cp
309 # (GNU coreutils) which contains both strings:
310 # Usage: cp [OPTION]... [-T] SOURCE DEST
311 # or: cp [OPTION]... SOURCE... DIRECTORY
312 # or: cp [OPTION]... -t DIRECTORY SOURCE...
313 my $PAT_USAGE = _('Usage');
314 my $PAT_USAGE_CONT = _('or');
315 if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
322 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
328 $synopsis .= ".br\n" if $synopsis;
330 s/^lt-// if $opt_libtool;
332 $synopsis .= ".B $1\n";
334 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
335 s/^/\\fI/ unless s/^\\fR//;
346 $include{_('SYNOPSIS')} ||= $synopsis;
349 # Process text, initial section is DESCRIPTION.
350 my $sect = _('DESCRIPTION');
351 $_ = "$help_text\n\n$version_text";
353 # Normalise paragraph breaks.
358 # Join hyphenated lines.
359 s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
361 # Temporarily exchange leading dots, apostrophes and backslashes for
367 # Translators: patterns are used to match common program output. In the source
368 # these strings are all of the form of "my $PAT_something = _('...');" and are
369 # regular expressions. If there is more than one commonly used string, you
370 # may separate alternatives with "|". Spaces in these expressions are written
371 # as " +" to indicate that more than one space may be matched. The string
372 # "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
373 # optional word, so that either "Report bugs" or "Report _program_ bugs" will
375 my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|Email +bug +reports +to');
376 my $PAT_AUTHOR = _('Written +by');
377 my $PAT_OPTIONS = _('Options');
378 my $PAT_ENVIRONMENT = _('Environment');
379 my $PAT_FILES = _('Files');
380 my $PAT_EXAMPLES = _('Examples');
381 my $PAT_FREE_SOFTWARE = _('This +is +free +software');
383 # Start a new paragraph (if required) for these.
384 s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR) /$1\n\n$2 /og;
386 # Convert iso-8859-1 copyright symbol or (c) to nroff
388 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
394 # Convert some standard paragraph names.
395 if (s/^($PAT_OPTIONS): *\n//o)
397 $sect = _('OPTIONS');
400 if (s/^($PAT_ENVIRONMENT): *\n//o)
402 $sect = _('ENVIRONMENT');
405 if (s/^($PAT_FILES): *\n//o)
410 elsif (s/^($PAT_EXAMPLES): *\n//o)
412 $sect = _('EXAMPLES');
419 $sect = _('COPYRIGHT');
422 # Bug reporting section.
423 elsif (/^($PAT_BUGS) /o)
425 $sect = _('REPORTING BUGS');
429 elsif (/^($PAT_AUTHOR)/o)
434 # Examples, indicated by an indented leading $, % or > are
435 # rendered in a constant width font.
436 if (/^( +)([\$\%>] )\S/)
441 $include{$sect} ||= '';
442 while (s/^$indent\Q$prefix\E(\S.*)\n*//)
444 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
452 $include{$sect} ||= '';
454 # Sub-sections have a trailing colon and the second line indented.
455 if (s/^(\S.*:) *\n / /)
457 $matched .= $& if %append;
458 $include{$sect} .= qq(.SS "$1"\n);
464 # Option with description.
465 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
467 $matched .= $& if %append;
468 $indent = length ($4 || "$1$3");
469 $content = ".TP\n\x84$2\n\x84$5\n";
472 # Indent may be different on second line.
473 $indent = length $& if /^ {20,}/;
477 # Option without description.
478 elsif (s/^ {1,10}([+-]\S.*)\n//)
480 $matched .= $& if %append;
481 $content = ".HP\n\x84$1\n";
482 $indent = 80; # not continued
485 # Indented paragraph with tag.
486 elsif (s/^( +(\S.*?) +)(\S.*)\n//)
488 $matched .= $& if %append;
490 $content = ".TP\n\x84$2\n\x84$3\n";
493 # Indented paragraph.
494 elsif (s/^( +)(\S.*)\n//)
496 $matched .= $& if %append;
498 $content = ".IP\n\x84$2\n";
501 # Left justified paragraph.
505 $matched .= $& if %append;
506 $content = ".PP\n" if $include{$sect};
510 # Append continuations.
511 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
513 $matched .= $& if %append;
514 $content .= "\x84$1\n";
517 # Move to next paragraph.
522 # Leading dot and apostrophe protection.
528 s/(^| |\()(-[][\w=-]+)/$1 . convert_option $2/mge;
530 # Escape remaining hyphens
533 if ($sect eq 'COPYRIGHT')
535 # Insert line breaks before additional copyright messages
536 # and the disclaimer.
537 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
539 elsif ($sect eq 'REPORTING BUGS')
541 # Handle multi-line bug reporting sections of the form:
543 # Report <program> bugs to <addr>
544 # GNU <package> home page: <url>
546 s/\n([[:upper:]])/\n.br\n$1/g;
550 # Check if matched paragraph contains /pat/.
553 for my $pat (keys %append)
555 if ($matched =~ $pat)
557 $content .= ".PP\n" unless $append{$pat} =~ /^\./;
558 $content .= $append{$pat};
563 $include{$sect} .= $content;
566 # Refer to the real documentation.
567 unless ($opt_no_info)
569 my $info_page = $opt_info || $program;
571 $sect = _('SEE ALSO');
572 $include{$sect} ||= '';
573 $include{$sect} .= ".PP\n" if $include{$sect};
574 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
575 The full documentation for
577 is maintained as a Texinfo manual. If the
581 programs are properly installed at your site, the command
585 should give you access to the complete manual.
591 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
592 .TH $PROGRAM "$section" "$date" "$source" "$manual"
596 my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
597 _('ENVIRONMENT'), _('FILES'), _('EXAMPLES'));
599 my @post = (_('AUTHOR'), _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
600 my $filter = join '|', @pre, @post;
603 for my $sect (@pre, (grep ! /^($filter)$/o, @include), @post)
607 my $quote = $sect =~ /\W/ ? '"' : '';
608 print enc ".SH $quote$sect$quote\n";
610 for ($include{$sect})
612 # Replace leading dot, apostrophe, backslash and hyphen
619 # Convert some latin1 chars to troff equivalents
620 s/\xa0/\\ /g; # non-breaking space
627 close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
628 $opt_output || 'stdout', $!;
632 # Call program with given option and return results.
635 my ($prog, $opt) = @_;
636 my $stderr = $discard_stderr ? '/dev/null' : '&1';
638 map { s/ +$//; expand $_ }
640 `$prog $opt 2>$stderr`;
644 my $err = N_("%s: can't get `%s' info from %s%s");
645 my $extra = $discard_stderr
646 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr")
649 kark $err, $this_program, $opt, $prog, $extra;
655 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
656 # embolden. Option arguments get italicised.
659 local $_ = '\fB' . shift;
662 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)