📄 man.pm
字号:
# format. Currently, the only formatting options are guesswork, cleanup, and# convert, all of which are boolean.sub format_text { my ($self, $options, $text) = @_; my $guesswork = $$options{guesswork} && !$$self{IN_NAME}; my $cleanup = $$options{cleanup}; my $convert = $$options{convert}; my $literal = $$options{literal}; # Normally we do character translation, but we won't even do that in # <Data> blocks. if ($convert) { if (ASCII) { $text =~ s/(\\|[^\x00-\x7F])/$ESCAPES{ord ($1)} || "X"/eg; } else { $text =~ s/(\\)/$ESCAPES{ord ($1)} || "X"/eg; } } # Cleanup just tidies up a few things, telling *roff that the hyphens are # hard and putting a bit of space between consecutive underscores. if ($cleanup) { $text =~ s/-/\\-/g; $text =~ s/_(?=_)/_\\|/g; } # Ensure that *roff doesn't convert literal quotes to UTF-8 single quotes, # but don't mess up our accept escapes. if ($literal) { $text =~ s/(?<!\\\*)\'/\\*\(Aq/g; $text =~ s/(?<!\\\*)\`/\\\`/g; } # If guesswork is asked for, do that. This involves more substantial # formatting based on various heuristics that may only be appropriate for # particular documents. if ($guesswork) { $text = $self->guesswork ($text); } return $text;}# Handles C<> text, deciding whether to put \*C` around it or not. This is a# whole bunch of messy heuristics to try to avoid overquoting, originally from# Barrie Slaymaker. This largely duplicates similar code in Pod::Text.sub quote_literal { my $self = shift; local $_ = shift; # A regex that matches the portion of a variable reference that's the # array or hash index, separated out just because we want to use it in # several places in the following regex. my $index = '(?: \[.*\] | \{.*\} )?'; # Check for things that we don't want to quote, and if we find any of # them, return the string with just a font change and no quoting. m{ ^\s* (?: ( [\'\`\"] ) .* \1 # already quoted | \\\*\(Aq .* \\\*\(Aq # quoted and escaped | \\?\` .* ( \' | \\\*\(Aq ) # `quoted' | \$+ [\#^]? \S $index # special ($^Foo, $") | [\$\@%&*]+ \#? [:\'\w]+ $index # plain var or func | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call | [-+]? ( \d[\d.]* | \.\d+ ) (?: [eE][-+]?\d+ )? # a number | 0x [a-fA-F\d]+ # a hex constant ) \s*\z }xso and return '\f(FS' . $_ . '\f(FE'; # If we didn't return, go ahead and quote the text. return '\f(FS\*(C`' . $_ . "\\*(C'\\f(FE";}# Takes a text block to perform guesswork on. Returns the text block with# formatting codes added. This is the code that marks up various Perl# constructs and things commonly used in man pages without requiring the user# to add any explicit markup, and is applied to all non-literal text. We're# guaranteed that the text we're applying guesswork to does not contain any# *roff formatting codes. Note that the inserted font sequences must be# treated later with mapfonts or textmapfonts.## This method is very fragile, both in the regular expressions it uses and in# the ordering of those modifications. Care and testing is required when# modifying it.sub guesswork { my $self = shift; local $_ = shift; DEBUG > 5 and print " Guesswork called on [$_]\n"; # By the time we reach this point, all hypens will be escaped by adding a # backslash. We want to undo that escaping if they're part of regular # words and there's only a single dash, since that's a real hyphen that # *roff gets to consider a possible break point. Make sure that a dash # after the first character of a word stays non-breaking, however. # # Note that this is not user-controllable; we pretty much have to do this # transformation or *roff will mangle the output in unacceptable ways. s{ ( (?:\G|^|\s) [\(\"]* [a-zA-Z] ) ( \\- )? ( (?: [a-zA-Z\']+ \\-)+ ) ( [a-zA-Z\']+ ) (?= [\)\".?!,;:]* (?:\s|\Z|\\\ ) ) \b } { my ($prefix, $hyphen, $main, $suffix) = ($1, $2, $3, $4); $hyphen ||= ''; $main =~ s/\\-/-/g; $prefix . $hyphen . $main . $suffix; }egx; # Translate "--" into a real em-dash if it's used like one. This means # that it's either surrounded by whitespace, it follows a regular word, or # it occurs between two regular words. if ($$self{MAGIC_EMDASH}) { s{ (\s) \\-\\- (\s) } { $1 . '\*(--' . $2 }egx; s{ (\b[a-zA-Z]+) \\-\\- (\s|\Z|[a-zA-Z]+\b) } { $1 . '\*(--' . $2 }egx; } # Make words in all-caps a little bit smaller; they look better that way. # However, we don't want to change Perl code (like @ARGV), nor do we want # to fix the MIME in MIME-Version since it looks weird with the # full-height V. # # We change only a string of all caps (2) either at the beginning of the # line or following regular punctuation (like quotes) or whitespace (1), # and followed by either similar punctuation, an em-dash, or the end of # the line (3). if ($$self{MAGIC_SMALLCAPS}) { s{ ( ^ | [\s\(\"\'\`\[\{<>] | \\\ ) # (1) ( [A-Z] [A-Z] (?: [/A-Z+:\d_\$&] | \\- )* ) # (2) (?= [\s>\}\]\(\)\'\".?!,;] | \\*\(-- | \\\ | $ ) # (3) } { $1 . '\s-1' . $2 . '\s0' }egx; } # Note that from this point forward, we have to adjust for \s-1 and \s-0 # strings inserted around things that we've made small-caps if later # transforms should work on those strings. # Italize functions in the form func(), including functions that are in # all capitals, but don't italize if there's anything between the parens. # The function must start with an alphabetic character or underscore and # then consist of word characters or colons. if ($$self{MAGIC_FUNC}) { s{ ( \b | \\s-1 ) ( [A-Za-z_] ([:\w] | \\s-?[01])+ \(\) ) } { $1 . '\f(IS' . $2 . '\f(IE' }egx; } # Change references to manual pages to put the page name in italics but # the number in the regular font, with a thin space between the name and # the number. Only recognize func(n) where func starts with an alphabetic # character or underscore and contains only word characters, periods (for # configuration file man pages), or colons, and n is a single digit, # optionally followed by some number of lowercase letters. Note that this # does not recognize man page references like perl(l) or socket(3SOCKET). if ($$self{MAGIC_MANREF}) { s{ ( \b | \\s-1 ) ( [A-Za-z_] (?:[.:\w] | \\- | \\s-?[01])+ ) ( \( \d [a-z]* \) ) } { $1 . '\f(IS' . $2 . '\f(IE\|' . $3 }egx; } # Convert simple Perl variable references to a fixed-width font. Be # careful not to convert functions, though; there are too many subtleties # with them to want to perform this transformation. if ($$self{MAGIC_VARS}) { s{ ( ^ | \s+ ) ( [\$\@%] [\w:]+ ) (?! \( ) } { $1 . '\f(FS' . $2 . '\f(FE' }egx; } # Fix up double quotes. Unfortunately, we miss this transformation if the # quoted text contains any code with formatting codes and there's not much # we can effectively do about that, which makes it somewhat unclear if # this is really a good idea. s{ \" ([^\"]+) \" } { '\*(L"' . $1 . '\*(R"' }egx; # Make C++ into \*(C+, which is a squinched version. if ($$self{MAGIC_CPP}) { s{ \b C\+\+ } {\\*\(C+}gx; } # Done. DEBUG > 5 and print " Guesswork returning [$_]\n"; return $_;}############################################################################### Output############################################################################### When building up the *roff code, we don't use real *roff fonts. Instead, we# embed font codes of the form \f(<font>[SE] where <font> is one of B, I, or# F, S stands for start, and E stands for end. This method turns these into# the right start and end codes.## We add this level of complexity because the old pod2man didn't get code like# B<someI<thing> else> right; after I<> it switched back to normal text rather# than bold. We take care of this by using variables that state whether bold,# italic, or fixed are turned on as a combined pointer to our current font# sequence, and set each to the number of current nestings of start tags for# that font.## \fP changes to the previous font, but only one previous font is kept. We# don't know what the outside level font is; normally it's R, but if we're# inside a heading it could be something else. So arrange things so that the# outside font is always the "previous" font and end with \fP instead of \fR.# Idea from Zack Weinberg.sub mapfonts { my ($self, $text) = @_; my ($fixed, $bold, $italic) = (0, 0, 0); my %magic = (F => \$fixed, B => \$bold, I => \$italic); my $last = '\fR'; $text =~ s< \\f\((.)(.) > < my $sequence = ''; my $f; if ($last ne '\fR') { $sequence = '\fP' } ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; $f = $$self{FONTS}{ ($fixed && 1) . ($bold && 1) . ($italic && 1) }; if ($f eq $last) { ''; } else { if ($f ne '\fR') { $sequence .= $f } $last = $f; $sequence; } >gxe; return $text;}# Unfortunately, there is a bug in Solaris 2.6 nroff (not present in GNU# groff) where the sequence \fB\fP\f(CW\fP leaves the font set to B rather# than R, presumably because \f(CW doesn't actually do a font change. To work# around this, use a separate textmapfonts for text blocks where the default# font is always R and only use the smart mapfonts for headings.sub textmapfonts { my ($self, $text) = @_; my ($fixed, $bold, $italic) = (0, 0, 0); my %magic = (F => \$fixed, B => \$bold, I => \$italic); $text =~ s< \\f\((.)(.) > < ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1; $$self{FONTS}{ ($fixed && 1) . ($bold && 1) . ($italic && 1) }; >gxe; return $text;}# Given a command and a single argument that may or may not contain double# quotes, handle double-quote formatting for it. If there are no double# quotes, just return the command followed by the argument in double quotes.# If there are double quotes, use an if statement to test for nroff, and for# nroff output the command followed by the argument in double quotes with# embedded double quotes doubled. For other formatters, remap paired double# quotes to LQUOTE and RQUOTE.sub switchquotes { my ($self, $command, $text, $extra) = @_; $text =~ s/\\\*\([LR]\"/\"/g; # We also have to deal with \*C` and \*C', which are used to add the # quotes around C<> text, since they may expand to " and if they do this # confuses the .SH macros and the like no end. Expand them ourselves. # Also separate troff from nroff if there are any fixed-width fonts in use # to work around problems with Solaris nroff. my $c_is_quote = ($$self{LQUOTE} =~ /\"/) || ($$self{RQUOTE} =~ /\"/); my $fixedpat = join '|', @{ $$self{FONTS} }{'100', '101', '110', '111'}; $fixedpat =~ s/\\/\\\\/g; $fixedpat =~ s/\(/\\\(/g; if ($text =~ m/\"/ || $text =~ m/$fixedpat/) { $text =~ s/\"/\"\"/g; my $nroff = $text; my $troff = $text; $troff =~ s/\"\"([^\"]*)\"\"/\`\`$1\'\'/g; if ($c_is_quote and $text =~ m/\\\*\(C[\'\`]/) { $nroff =~ s/\\\*\(C\`/$$self{LQUOTE}/g; $nroff =~ s/\\\*\(C\'/$$self{RQUOTE}/g; $troff =~ s/\\\*\(C[\'\`]//g; } $nroff = qq("$nroff") . ($extra ? " $extra" : ''); $troff = qq("$troff") . ($extra ? " $extra" : ''); # Work around the Solaris nroff bug where \f(CW\fP leaves the font set # to Roman rather than the actual previous font when used in headings. # troff output may still be broken, but at least we can fix nroff by # just switching the font changes to the non-fixed versions. $nroff =~ s/\Q$$self{FONTS}{100}\E(.*)\\f[PR]/$1/g; $nroff =~ s/\Q$$self{FONTS}{101}\E(.*)\\f([PR])/\\fI$1\\f$2/g; $nroff =~ s/\Q$$self{FONTS}{110}\E(.*)\\f([PR])/\\fB$1\\f$2/g; $nroff =~ s/\Q$$self{FONTS}{111}\E(.*)\\f([PR])/\\f\(BI$1\\f$2/g; # Now finally output the command. Bother with .ie only if the nroff # and troff output aren't the same. if ($nroff ne $troff) { return ".ie n $command $nroff\n.el $command $troff\n"; } else { return "$command $nroff\n"; } } else { $text = qq("$text") . ($extra ? " $extra" : ''); return "$command $text\n"; }}# Protect leading quotes and periods against interpretation as commands. Also# protect anything starting with a backslash, since it could expand or hide# something that *roff would interpret as a command. This is overkill, but# it's much simpler than trying to parse *roff here.sub protect { my ($self, $text) = @_; $text =~ s/^([.\'\\])/\\&$1/mg; return $text;}# Make vertical whitespace if NEEDSPACE is set, appropriate to the indentation# level the situation. This function is needed since in *roff one has to# create vertical whitespace after paragraphs and between some things, but# other macros create their own whitespace. Also close out a sequence of# repeated =items, since calling makespace means we're about to begin the item# body.sub makespace { my ($self) = @_; $self->output (".PD\n") if $$self{ITEMS} > 1; $$self{ITEMS} = 0; $self->output ($$self{INDENT} > 0 ? ".Sp\n" : ".PP\n")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -