📄 man.pm
字号:
if $$self{NEEDSPACE};}# Output any pending index entries, and optionally an index entry given as an# argument. Support multiple index entries in X<> separated by slashes, and# strip special escapes from index entries.sub outindex { my ($self, $section, $index) = @_; my @entries = map { split m%\s*/\s*% } @{ $$self{INDEX} }; return unless ($section || @entries); # We're about to output all pending entries, so clear our pending queue. $$self{INDEX} = []; # Build the output. Regular index entries are marked Xref, and headings # pass in their own section. Undo some *roff formatting on headings. my @output; if (@entries) { push @output, [ 'Xref', join (' ', @entries) ]; } if ($section) { $index =~ s/\\-/-/g; $index =~ s/\\(?:s-?\d|.\(..|.)//g; push @output, [ $section, $index ]; } # Print out the .IX commands. for (@output) { my ($type, $entry) = @$_; $entry =~ s/\"/\"\"/g; $self->output (".IX $type " . '"' . $entry . '"' . "\n"); }}# Output some text, without any additional changes.sub output { my ($self, @text) = @_; print { $$self{output_fh} } @text;}############################################################################### Document initialization############################################################################### Handle the start of the document. Here we handle empty documents, as well# as setting up our basic macros in a preamble and building the page title.sub start_document { my ($self, $attrs) = @_; if ($$attrs{contentless} && !$$self{ALWAYS_EMIT_SOMETHING}) { DEBUG and print "Document is contentless\n"; $$self{CONTENTLESS} = 1; return; } # Determine information for the preamble and then output it. my ($name, $section); if (defined $$self{name}) { $name = $$self{name}; $section = $$self{section} || 1; } else { ($name, $section) = $self->devise_title; } my $date = $$self{date} || $self->devise_date; $self->preamble ($name, $section, $date) unless $self->bare_output or DEBUG > 9; # Initialize a few per-document variables. $$self{INDENT} = 0; # Current indentation level. $$self{INDENTS} = []; # Stack of indentations. $$self{INDEX} = []; # Index keys waiting to be printed. $$self{IN_NAME} = 0; # Whether processing the NAME section. $$self{ITEMS} = 0; # The number of consecutive =items. $$self{ITEMTYPES} = []; # Stack of =item types, one per list. $$self{SHIFTWAIT} = 0; # Whether there is a shift waiting. $$self{SHIFTS} = []; # Stack of .RS shifts. $$self{PENDING} = [[]]; # Pending output.}# Handle the end of the document. This does nothing but print out a final# comment at the end of the document under debugging.sub end_document { my ($self) = @_; return if $self->bare_output; return if ($$self{CONTENTLESS} && !$$self{ALWAYS_EMIT_SOMETHING}); $self->output (q(.\" [End document]) . "\n") if DEBUG;}# Try to figure out the name and section from the file name and return them as# a list, returning an empty name and section 1 if we can't find any better# information. Uses File::Basename and File::Spec as necessary.sub devise_title { my ($self) = @_; my $name = $self->source_filename || ''; my $section = $$self{section} || 1; $section = 3 if (!$$self{section} && $name =~ /\.pm\z/i); $name =~ s/\.p(od|[lm])\z//i; # If the section isn't 3, then the name defaults to just the basename of # the file. Otherwise, assume we're dealing with a module. We want to # figure out the full module name from the path to the file, but we don't # want to include too much of the path into the module name. Lose # anything up to the first off: # # */lib/*perl*/ standard or site_perl module # */*perl*/lib/ from -Dprefix=/opt/perl # */*perl*/ random module hierarchy # # which works. Also strip off a leading site, site_perl, or vendor_perl # component, any OS-specific component, and any version number component, # and strip off an initial component of "lib" or "blib/lib" since that's # what ExtUtils::MakeMaker creates. splitdir requires at least File::Spec # 0.8. if ($section !~ /^3/) { require File::Basename; $name = uc File::Basename::basename ($name); } else { require File::Spec; my ($volume, $dirs, $file) = File::Spec->splitpath ($name); my @dirs = File::Spec->splitdir ($dirs); my $cut = 0; my $i; for ($i = 0; $i < @dirs; $i++) { if ($dirs[$i] =~ /perl/) { $cut = $i + 1; $cut++ if ($dirs[$i + 1] && $dirs[$i + 1] eq 'lib'); last; } } if ($cut > 0) { splice (@dirs, 0, $cut); shift @dirs if ($dirs[0] =~ /^(site|vendor)(_perl)?$/); shift @dirs if ($dirs[0] =~ /^[\d.]+$/); shift @dirs if ($dirs[0] =~ /^(.*-$^O|$^O-.*|$^O)$/); } shift @dirs if $dirs[0] eq 'lib'; splice (@dirs, 0, 2) if ($dirs[0] eq 'blib' && $dirs[1] eq 'lib'); # Remove empty directories when building the module name; they # occur too easily on Unix by doubling slashes. $name = join ('::', (grep { $_ ? $_ : () } @dirs), $file); } return ($name, $section);}# Determine the modification date and return that, properly formatted in ISO# format. If we can't get the modification date of the input, instead use the# current time. Pod::Simple returns a completely unuseful stringified file# handle as the source_filename for input from a file handle, so we have to# deal with that as well.sub devise_date { my ($self) = @_; my $input = $self->source_filename; my $time; if ($input) { $time = (stat $input)[9] || time; } else { $time = time; } return strftime ('%Y-%m-%d', localtime $time);}# Print out the preamble and the title. The meaning of the arguments to .TH# unfortunately vary by system; some systems consider the fourth argument to# be a "source" and others use it as a version number. Generally it's just# presented as the left-side footer, though, so it doesn't matter too much if# a particular system gives it another interpretation.## The order of date and release used to be reversed in older versions of this# module, but this order is correct for both Solaris and Linux.sub preamble { my ($self, $name, $section, $date) = @_; my $preamble = $self->preamble_template; # Build the index line and make sure that it will be syntactically valid. my $index = "$name $section"; $index =~ s/\"/\"\"/g; # If name or section contain spaces, quote them (section really never # should, but we may as well be cautious). for ($name, $section) { if (/\s/) { s/\"/\"\"/g; $_ = '"' . $_ . '"'; } } # Double quotes in date, since it will be quoted. $date =~ s/\"/\"\"/g; # Substitute into the preamble the configuration options. $preamble =~ s/\@CFONT\@/$$self{fixed}/; $preamble =~ s/\@LQUOTE\@/$$self{LQUOTE}/; $preamble =~ s/\@RQUOTE\@/$$self{RQUOTE}/; chomp $preamble; # Get the version information. my $version = $self->version_report; # Finally output everything. $self->output (<<"----END OF HEADER----");.\\" Automatically generated by $version.\\".\\" Standard preamble:.\\" ========================================================================$preamble.\\" ========================================================================.\\".IX Title "$index".TH $name $section "$date" "$$self{release}" "$$self{center}".\\" For nroff, turn off justification. Always turn off hyphenation; it makes.\\" way too many mistakes in technical documents..if n .ad l.nh----END OF HEADER---- $self->output (".\\\" [End of preamble]\n") if DEBUG;}############################################################################### Text blocks############################################################################### Handle a basic block of text. The only tricky part of this is if this is# the first paragraph of text after an =over, in which case we have to change# indentations for *roff.sub cmd_para { my ($self, $attrs, $text) = @_; my $line = $$attrs{start_line}; # Output the paragraph. We also have to handle =over without =item. If # there's an =over without =item, SHIFTWAIT will be set, and we need to # handle creation of the indent here. Add the shift to SHIFTS so that it # will be cleaned up on =back. $self->makespace; if ($$self{SHIFTWAIT}) { $self->output (".RS $$self{INDENT}\n"); push (@{ $$self{SHIFTS} }, $$self{INDENT}); $$self{SHIFTWAIT} = 0; } # Add the line number for debugging, but not in the NAME section just in # case the comment would confuse apropos. $self->output (".\\\" [At source line $line]\n") if defined ($line) && DEBUG && !$$self{IN_NAME}; # Force exactly one newline at the end and strip unwanted trailing # whitespace at the end. $text =~ s/\s*$/\n/; # Output the paragraph. $self->output ($self->protect ($self->textmapfonts ($text))); $self->outindex; $$self{NEEDSPACE} = 1; return '';}# Handle a verbatim paragraph. Put a null token at the beginning of each line# to protect against commands and wrap in .Vb/.Ve (which we define in our# prelude).sub cmd_verbatim { my ($self, $attrs, $text) = @_; # Ignore an empty verbatim paragraph. return unless $text =~ /\S/; # Force exactly one newline at the end and strip unwanted trailing # whitespace at the end. $text =~ s/\s*$/\n/; # Get a count of the number of lines before the first blank line, which # we'll pass to .Vb as its parameter. This tells *roff to keep that many # lines together. We don't want to tell *roff to keep huge blocks # together. my @lines = split (/\n/, $text); my $unbroken = 0; for (@lines) { last if /^\s*$/; $unbroken++; } $unbroken = 10 if ($unbroken > 12 && !$$self{MAGIC_VNOPAGEBREAK_LIMIT}); # Prepend a null token to each line. $text =~ s/^/\\&/gm; # Output the results. $self->makespace; $self->output (".Vb $unbroken\n$text.Ve\n"); $$self{NEEDSPACE} = 1; return '';}# Handle literal text (produced by =for and similar constructs). Just output# it with the minimum of changes.sub cmd_data { my ($self, $attrs, $text) = @_; $text =~ s/^\n+//; $text =~ s/\n{0,2}$/\n/; $self->output ($text); return '';}############################################################################### Headings############################################################################### Common code for all headings. This is called before the actual heading is# output. It returns the cleaned up heading text (putting the heading all on# one line) and may do other things, like closing bad =item blocks.sub heading_common { my ($self, $text, $line) = @_; $text =~ s/\s+$//; $text =~ s/\s*\n\s*/ /g; # This should never happen; it means that we have a heading after =item # without an intervening =back. But just in case, handle it anyway. if ($$self{ITEMS} > 1) { $$self{ITEMS} = 0; $self->output (".PD\n"); } # Output the current source line. $self->output ( ".\\\" [At source line $line]\n" ) if defined ($line) && DEBUG; return $text;}# First level heading. We can't output .IX in the NAME section due to a bug# in some versions of catman, so don't output a .IX for that section. .SH# already uses small caps, so remove \s0 and \s-1. Maintain IN_NAME as# appropriate.sub cmd_head1 { my ($self, $attrs, $text) = @_; $text =~ s/\\s-?\d//g; $text = $self->heading_common ($text, $$attrs{start_line}); my $isname = ($text eq 'NAME' || $text =~ /\(NAME\)/); $self->output ($self->switchquotes ('.SH', $self->mapfonts ($text))); $self->outindex ('Header', $text) unless $isname; $$self{NEEDSPACE} = 0; $$self{IN_NAME} = $isname; return '';}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -