3 # Generate a short man page from --help and --version output.
4 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software
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 2, 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, write to the Free Software Foundation,
19 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 # Written by Brendan O'Dea <bod@debian.org>
22 # Available from ftp://ftp.gnu.org/gnu/help2man/
27 use Text
::Tabs
qw(expand);
28 use POSIX
qw(strftime setlocale LC_TIME);
30 my $this_program = 'help2man';
31 my $this_version = '1.28';
32 my $version_info = <<EOT;
33 GNU $this_program $this_version
35 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
36 This is free software; see the source for copying conditions. There is NO
37 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
39 Written by Brendan O'Dea <bod\@debian.org>
42 my $help_info = <<EOT;
43 `$this_program' generates a man page out of `--help' and `--version' output.
45 Usage: $this_program [OPTIONS]... EXECUTABLE
47 -n, --name=STRING description for the NAME paragraph
48 -s, --section=SECTION section number for manual page (1, 6, 8)
49 -m, --manual=TEXT name of manual (User Commands, ...)
50 -S, --source=TEXT source of program (FSF, Debian, ...)
51 -i, --include=FILE include material from `FILE'
52 -I, --opt-include=FILE include material from `FILE' if it exists
53 -o, --output=FILE send output to `FILE'
54 -p, --info-page=TEXT name of Texinfo manual
55 -N, --no-info suppress pointer to Texinfo manual
56 --help print this help, then exit
57 --version print version number, then exit
59 EXECUTABLE should accept `--help' and `--version' options although
60 alternatives may be specified using:
62 -h, --help-option=STRING help option string
63 -v, --version-option=STRING version option string
65 Report bugs to <bug-help2man\@gnu.org>.
71 my $help_option = '--help';
72 my $version_option = '--version';
73 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info);
76 'n|name=s' => \
$opt_name,
77 's|section=s' => \
$section,
78 'm|manual=s' => \
$manual,
79 'S|source=s' => \
$source,
80 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
81 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
82 'o|output=s' => \
$opt_output,
83 'p|info-page=s' => \
$opt_info,
84 'N|no-info' => \
$opt_no_info,
85 'h|help-option=s' => \
$help_option,
86 'v|version-option=s' => \
$version_option,
90 Getopt
::Long
::config
('bundling');
92 help
=> sub { print $help_info; exit },
93 version
=> sub { print $version_info; exit },
96 die $help_info unless @ARGV == 1;
100 my @include = (); # retain order given in include file
102 # Process include file (if given). Format is:
115 my ($inc, $required) = @
{shift @opt_include};
117 next unless -f
$inc or $required;
118 die "$this_program: can't open `$inc' ($!)\n"
119 unless open INC
, $inc;
122 my $hash = \
%include;
133 push @include, $key unless $include{$key};
138 if (m!^/(.*)/([ims]*)!)
140 my $pat = $2 ?
"(?$2)$1" : $1;
143 eval { $key = qr
($pat) };
146 $@
=~ s/ at .*? line \d.*//;
154 # Check for options before the first section--anything else is
155 # silently ignored, allowing the first for comments and
169 $hash->{$key} ||= '';
175 die "$this_program: no valid information found in `$inc'\n"
179 # Compress trailing blank lines.
180 for my $hash (\
(%include, %append))
182 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
185 # Turn off localisation of executable's output.
186 @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x
3;
188 # Turn off localisation of date (for strftime).
189 setlocale LC_TIME
, 'C';
191 # Grab help and version info from executable.
192 my ($help_text, $version_text) = map {
193 join '', map { s/ +$//; expand
$_ } `$ARGV[0] $_ 2>/dev/null`
194 or die "$this_program: can't get `$_' info from $ARGV[0]\n"
195 } $help_option, $version_option;
197 my $date = strftime
"%B %Y", localtime;
198 (my $program = $ARGV[0]) =~ s!.*/!!;
199 my $package = $program;
205 or die "$this_program: can't unlink $opt_output ($!)\n"
208 open STDOUT
, ">$opt_output"
209 or die "$this_program: can't create $opt_output ($!)\n";
212 # The first line of the --version information is assumed to be in one
213 # of the following formats:
216 # <program> <version>
217 # {GNU,Free} <program> <version>
218 # <program> ({GNU,Free} <package>) <version>
219 # <program> - {GNU,Free} <package> <version>
221 # and seperated from any copyright/author details by a blank line.
223 ($_, $version_text) = split /\n+/, $version_text, 2;
225 if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
226 /^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
232 elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
235 $package = $1 ?
"$1$2" : $2;
245 # No info for `info' itself.
246 $opt_no_info = 1 if $program eq 'info';
248 # --name overrides --include contents.
249 $include{NAME
} = "$program \\- $opt_name\n" if $opt_name;
251 # Default (useless) NAME paragraph.
252 $include{NAME
} ||= "$program \\- manual page for $program $version\n";
254 # Man pages traditionally have the page title in caps.
255 my $PROGRAM = uc $program;
257 # Set default page head/footers
258 $source ||= "$program $version";
263 if (/^(1[Mm]|8)/) { $manual = 'System Administration Utilities' }
264 elsif (/^6/) { $manual = 'Games' }
265 else { $manual = 'User Commands' }
269 # Extract usage clause(s) [if any] for SYNOPSIS.
270 if ($help_text =~ s/^Usage:( +(\S+))(.*)((?:\n(?: {6}\1| *or: +\S).*)*)//m)
277 for (split /\n/) { s/^ *(or: +)?//; push @syn, $_ }
283 $synopsis .= ".br\n" if $synopsis;
286 $synopsis .= ".B $1\n";
288 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
289 s/^/\\fI/ unless s/^\\fR//;
300 $include{SYNOPSIS
} ||= $synopsis;
303 # Process text, initial section is DESCRIPTION.
304 my $sect = 'DESCRIPTION';
305 $_ = "$help_text\n\n$version_text";
307 # Normalise paragraph breaks.
312 # Temporarily exchange leading dots, apostrophes and backslashes for
318 # Start a new paragraph (if required) for these.
319 s/([^\n])\n(Report +bugs|Email +bug +reports +to|Written +by)/$1\n\n$2/g;
325 # Convert some standard paragraph names.
326 if (s/^(Options|Examples): *\n//)
333 if (/^Copyright +[(\xa9]/)
336 $include{$sect} ||= '';
337 $include{$sect} .= ".PP\n" if $include{$sect};
340 ($copy, $_) = split /\n\n/, $_, 2;
347 # Convert iso9959-1 copyright symbol or (c) to nroff
349 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
351 # Insert line breaks before additional copyright messages
352 # and the disclaimer.
353 s/(.)\n(Copyright |This +is +free +software)/$1\n.br\n$2/g;
355 # Join hyphenated lines.
356 s/([A-Za-z])-\n */$1/g;
359 $include{$sect} .= $copy;
364 # Catch bug report text.
365 if (/^(Report +bugs|Email +bug +reports +to) /)
367 $sect = 'REPORTING BUGS';
371 elsif (/^Written +by/)
376 # Examples, indicated by an indented leading $, % or > are
377 # rendered in a constant width font.
378 if (/^( +)([\$\%>] )\S/)
383 $include{$sect} ||= '';
384 while (s/^$indent\Q$prefix\E(\S.*)\n*//)
386 $include{$sect} .= "$break\n\\f(CW$prefix$1\\fR\n";
394 $include{$sect} ||= '';
396 # Sub-sections have a trailing colon and the second line indented.
397 if (s/^(\S.*:) *\n / /)
399 $matched .= $& if %append;
400 $include{$sect} .= qq(.SS
"$1"\n);
406 # Option with description.
407 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
409 $matched .= $& if %append;
410 $indent = length ($4 || "$1$3");
411 $content = ".TP\n\x83$2\n\x83$5\n";
414 # Indent may be different on second line.
415 $indent = length $& if /^ {20,}/;
419 # Option without description.
420 elsif (s/^ {1,10}([+-]\S.*)\n//)
422 $matched .= $& if %append;
423 $content = ".HP\n\x83$1\n";
424 $indent = 80; # not continued
427 # Indented paragraph with tag.
428 elsif (s/^( +(\S.*?) +)(\S.*)\n//)
430 $matched .= $& if %append;
432 $content = ".TP\n\x83$2\n\x83$3\n";
435 # Indented paragraph.
436 elsif (s/^( +)(\S.*)\n//)
438 $matched .= $& if %append;
440 $content = ".IP\n\x83$2\n";
443 # Left justified paragraph.
447 $matched .= $& if %append;
448 $content = ".PP\n" if $include{$sect};
452 # Append continuations.
453 while (s/^ {$indent}(\S.*)\n//)
455 $matched .= $& if %append;
456 $content .= "\x83$1\n"
459 # Move to next paragraph.
464 # Leading dot and apostrophe protection.
470 s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge;
473 # Check if matched paragraph contains /pat/.
476 for my $pat (keys %append)
478 if ($matched =~ $pat)
480 $content .= ".PP\n" unless $append{$pat} =~ /^\./;
481 $content .= $append{$pat};
486 $include{$sect} .= $content;
489 # Refer to the real documentation.
490 unless ($opt_no_info)
492 my $info_page = $opt_info || $program;
495 $include{$sect} ||= '';
496 $include{$sect} .= ".PP\n" if $include{$sect};
497 $include{$sect} .= <<EOT;
498 The full documentation for
500 is maintained as a Texinfo manual. If the
504 programs are properly installed at your site, the command
508 should give you access to the complete manual.
514 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
515 .TH $PROGRAM "$section" "$date" "$source" "$manual"
519 my @pre = qw(NAME SYNOPSIS DESCRIPTION OPTIONS EXAMPLES);
520 my @post = ('AUTHOR', 'REPORTING BUGS', 'COPYRIGHT', 'SEE ALSO');
521 my $filter = join '|', @pre, @post;
524 for (@pre, (grep ! /^($filter)$/o, @include), @post)
528 my $quote = /\W/ ?
'"' : '';
529 print ".SH $quote$_$quote\n";
533 # Replace leading dot, apostrophe and backslash tokens.
544 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
545 # embolden. Option arguments get italicised.
548 local $_ = '\fB' . shift;
551 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)