📄 man.pm
字号:
# Second level heading.sub cmd_head2 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); $self->output ($self->switchquotes ('.Sh', $self->mapfonts ($text))); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 0; return '';}# Third level heading. *roff doesn't have this concept, so just put the# heading in italics as a normal paragraph.sub cmd_head3 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); $self->makespace; $self->output ($self->textmapfonts ('\f(IS' . $text . '\f(IE') . "\n"); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 1; return '';}# Fourth level heading. *roff doesn't have this concept, so just put the# heading as a normal paragraph.sub cmd_head4 { my ($self, $attrs, $text) = @_; $text = $self->heading_common ($text, $$attrs{start_line}); $self->makespace; $self->output ($self->textmapfonts ($text) . "\n"); $self->outindex ('Subsection', $text); $$self{NEEDSPACE} = 1; return '';}############################################################################### Formatting codes############################################################################### All of the formatting codes that aren't handled internally by the parser,# other than L<> and X<>.sub cmd_b { return '\f(BS' . $_[2] . '\f(BE' }sub cmd_i { return '\f(IS' . $_[2] . '\f(IE' }sub cmd_f { return '\f(IS' . $_[2] . '\f(IE' }sub cmd_c { return $_[0]->quote_literal ($_[2]) }# Index entries are just added to the pending entries.sub cmd_x { my ($self, $attrs, $text) = @_; push (@{ $$self{INDEX} }, $text); return '';}# Links reduce to the text that we're given, wrapped in angle brackets if it's# a URL.sub cmd_l { my ($self, $attrs, $text) = @_; return $$attrs{type} eq 'url' ? "<$text>" : $text;}############################################################################### List handling############################################################################### Handle the beginning of an =over block. Takes the type of the block as the# first argument, and then the attr hash. This is called by the handlers for# the four different types of lists (bullet, number, text, and block).sub over_common_start { my ($self, $type, $attrs) = @_; my $line = $$attrs{start_line}; my $indent = $$attrs{indent}; DEBUG > 3 and print " Starting =over $type (line $line, indent ", ($indent || '?'), "\n"; # Find the indentation level. unless (defined ($indent) && $indent =~ /^[-+]?\d{1,4}\s*$/) { $indent = $$self{indent}; } # If we've gotten multiple indentations in a row, we need to emit the # pending indentation for the last level that we saw and haven't acted on # yet. SHIFTS is the stack of indentations that we've actually emitted # code for. if (@{ $$self{SHIFTS} } < @{ $$self{INDENTS} }) { $self->output (".RS $$self{INDENT}\n"); push (@{ $$self{SHIFTS} }, $$self{INDENT}); } # Now, do record-keeping. INDENTS is a stack of indentations that we've # seen so far, and INDENT is the current level of indentation. ITEMTYPES # is a stack of list types that we've seen. push (@{ $$self{INDENTS} }, $$self{INDENT}); push (@{ $$self{ITEMTYPES} }, $type); $$self{INDENT} = $indent + 0; $$self{SHIFTWAIT} = 1;}# End an =over block. Takes no options other than the class pointer.# Normally, once we close a block and therefore remove something from INDENTS,# INDENTS will now be longer than SHIFTS, indicating that we also need to emit# *roff code to close the indent. This isn't *always* true, depending on the# circumstance. If we're still inside an indentation, we need to emit another# .RE and then a new .RS to unconfuse *roff.sub over_common_end { my ($self) = @_; DEBUG > 3 and print " Ending =over\n"; $$self{INDENT} = pop @{ $$self{INDENTS} }; pop @{ $$self{ITEMTYPES} }; # If we emitted code for that indentation, end it. if (@{ $$self{SHIFTS} } > @{ $$self{INDENTS} }) { $self->output (".RE\n"); pop @{ $$self{SHIFTS} }; } # If we're still in an indentation, *roff will have now lost track of the # right depth of that indentation, so fix that. if (@{ $$self{INDENTS} } > 0) { $self->output (".RE\n"); $self->output (".RS $$self{INDENT}\n"); } $$self{NEEDSPACE} = 1; $$self{SHIFTWAIT} = 0;}# Dispatch the start and end calls as appropriate.sub start_over_bullet { my $s = shift; $s->over_common_start ('bullet', @_) }sub start_over_number { my $s = shift; $s->over_common_start ('number', @_) }sub start_over_text { my $s = shift; $s->over_common_start ('text', @_) }sub start_over_block { my $s = shift; $s->over_common_start ('block', @_) }sub end_over_bullet { $_[0]->over_common_end }sub end_over_number { $_[0]->over_common_end }sub end_over_text { $_[0]->over_common_end }sub end_over_block { $_[0]->over_common_end }# The common handler for all item commands. Takes the type of the item, the# attributes, and then the text of the item.## Emit an index entry for anything that's interesting, but don't emit index# entries for things like bullets and numbers. Newlines in an item title are# turned into spaces since *roff can't handle them embedded.sub item_common { my ($self, $type, $attrs, $text) = @_; my $line = $$attrs{start_line}; DEBUG > 3 and print " $type item (line $line): $text\n"; # Clean up the text. We want to end up with two variables, one ($text) # which contains any body text after taking out the item portion, and # another ($item) which contains the actual item text. $text =~ s/\s+$//; my ($item, $index); if ($type eq 'bullet') { $item = "\\\(bu"; $text =~ s/\n*$/\n/; } elsif ($type eq 'number') { $item = $$attrs{number} . '.'; } else { $item = $text; $item =~ s/\s*\n\s*/ /g; $text = ''; $index = $item if ($item =~ /\w/); } # Take care of the indentation. If shifts and indents are equal, close # the top shift, since we're about to create an indentation with .IP. # Also output .PD 0 to turn off spacing between items if this item is # directly following another one. We only have to do that once for a # whole chain of items so do it for the second item in the change. Note # that makespace is what undoes this. if (@{ $$self{SHIFTS} } == @{ $$self{INDENTS} }) { $self->output (".RE\n"); pop @{ $$self{SHIFTS} }; } $self->output (".PD 0\n") if ($$self{ITEMS} == 1); # Now, output the item tag itself. $item = $self->textmapfonts ($item); $self->output ($self->switchquotes ('.IP', $item, $$self{INDENT})); $$self{NEEDSPACE} = 0; $$self{ITEMS}++; $$self{SHIFTWAIT} = 0; # If body text for this item was included, go ahead and output that now. if ($text) { $text =~ s/\s*$/\n/; $self->makespace; $self->output ($self->protect ($self->textmapfonts ($text))); $$self{NEEDSPACE} = 1; } $self->outindex ($index ? ('Item', $index) : ());}# Dispatch the item commands to the appropriate place.sub cmd_item_bullet { my $self = shift; $self->item_common ('bullet', @_) }sub cmd_item_number { my $self = shift; $self->item_common ('number', @_) }sub cmd_item_text { my $self = shift; $self->item_common ('text', @_) }sub cmd_item_block { my $self = shift; $self->item_common ('block', @_) }############################################################################### Backward compatibility############################################################################### Reset the underlying Pod::Simple object between calls to parse_from_file so# that the same object can be reused to convert multiple pages.sub parse_from_file { my $self = shift; $self->reinit; # Fake the old cutting option to Pod::Parser. This fiddings with internal # Pod::Simple state and is quite ugly; we need a better approach. if (ref ($_[0]) eq 'HASH') { my $opts = shift @_; if (defined ($$opts{-cutting}) && !$$opts{-cutting}) { $$self{in_pod} = 1; $$self{last_was_blank} = 1; } } # Do the work. my $retval = $self->SUPER::parse_from_file (@_); # Flush output, since Pod::Simple doesn't do this. Ideally we should also # close the file descriptor if we had to open one, but we can't easily # figure this out. my $fh = $self->output_fh (); my $oldfh = select $fh; my $oldflush = $|; $| = 1; print $fh ''; $| = $oldflush; select $oldfh; return $retval;}# Pod::Simple failed to provide this backward compatibility function, so# implement it ourselves. File handles are one of the inputs that# parse_from_file supports.sub parse_from_filehandle { my $self = shift; $self->parse_from_file (@_);}############################################################################### Translation tables############################################################################### The following table is adapted from Tom Christiansen's pod2man. It assumes# that the standard preamble has already been printed, since that's what# defines all of the accent marks. We really want to do something better than# this when *roff actually supports other character sets itself, since these# results are pretty poor.## This only works in an ASCII world. What to do in a non-ASCII world is very# unclear.@ESCAPES{0xA0 .. 0xFF} = ( "\\ ", undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, "\\%", undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, "A\\*`", "A\\*'", "A\\*^", "A\\*~", "A\\*:", "A\\*o", "\\*(AE", "C\\*,", "E\\*`", "E\\*'", "E\\*^", "E\\*:", "I\\*`", "I\\*'", "I\\*^", "I\\*:", "\\*(D-", "N\\*~", "O\\*`", "O\\*'", "O\\*^", "O\\*~", "O\\*:", undef, "O\\*/", "U\\*`", "U\\*'", "U\\*^", "U\\*:", "Y\\*'", "\\*(Th", "\\*8", "a\\*`", "a\\*'", "a\\*^", "a\\*~", "a\\*:", "a\\*o", "\\*(ae", "c\\*,", "e\\*`", "e\\*'", "e\\*^", "e\\*:", "i\\*`", "i\\*'", "i\\*^", "i\\*:", "\\*(d-", "n\\*~", "o\\*`", "o\\*'", "o\\*^", "o\\*~", "o\\*:", undef, "o\\*/" , "u\\*`", "u\\*'", "u\\*^", "u\\*:", "y\\*'", "\\*(th", "y\\*:",) if ASCII;# Make sure that at least this works even outside of ASCII.$ESCAPES{ord("\\")} = "\\e";############################################################################### Premable############################################################################### The following is the static preamble which starts all *roff output we# generate. It's completely static except for the font to use as a# fixed-width font, which is designed by @CFONT@, and the left and right# quotes to use for C<> text, designated by @LQOUTE@ and @RQUOTE@.sub preamble_template { return <<'----END OF PREAMBLE----';.de Sh \" Subsection heading.br.if t .Sp.ne 5.PP\fB\\$1\fR.PP...de Sp \" Vertical space (when we can't use .PP).if t .sp .5v.if n .sp...de Vb \" Begin verbatim text.ft @CFONT@.nf.ne \\$1...de Ve \" End verbatim text.ft R.fi...\" Set up some character translations and predefined strings. \*(-- will.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left.\" double quote, and \*(R" will give a right double quote. \*(C+ will.\" give a nicer C++. Capital omega is used to do unbreakable dashes and.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,.\" nothing in troff, for use with C<>..tr \(*W-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'.ie n \{\. ds -- \(*W-. ds PI pi. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch. ds L" "". ds R" "". ds C` @LQUOTE@. ds C' @RQUOTE@'br\}.el\{\. ds -- \|\(em\|. ds PI \(*p. ds L" ``. ds R" '''br\}.\".\" Escape single quotes in literal strings from groff's Unicode transform..ie \n(.g .ds Aq \(aq.el .ds Aq '.\".\" If the F register is turned on, we'll generate index entries on stderr for.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index.\" entries marked with X<> in POD. Of course, you'll have to process the.\" output yourself in some meaningful fashion..ie \nF \{\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -