doc: remove extraneous new lines in some man pages
[coreutils.git] / man / help2man
blob960eebcae24218c25b4dde62afc94bdcb7a4fd68
1 #!/usr/bin/perl -w
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, 2013, 2014, 2015, 2016, 2017, 2020, 2021, 2022, 2025
6 # Free Software Foundation, Inc.
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3, or (at your option)
11 # any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, see <https://www.gnu.org/licenses/>.
21 # Written by Brendan O'Dea <bod@debian.org>
22 # Available from https://ftp.gnu.org/gnu/help2man/
24 use 5.008;
25 use strict;
26 use Getopt::Long;
27 use Text::ParseWords qw(shellwords);
28 use Text::Tabs qw(expand);
29 use POSIX qw(strftime setlocale LC_ALL);
31 my $this_program = 'help2man';
32 my $this_version = '1.50.1';
34 sub _ { $_[0] }
35 sub configure_locale
37 my $locale = shift;
38 die "$this_program: no locale support (Locale::gettext required)\n"
39 unless $locale eq 'C';
42 sub dec { $_[0] }
43 sub enc { $_[0] }
44 sub enc_user { $_[0] }
45 sub kark { die +(sprintf shift, @_), "\n" }
46 sub N_ { $_[0] }
48 sub program_basename;
49 sub get_option_value;
50 sub convert_option;
51 sub fix_italic_spacing;
52 sub set_indent;
54 my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version;
55 GNU %s %s
57 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
58 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2020, 2021, 2022, 2025 Free
59 Software Foundation, Inc.
60 This is free software; see the source for copying conditions. There is NO
61 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
63 Written by Brendan O'Dea <bod@debian.org>
64 EOT
66 my $help_info = enc_user sprintf _(<<'EOT'), $this_program, $this_program;
67 `%s' generates a man page out of `--help' and `--version' output.
69 Usage: %s [OPTION]... EXECUTABLE
71 -n, --name=STRING description for the NAME paragraph
72 -s, --section=SECTION section number for manual page (1, 6, 8)
73 -m, --manual=TEXT name of manual (User Commands, ...)
74 -S, --source=TEXT source of program (FSF, Debian, ...)
75 -L, --locale=STRING select locale (default "C")
76 -i, --include=FILE include material from `FILE'
77 -I, --opt-include=FILE include material from `FILE' if it exists
78 -o, --output=FILE send output to `FILE'
79 -p, --info-page=TEXT name of Texinfo manual
80 -N, --no-info suppress pointer to Texinfo manual
81 -l, --libtool exclude the `lt-' from the program name
82 --loose-indent relax matching of indented continuation lines
83 -b, --bold-refs apply bold style to references
84 --help print this help, then exit
85 --version print version number, then exit
87 EXECUTABLE should accept `--help' and `--version' options and produce output on
88 stdout although alternatives may be specified using:
90 -h, --help-option=STRING help option string
91 -v, --version-option=STRING version option string
92 --version-string=STRING version string
93 --no-discard-stderr include stderr when parsing option output
95 Report bugs to <bug-help2man@gnu.org>.
96 EOT
98 my $section = 1;
99 my $manual = '';
100 my $source = '';
101 my $help_option = '--help';
102 my $version_option = '--version';
103 my $loose_indent = 0;
104 my $discard_stderr = 1;
105 my ($opt_name, @opt_include, $opt_output, $opt_info, $opt_no_info, $opt_libtool,
106 $opt_bold_refs, $version_text);
108 my %opt_def = (
109 'n|name=s' => \$opt_name,
110 's|section=s' => \$section,
111 'm|manual=s' => \$manual,
112 'S|source=s' => \$source,
113 'L|locale=s' => sub { configure_locale pop },
114 'i|include=s' => sub { push @opt_include, [ pop, 1 ] },
115 'I|opt-include=s' => sub { push @opt_include, [ pop, 0 ] },
116 'o|output=s' => \$opt_output,
117 'p|info-page=s' => \$opt_info,
118 'N|no-info' => \$opt_no_info,
119 'l|libtool' => \$opt_libtool,
120 'loose-indent!' => \$loose_indent,
121 'b|bold-refs' => \$opt_bold_refs,
122 'help' => sub { print $help_info; exit },
123 'version' => sub { print $version_info; exit },
124 'h|help-option=s' => \$help_option,
125 'v|version-option=s' => \$version_option,
126 'version-string=s' => \$version_text,
127 'discard-stderr!' => \$discard_stderr,
130 # Parse options.
131 Getopt::Long::config('bundling');
132 die $help_info unless GetOptions %opt_def and @ARGV == 1;
134 my %include = ();
135 my %replace = ();
136 my %append = ();
137 my %append_match = ();
138 my @sections = (); # retain order of include file or in-line *section*s
140 # Process include file (if given). Format is:
142 # Optional initial text, ignored. May include lines starting with `-'
143 # which are processed as options.
145 # [section]
146 # Verbatim text to be included in the named section. By default at
147 # the start, but in the case of `name' and `synopsis' the content
148 # will replace the autogenerated contents.
150 # [<section]
151 # Verbatim text to be inserted at the start of the named section.
153 # [=section]
154 # Verbatim text to replace the named section.
156 # [>section]
157 # Verbatim text to be appended to the end of the named section.
159 # /pattern/
160 # Verbatim text for inclusion below a paragraph matching `pattern'.
163 while (@opt_include)
165 my ($inc, $required) = @{shift @opt_include};
167 next unless -f $inc or $required;
168 kark N_("%s: can't open `%s' (%s)"), $this_program, $inc, $!
169 unless open INC, $inc;
171 my $key;
172 my $hash;
174 while (<INC>)
176 # Convert input to internal Perl format, so that multibyte
177 # sequences are treated as single characters.
178 $_ = dec $_;
180 # [section]
181 if (/^\[([^]]+)\]\s*$/)
183 $key = uc $1;
184 $key =~ s/^\s+//;
185 $key =~ s/\s+$//;
186 $hash = \%include;
187 # Handle explicit [<section], [=section] and [>section].
188 if ($key =~ s/^([<>=])\s*//)
190 if ($1 eq '>') { $hash = \%append; }
191 elsif ($1 eq '=') { $hash = \%replace; }
193 # NAME/SYNOPSIS replace by default.
194 elsif ($key eq _('NAME') or $key eq _('SYNOPSIS'))
196 $hash = \%replace;
198 else
200 $hash = \%include;
203 push @sections, $key;
204 next;
207 # /pattern/
208 if (m!^/(.*)/([ims]*)\s*$!)
210 my $pat = $2 ? "(?$2)$1" : $1;
212 # Check pattern.
213 eval { $key = qr($pat) };
214 if ($@)
216 $@ =~ s/ at .*? line \d.*//;
217 die "$inc:$.:$@";
220 $hash = \%append_match;
221 next;
224 # Check for options before the first section--anything else is
225 # silently ignored, allowing the first for comments and
226 # revision info.
227 unless ($key)
229 # Handle options.
230 if (/^-/)
232 local @ARGV = shellwords $_;
233 GetOptions %opt_def;
236 next;
239 $hash->{$key} .= $_;
242 close INC;
244 kark N_("%s: no valid information found in `%s'"), $this_program, $inc
245 unless $key;
248 # Compress trailing blank lines.
249 for my $hash (\(%include, %replace, %append, %append_match))
251 for (keys %$hash) { $hash->{$_} =~ s/\n+$/\n/ }
254 # Grab help and version info from executable.
255 my $help_text = get_option_value $ARGV[0], $help_option;
256 $version_text ||= get_option_value $ARGV[0], $version_option;
258 # By default the generated manual pages will include the current date. This may
259 # however be overridden by setting the environment variable $SOURCE_DATE_EPOCH
260 # to an integer value of the seconds since the UNIX epoch. This is primarily
261 # intended to support reproducible builds (wiki.debian.org/ReproducibleBuilds)
262 # and will additionally ensure that the output date string is UTC.
263 my $epoch_secs = time;
264 if (exists $ENV{SOURCE_DATE_EPOCH} and $ENV{SOURCE_DATE_EPOCH} =~ /^(\d+)$/)
266 $epoch_secs = $1;
267 $ENV{TZ} = 'UTC0';
270 # Translators: the following message is a strftime(3) format string, which in
271 # the English version expands to the month as a word and the full year. It
272 # is used on the footer of the generated manual pages. If in doubt, you may
273 # just use %x as the value (which should be the full locale-specific date).
274 my $date = strftime _("%B %Y"), localtime $epoch_secs;
275 my $program = program_basename $ARGV[0];
276 my $package = $program;
277 my $version;
279 if ($opt_output)
281 unlink $opt_output or kark N_("%s: can't unlink %s (%s)"),
282 $this_program, $opt_output, $! if -e $opt_output;
284 open STDOUT, ">$opt_output"
285 or kark N_("%s: can't create %s (%s)"), $this_program, $opt_output, $!;
288 # The first line of the --version information is assumed to be in one
289 # of the following formats:
291 # <version>
292 # <program> <version>
293 # {GNU,Free} <program> <version>
294 # <program> ({GNU,Free,} <package>) <version>
295 # <program> - {GNU,Free,} <package> <version>
296 # <program> - {GNU,Free,} <package> - <version>
298 # and separated from any copyright/author details by a blank line.
300 ($_, $version_text) = ((split /\n+/, $version_text, 2), '');
302 if (/^(\S+) +\(((?:(?:GNU|Free) +)?[^)]+)\) +(\S.*)$/ or
303 /^(\S+) +- +((?:(?:GNU|Free) +)?\S.*) +- +(\S.*)$/ or
304 /^(\S+) +- +((?:(?:GNU|Free) +)?\S+) +(\S.*)$/)
306 $program = program_basename $1;
307 $package = $2;
308 $version = $3;
310 elsif (/^((?:GNU|Free) +)?(\S+) +(\S.*)$/)
312 $program = program_basename $2;
313 $package = $1 ? "$1$program" : $program;
314 $version = $3;
316 else
318 $version = $_;
321 # No info for `info' itself.
322 $opt_no_info = 1 if $program eq 'info';
324 if ($opt_name)
326 # --name overrides --include contents.
327 $replace{_('NAME')} = "$program \\- $opt_name\n";
330 # Translators: "NAME", "SYNOPSIS" and other one or two word strings in all
331 # upper case are manual page section headings. The man(1) manual page in your
332 # language, if available should provide the conventional translations.
333 for ($replace{_('NAME')} || ($include{_('NAME')} ||= ''))
335 if ($_) # Use first name given as $program
337 $program = $1 if /^([^\s,]+)(?:,?\s*[^\s,\\-]+)*\s+\\?-/;
339 else # Set a default (useless) NAME paragraph.
341 $_ = sprintf _("%s \\- manual page for %s %s") . "\n", $program,
342 $program, $version;
346 # Man pages traditionally have the page title in caps.
347 my $PROGRAM = uc $program;
349 # Set default page head/footers.
350 $source ||= "$package $version";
351 unless ($manual)
353 for ($section)
355 if (/^(1[Mm]|8)/) { $manual = _('System Administration Utilities') }
356 elsif (/^6/) { $manual = _('Games') }
357 else { $manual = _('User Commands') }
361 # Extract usage clause(s) [if any] for SYNOPSIS.
362 # Translators: "Usage" and "or" here are patterns (regular expressions) which
363 # are used to match the usage synopsis in program output. An example from cp
364 # (GNU coreutils) which contains both strings:
365 # Usage: cp [OPTION]... [-T] SOURCE DEST
366 # or: cp [OPTION]... SOURCE... DIRECTORY
367 # or: cp [OPTION]... -t DIRECTORY SOURCE...
368 my $PAT_USAGE = _('Usage');
369 my $PAT_USAGE_CONT = _('or');
370 if ($help_text =~ s/^($PAT_USAGE):( +(\S+))(.*)((?:\n(?: {6}\1| *($PAT_USAGE_CONT): +\S).*)*)//om)
372 my @syn = $3 . $4;
374 if ($_ = $5)
376 s/^\n//;
377 for (split /\n/) { s/^ *(($PAT_USAGE_CONT): +)?//o; push @syn, $_ }
380 my $synopsis = '';
381 for (@syn)
383 $synopsis .= ".br\n" if $synopsis;
384 s!^\S*/!!;
385 s/^lt-// if $opt_libtool;
386 s/^(\S+) *//;
387 $synopsis .= ".B $1\n";
388 s/\s+$//;
389 s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
390 s/^/\\fI/ unless s/^\\fR//;
391 $_ .= '\fR';
392 s/(\\fI)( *)/$2$1/g;
393 s/\\fI\\fR//g;
394 s/^\\fR//;
395 s/\\fI$//;
396 s/^\./\\&./;
398 $_ = fix_italic_spacing $_;
399 $synopsis .= "$_\n";
402 $include{_('SYNOPSIS')} .= $synopsis;
405 # Process text, initial section is DESCRIPTION.
406 my $sect = _('DESCRIPTION');
407 $_ = "$help_text\n\n$version_text";
409 # Normalise paragraph breaks.
410 s/^\n+//;
411 s/\n*$/\n/;
412 s/\n\n+/\n\n/g;
414 # Join hyphenated lines.
415 s/([A-Za-z])-\n *([A-Za-z])/$1$2/g;
417 # Temporarily exchange leading dots, apostrophes and backslashes for
418 # tokens.
419 s/^\./\x80/mg;
420 s/^'/\x81/mg;
421 s/\\/\x82/g;
423 # Translators: patterns are used to match common program output. In the source
424 # these strings are all of the form of "my $PAT_something = _('...');" and are
425 # regular expressions. If there is more than one commonly used string, you
426 # may separate alternatives with "|". Spaces in these expressions are written
427 # as " +" to indicate that more than one space may be matched. The string
428 # "(?:[\\w-]+ +)?" in the bug reporting pattern is used to indicate an
429 # optional word, so that either "Report bugs" or "Report _program_ bugs" will
430 # be matched.
431 my $PAT_BUGS = _('Report +(?:[\w-]+ +)?bugs|' .
432 'Email +bug +reports +to|' .
433 '.* +online +help:');
434 my $PAT_AUTHOR = _('Written +by');
435 my $PAT_OPTIONS = _('Options');
436 my $PAT_ENVIRONMENT = _('Environment');
437 my $PAT_FILES = _('Files');
438 my $PAT_EXAMPLES = _('Examples');
439 my $PAT_FREE_SOFTWARE = _('This +is +free +software');
440 my $PAT_SEE_ALSO = _('Full +documentation');
442 # Start a new paragraph (if required) for these.
443 s/([^\n])\n($PAT_BUGS|$PAT_AUTHOR|$PAT_SEE_ALSO) /$1\n\n$2 /og;
445 # Convert iso-8859-1 copyright symbol or (c) to nroff
446 # character.
447 s/^Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/mg;
449 my $require_mono = 0;
450 while (length)
452 # Convert some standard paragraph names.
453 if (s/^($PAT_OPTIONS): *\n+//o)
455 $sect = _('OPTIONS');
456 next;
458 if (s/^($PAT_ENVIRONMENT): *\n+//o)
460 $sect = _('ENVIRONMENT');
461 next;
463 if (s/^($PAT_FILES): *\n+//o)
465 $sect = _('FILES');
466 next;
468 elsif (s/^($PAT_EXAMPLES): *\n+//o)
470 $sect = _('EXAMPLES');
471 next;
474 # Custom section indicated by a line containing "*Section Name*".
475 if (s/^\*(\w(.*\w)?)\* *\n+//)
477 $sect = uc $1;
478 $sect =~ tr/*/ /; # also accept *Section*Name*
479 push @sections, $sect;
480 next;
483 # Copyright section.
484 if (/^Copyright /)
486 $sect = _('COPYRIGHT');
489 # Bug reporting section.
490 elsif (/^($PAT_BUGS) /o)
492 $sect = _('REPORTING BUGS');
495 # Author section.
496 elsif (/^($PAT_AUTHOR)/o)
498 $sect = _('AUTHOR');
501 elsif (/^($PAT_SEE_ALSO)/o)
503 $sect = _('SEE ALSO');
504 $opt_no_info = 1;
507 # Examples, indicated by an indented leading $, % or > are
508 # rendered in a monospace font when using groff in troff mode.
509 if (/^( +)([\$\%>] )\S/)
511 my $spaces = $1;
512 my $prefix = $2;
513 my $break = '.IP';
514 while (s/^$spaces\Q$prefix\E(\S.*)\n*//)
516 $include{$sect} .= "$break\n\\*[mono]$prefix$1\\*[/mono]\n";
517 $require_mono++;
518 $break = '.br';
521 next;
524 my $matched = '';
526 # Sub-sections have a trailing colon and the second line indented.
527 if (s/^(\S.*:) *\n / /)
529 $matched .= $& if %append_match;
530 $include{$sect} .= qq(.SS "$1"\n);
533 my $indent = 0;
534 my $content = '';
536 # Option with description.
537 if (s/^( {1,10}([+-]\S.*?))(?:( +(?!-))|\n( {20,}))(\S.*)\n//)
539 $matched .= $& if %append_match;
540 $indent = set_indent length ($4 || "$1$3");
541 $content = ".TP\n\x84$2\n\x84$5\n";
542 unless ($4)
544 # Indent may be different on second line.
545 $indent = set_indent length $& if /^ {20,}/;
549 # Option without description.
550 elsif (s/^ {1,10}([+-]\S.*)\n//)
552 $matched .= $& if %append_match;
553 $content = ".HP\n\x84$1\n";
554 $indent = 80; # not continued
557 # Indented paragraph with tag.
558 elsif (s/^( +(\S.*?) +)(\S.*)\n//)
560 $matched .= $& if %append_match;
561 $indent = set_indent length $1;
562 $content = ".TP\n\x84$2\n\x84$3\n";
565 # Indented paragraph.
566 elsif (s/^( +)(\S.*)\n//)
568 $matched .= $& if %append_match;
569 $indent = set_indent length $1;
570 $content = ".IP\n\x84$2\n";
573 # Left justified paragraph.
574 else
576 s/(.*)\n//;
577 $matched .= $& if %append_match;
578 $content = ".PP\n" if $include{$sect};
579 $content .= "$1\n";
582 # Append continuations.
583 while ($indent ? s/^ {$indent}(\S.*)\n// : s/^(\S.*)\n//)
585 $matched .= $& if %append_match;
586 $content .= "\x84$1\n";
589 # Move to next paragraph.
590 s/^\n+//;
592 for ($content)
594 # Leading dot and apostrophe protection.
595 s/\x84\./\x80/g;
596 s/\x84'/\x81/g;
597 s/\x84//g;
599 # Examples should be verbatim.
600 unless ($sect eq _('EXAMPLES'))
602 # Convert options.
603 s/(^|[ (])(-[][\w=-]+)/$1 . convert_option $2/mge;
605 # Italicise filenames: /a/b, $VAR/c/d, ~/e/f
607 (^|[ (]) # space/punctuation before
609 (?:\$\w+|~)? # leading variable, or tilde
610 (?:/\w(?:[\w.-]*\w)?)+ # path components
612 ($|[ ,;.)]) # space/punctuation after
613 !$1\\fI$2\\fP$3!xmg;
615 $_ = fix_italic_spacing $_;
618 # Escape remaining hyphens.
619 s/-/\x83/g;
621 if ($sect eq _('COPYRIGHT'))
623 # Insert line breaks before additional copyright messages
624 # and the disclaimer.
625 s/\n(Copyright |$PAT_FREE_SOFTWARE)/\n.br\n$1/og;
627 elsif ($sect eq _('REPORTING BUGS'))
629 # Handle multi-line bug reporting sections of the form:
631 # Report <program> bugs to <addr>
632 # GNU <package> home page: <url>
633 # ...
634 s/\n([[:upper:]])/\n.br\n$1/g;
636 elsif ($sect eq _('SEE ALSO'))
638 # Handle external references of the form:
640 # GNU <package> online resources: <addr>
641 # Full documentation at: <addr>
642 # or available locally via: info ...
644 s/\'/\\(aq/g; # shell quotes for info command
645 s/\n(.)/\n.br\n$1/g; # separate lines for each item
649 # Check if matched paragraph contains /pat/.
650 if (%append_match)
652 for my $pat (keys %append_match)
654 if ($matched =~ $pat)
656 $content .= ".PP\n" unless $append_match{$pat} =~ /^\./;
657 $content .= $append_match{$pat};
662 $include{$sect} .= $content;
665 # Refer to the real documentation.
666 unless ($opt_no_info)
668 my $info_page = $opt_info || $program;
670 $sect = _('SEE ALSO');
671 $include{$sect} .= ".PP\n" if $include{$sect};
672 $include{$sect} .= sprintf _(<<'EOT'), $program, $program, $info_page;
673 The full documentation for
674 .B %s
675 is maintained as a Texinfo manual. If the
676 .B info
678 .B %s
679 programs are properly installed at your site, the command
681 .B info %s
683 should give you access to the complete manual.
687 # Append additional text.
688 while (my ($sect, $text) = each %append)
690 $require_mono++ if $text =~ /\\\*\[mono\]/;
691 $include{$sect} .= $text;
694 # Replace sections.
695 while (my ($sect, $text) = each %replace)
697 $include{$sect} = $replace{$sect};
700 # Output header.
701 print enc <<EOT;
702 .\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
703 .TH $PROGRAM "$section" "$date" "$source" "$manual"
706 # If monospace was used emit macros for groff.
707 print enc <<'EOT' if $require_mono;
708 .\" Define monospaced roman font for groff in troff mode.
709 .if t .if \n(.g \{\
710 . ds mono \f(CR
711 . ds /mono \fP
715 # Section ordering.
716 my @pre = (_('NAME'), _('SYNOPSIS'), _('DESCRIPTION'), _('OPTIONS'),
717 _('EXAMPLES'));
718 my @post = (_('ENVIRONMENT'), _('FILES'), _('AUTHOR'),
719 _('REPORTING BUGS'), _('COPYRIGHT'), _('SEE ALSO'));
720 my %filter = map { $_ => 1 } @pre, @post;
722 # Output content.
723 my %done;
724 for my $sect (@pre, (grep !$filter{$_}, @sections), @post)
726 next if $done{$sect}++; # ignore duplicates
727 next unless $include{$sect};
728 if ($include{$sect})
730 my $quote = $sect =~ /\W/ ? '"' : '';
731 print enc ".SH $quote$sect$quote\n";
733 for ($include{$sect})
735 # Add bold style around referenced pages.
736 if ($opt_bold_refs)
738 # This will ignore entries already marked up (with \)
739 s/(^|\s|,)([\[\w\x83]+)\(([1-9][[:lower:]]?)\)/$1\\fB$2\\fP($3)/g;
742 # Replace leading dot, apostrophe, backslash and hyphen
743 # tokens.
744 s/\x80/\\&./g;
745 s/\x81/\\&'/g;
746 s/\x82/\\e/g;
747 s/\x83/\\-/g;
749 # Convert some latin1 chars to troff equivalents.
750 s/\xa0/\\ /g; # non-breaking space
752 print enc $_;
757 close STDOUT or kark N_("%s: error writing to %s (%s)"), $this_program,
758 $opt_output || 'stdout', $!;
760 exit;
762 # Get program basename, and strip libtool "lt-" prefix if required.
763 sub program_basename
765 local $_ = shift;
766 s!.*/!!;
767 s/^lt-// if $opt_libtool;
771 # Call program with given option and return results.
772 sub get_option_value
774 my ($prog, $opt) = @_;
775 my $stderr = $discard_stderr ? '/dev/null' : '&1';
776 my $value = join '',
777 map { s/ +$//; expand $_ }
778 map { dec $_ }
779 `$prog $opt 2>$stderr`;
781 unless ($value)
783 my $err = N_("%s: can't get `%s' info from %s%s");
784 my $extra = $discard_stderr
785 ? "\n" . N_("Try `--no-discard-stderr' if option outputs to stderr")
786 : '';
788 kark $err, $this_program, $opt, $prog, $extra;
791 $value;
794 # Convert option dashes to \- to stop nroff from hyphenating 'em, and
795 # embolden. Option arguments get italicised.
796 sub convert_option
798 local $_ = '\fB' . shift;
800 s/-/\x83/g;
801 unless (s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
803 s/=(.)/\\fR=\\fI$1/;
804 s/ (.)/ \\fI$1/;
805 $_ .= '\fR';
811 # Insert spacing escape characters \, and \/ before and after italic text. See
812 # https://www.gnu.org/software/groff/manual/html_node/Ligatures-and-Kerning.html
813 sub fix_italic_spacing
815 local $_ = shift;
816 s!\\fI(.*?)\\f([BRP])!\\fI\\,$1\\/\\f$2!g;
817 return $_;
820 # Return indent to use: either the value passed in, or $v,$v+4 if
821 # loose index matching is used. The resulting string is used in a
822 # regex as " {$indent}", so will match either the exact number of
823 # spaces passed in, or up to four more. See the --loose-indent
824 # option.
825 sub set_indent
827 my $i = $_[0];
828 $i .= ',' . ($_[0] + 4) if $loose_indent;
829 return $i;