📄 man.pm
字号:
# Pod::Man -- Convert POD data to formatted *roff input.# $Id: Man.pm,v 2.16 2007-11-29 01:35:53 eagle Exp $## Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007# Russ Allbery <rra@stanford.edu># Substantial contributions by Sean Burke <sburke@cpan.org>## This program is free software; you may redistribute it and/or modify it# under the same terms as Perl itself.## This module translates POD documentation into *roff markup using the man# macro set, and is intended for converting POD documents written as Unix# manual pages to manual pages that can be read by the man(1) command. It is# a replacement for the pod2man command distributed with versions of Perl# prior to 5.6.## Perl core hackers, please note that this module is also separately# maintained outside of the Perl core as part of the podlators. Please send# me any patches at the address above in addition to sending them to the# standard Perl mailing lists.############################################################################### Modules and declarations##############################################################################package Pod::Man;require 5.005;use strict;use subs qw(makespace);use vars qw(@ISA %ESCAPES $PREAMBLE $VERSION);use Carp qw(croak);use Pod::Simple ();use POSIX qw(strftime);@ISA = qw(Pod::Simple);# Don't use the CVS revision as the version, since this module is also in Perl# core and too many things could munge CVS magic revision strings. This# number should ideally be the same as the CVS revision in podlators, however.$VERSION = '2.16';# Set the debugging level. If someone has inserted a debug function into this# class already, use that. Otherwise, use any Pod::Simple debug function# that's defined, and failing that, define a debug level of 10.BEGIN { my $parent = defined (&Pod::Simple::DEBUG) ? \&Pod::Simple::DEBUG : undef; unless (defined &DEBUG) { *DEBUG = $parent || sub () { 10 }; }}# Import the ASCII constant from Pod::Simple. This is true iff we're in an# ASCII-based universe (including such things as ISO 8859-1 and UTF-8), and is# generally only false for EBCDIC.BEGIN { *ASCII = \&Pod::Simple::ASCII }# Pretty-print a data structure. Only used for debugging.BEGIN { *pretty = \&Pod::Simple::pretty }############################################################################### Object initialization############################################################################### Initialize the object and set various Pod::Simple options that we need.# Here, we also process any additional options passed to the constructor or# set up defaults if none were given. Note that all internal object keys are# in all-caps, reserving all lower-case object keys for Pod::Simple and user# arguments.sub new { my $class = shift; my $self = $class->SUPER::new; # Tell Pod::Simple to handle S<> by automatically inserting . $self->nbsp_for_S (1); # Tell Pod::Simple to keep whitespace whenever possible. if ($self->can ('preserve_whitespace')) { $self->preserve_whitespace (1); } else { $self->fullstop_space_harden (1); } # The =for and =begin targets that we accept. $self->accept_targets (qw/man MAN roff ROFF/); # Ensure that contiguous blocks of code are merged together. Otherwise, # some of the guesswork heuristics don't work right. $self->merge_text (1); # Pod::Simple doesn't do anything useful with our arguments, but we want # to put them in our object as hash keys and values. This could cause # problems if we ever clash with Pod::Simple's own internal class # variables. %$self = (%$self, @_); # Initialize various other internal constants based on our arguments. $self->init_fonts; $self->init_quotes; $self->init_page; # For right now, default to turning on all of the magic. $$self{MAGIC_CPP} = 1; $$self{MAGIC_EMDASH} = 1; $$self{MAGIC_FUNC} = 1; $$self{MAGIC_MANREF} = 1; $$self{MAGIC_SMALLCAPS} = 1; $$self{MAGIC_VARS} = 1; return $self;}# Translate a font string into an escape.sub toescape { (length ($_[0]) > 1 ? '\f(' : '\f') . $_[0] }# Determine which fonts the user wishes to use and store them in the object.# Regular, italic, bold, and bold-italic are constants, but the fixed width# fonts may be set by the user. Sets the internal hash key FONTS which is# used to map our internal font escapes to actual *roff sequences later.sub init_fonts { my ($self) = @_; # Figure out the fixed-width font. If user-supplied, make sure that they # are the right length. for (qw/fixed fixedbold fixeditalic fixedbolditalic/) { my $font = $$self{$_}; if (defined ($font) && (length ($font) < 1 || length ($font) > 2)) { croak qq(roff font should be 1 or 2 chars, not "$font"); } } # Set the default fonts. We can't be sure portably across different # implementations what fixed bold-italic may be called (if it's even # available), so default to just bold. $$self{fixed} ||= 'CW'; $$self{fixedbold} ||= 'CB'; $$self{fixeditalic} ||= 'CI'; $$self{fixedbolditalic} ||= 'CB'; # Set up a table of font escapes. First number is fixed-width, second is # bold, third is italic. $$self{FONTS} = { '000' => '\fR', '001' => '\fI', '010' => '\fB', '011' => '\f(BI', '100' => toescape ($$self{fixed}), '101' => toescape ($$self{fixeditalic}), '110' => toescape ($$self{fixedbold}), '111' => toescape ($$self{fixedbolditalic}) };}# Initialize the quotes that we'll be using for C<> text. This requires some# special handling, both to parse the user parameter if given and to make sure# that the quotes will be safe against *roff. Sets the internal hash keys# LQUOTE and RQUOTE.sub init_quotes { my ($self) = (@_); $$self{quotes} ||= '"'; if ($$self{quotes} eq 'none') { $$self{LQUOTE} = $$self{RQUOTE} = ''; } elsif (length ($$self{quotes}) == 1) { $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes}; } elsif ($$self{quotes} =~ /^(.)(.)$/ || $$self{quotes} =~ /^(..)(..)$/) { $$self{LQUOTE} = $1; $$self{RQUOTE} = $2; } else { croak(qq(Invalid quote specification "$$self{quotes}")) } # Double the first quote; note that this should not be s///g as two double # quotes is represented in *roff as three double quotes, not four. Weird, # I know. $$self{LQUOTE} =~ s/\"/\"\"/; $$self{RQUOTE} =~ s/\"/\"\"/;}# Initialize the page title information and indentation from our arguments.sub init_page { my ($self) = @_; # We used to try first to get the version number from a local binary, but # we shouldn't need that any more. Get the version from the running Perl. # Work a little magic to handle subversions correctly under both the # pre-5.6 and the post-5.6 version numbering schemes. my @version = ($] =~ /^(\d+)\.(\d{3})(\d{0,3})$/); $version[2] ||= 0; $version[2] *= 10 ** (3 - length $version[2]); for (@version) { $_ += 0 } my $version = join ('.', @version); # Set the defaults for page titles and indentation if the user didn't # override anything. $$self{center} = 'User Contributed Perl Documentation' unless defined $$self{center}; $$self{release} = 'perl v' . $version unless defined $$self{release}; $$self{indent} = 4 unless defined $$self{indent}; # Double quotes in things that will be quoted. for (qw/center release/) { $$self{$_} =~ s/\"/\"\"/g if $$self{$_}; }}############################################################################### Core parsing############################################################################### This is the glue that connects the code below with Pod::Simple itself. The# goal is to convert the event stream coming from the POD parser into method# calls to handlers once the complete content of a tag has been seen. Each# paragraph or POD command will have textual content associated with it, and# as soon as all of a paragraph or POD command has been seen, that content# will be passed in to the corresponding method for handling that type of# object. The exceptions are handlers for lists, which have opening tag# handlers and closing tag handlers that will be called right away.## The internal hash key PENDING is used to store the contents of a tag until# all of it has been seen. It holds a stack of open tags, each one# represented by a tuple of the attributes hash for the tag, formatting# options for the tag (which are inherited), and the contents of the tag.# Add a block of text to the contents of the current node, formatting it# according to the current formatting instructions as we do.sub _handle_text { my ($self, $text) = @_; DEBUG > 3 and print "== $text\n"; my $tag = $$self{PENDING}[-1]; $$tag[2] .= $self->format_text ($$tag[1], $text);}# Given an element name, get the corresponding method name.sub method_for_element { my ($self, $element) = @_; $element =~ tr/-/_/; $element =~ tr/A-Z/a-z/; $element =~ tr/_a-z0-9//cd; return $element;}# Handle the start of a new element. If cmd_element is defined, assume that# we need to collect the entire tree for this element before passing it to the# element method, and create a new tree into which we'll collect blocks of# text and nested elements. Otherwise, if start_element is defined, call it.sub _handle_element_start { my ($self, $element, $attrs) = @_; DEBUG > 3 and print "++ $element (<", join ('> <', %$attrs), ">)\n"; my $method = $self->method_for_element ($element); # If we have a command handler, we need to accumulate the contents of the # tag before calling it. Turn off IN_NAME for any command other than # <Para> so that IN_NAME isn't still set for the first heading after the # NAME heading. if ($self->can ("cmd_$method")) { DEBUG > 2 and print "<$element> starts saving a tag\n"; $$self{IN_NAME} = 0 if ($element ne 'Para'); # How we're going to format embedded text blocks depends on the tag # and also depends on our parent tags. Thankfully, inside tags that # turn off guesswork and reformatting, nothing else can turn it back # on, so this can be strictly inherited. my $formatting = $$self{PENDING}[-1][1]; $formatting = $self->formatting ($formatting, $element); push (@{ $$self{PENDING} }, [ $attrs, $formatting, '' ]); DEBUG > 4 and print "Pending: [", pretty ($$self{PENDING}), "]\n"; } elsif ($self->can ("start_$method")) { my $method = 'start_' . $method; $self->$method ($attrs, ''); } else { DEBUG > 2 and print "No $method start method, skipping\n"; }}# Handle the end of an element. If we had a cmd_ method for this element,# this is where we pass along the tree that we built. Otherwise, if we have# an end_ method for the element, call that.sub _handle_element_end { my ($self, $element) = @_; DEBUG > 3 and print "-- $element\n"; my $method = $self->method_for_element ($element); # If we have a command handler, pull off the pending text and pass it to # the handler along with the saved attribute hash. if ($self->can ("cmd_$method")) { DEBUG > 2 and print "</$element> stops saving a tag\n"; my $tag = pop @{ $$self{PENDING} }; DEBUG > 4 and print "Popped: [", pretty ($tag), "]\n"; DEBUG > 4 and print "Pending: [", pretty ($$self{PENDING}), "]\n"; my $method = 'cmd_' . $method; my $text = $self->$method ($$tag[0], $$tag[2]); if (defined $text) { if (@{ $$self{PENDING} } > 1) { $$self{PENDING}[-1][2] .= $text; } else { $self->output ($text); } } } elsif ($self->can ("end_$method")) { my $method = 'end_' . $method; $self->$method (); } else { DEBUG > 2 and print "No $method end method, skipping\n"; }}############################################################################### General formatting############################################################################### Return formatting instructions for a new block. Takes the current# formatting and the new element. Formatting inherits negatively, in the# sense that if the parent has turned off guesswork, all child elements should# leave it off. We therefore return a copy of the same formatting# instructions but possibly with more things turned off depending on the# element.sub formatting { my ($self, $current, $element) = @_; my %options; if ($current) { %options = %$current; } else { %options = (guesswork => 1, cleanup => 1, convert => 1); } if ($element eq 'Data') { $options{guesswork} = 0; $options{cleanup} = 0; $options{convert} = 0; } elsif ($element eq 'X') { $options{guesswork} = 0; $options{cleanup} = 0; } elsif ($element eq 'Verbatim' || $element eq 'C') { $options{guesswork} = 0; $options{literal} = 1; } return \%options;}# Format a text block. Takes a hash of formatting options and the text to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -