This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Pod-Parser to CPAN version 1.60
[perl5.git] / cpan / Pod-Parser / lib / Pod / Select.pm
index 300eee5..148b5d1 100644 (file)
-#############################################################################
-# Pod/Select.pm -- function to select portions of POD docs
-#
-# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.
-# This file is part of "PodParser". PodParser is free software;
-# you can redistribute it and/or modify it under the same terms
-# as Perl itself.
-#############################################################################
-
-package Pod::Select;
-use strict;
-
-use vars qw($VERSION @ISA @EXPORT $MAX_HEADING_LEVEL %myData @section_headings @selected_sections);
-$VERSION = '1.51'; ## Current version of this package
-require  5.005;    ## requires this Perl version or later
-
-#############################################################################
-
-=head1 NAME
-
-Pod::Select, podselect() - extract selected sections of POD from input
-
-=head1 SYNOPSIS
-
-    use Pod::Select;
-
-    ## Select all the POD sections for each file in @filelist
-    ## and print the result on standard output.
-    podselect(@filelist);
-
-    ## Same as above, but write to tmp.out
-    podselect({-output => "tmp.out"}, @filelist):
-
-    ## Select from the given filelist, only those POD sections that are
-    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
-    podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist):
-
-    ## Select the "DESCRIPTION" section of the PODs from STDIN and write
-    ## the result to STDERR.
-    podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN);
-
-or
-
-    use Pod::Select;
-
-    ## Create a parser object for selecting POD sections from the input
-    $parser = new Pod::Select();
-
-    ## Select all the POD sections for each file in @filelist
-    ## and print the result to tmp.out.
-    $parser->parse_from_file("<&STDIN", "tmp.out");
-
-    ## Select from the given filelist, only those POD sections that are
-    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
-    $parser->select("NAME|SYNOPSIS", "OPTIONS");
-    for (@filelist) { $parser->parse_from_file($_); }
-
-    ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from
-    ## STDIN and write the result to STDERR.
-    $parser->select("DESCRIPTION");
-    $parser->add_selection("SEE ALSO");
-    $parser->parse_from_filehandle(\*STDIN, \*STDERR);
-
-=head1 REQUIRES
-
-perl5.005, Pod::Parser, Exporter, Carp
-
-=head1 EXPORTS
-
-podselect()
-
-=head1 DESCRIPTION
-
-B<podselect()> is a function which will extract specified sections of
-pod documentation from an input stream. This ability is provided by the
-B<Pod::Select> module which is a subclass of B<Pod::Parser>.
-B<Pod::Select> provides a method named B<select()> to specify the set of
-POD sections to select for processing/printing. B<podselect()> merely
-creates a B<Pod::Select> object and then invokes the B<podselect()>
-followed by B<parse_from_file()>.
-
-=head1 SECTION SPECIFICATIONS
-
-B<podselect()> and B<Pod::Select::select()> may be given one or more
-"section specifications" to restrict the text processed to only the
-desired set of sections and their corresponding subsections.  A section
-specification is a string containing one or more Perl-style regular
-expressions separated by forward slashes ("/").  If you need to use a
-forward slash literally within a section title you can escape it with a
-backslash ("\/").
-
-The formal syntax of a section specification is:
-
-=over 4
-
-=item *
-
-I<head1-title-regex>/I<head2-title-regex>/...
-
-=back
-
-Any omitted or empty regular expressions will default to ".*".
-Please note that each regular expression given is implicitly
-anchored by adding "^" and "$" to the beginning and end.  Also, if a
-given regular expression starts with a "!" character, then the
-expression is I<negated> (so C<!foo> would match anything I<except>
-C<foo>).
-
-Some example section specifications follow.
-
-=over 4
-
-=item *
-
-Match the C<NAME> and C<SYNOPSIS> sections and all of their subsections:
-
-C<NAME|SYNOPSIS>
-
-=item *
-
-Match only the C<Question> and C<Answer> subsections of the C<DESCRIPTION>
-section:
-
-C<DESCRIPTION/Question|Answer>
-
-=item *
-
-Match the C<Comments> subsection of I<all> sections:
-
-C</Comments>
-
-=item *
-
-Match all subsections of C<DESCRIPTION> I<except> for C<Comments>:
-
-C<DESCRIPTION/!Comments>
-
-=item *
-
-Match the C<DESCRIPTION> section but do I<not> match any of its subsections:
-
-C<DESCRIPTION/!.+>
-
-=item *
-
-Match all top level sections but none of their subsections:
-
-C</!.+>
-
-=back 
-
-=begin _NOT_IMPLEMENTED_
-
-=head1 RANGE SPECIFICATIONS
-
-B<podselect()> and B<Pod::Select::select()> may be given one or more
-"range specifications" to restrict the text processed to only the
-desired ranges of paragraphs in the desired set of sections. A range
-specification is a string containing a single Perl-style regular
-expression (a regex), or else two Perl-style regular expressions
-(regexs) separated by a ".." (Perl's "range" operator is "..").
-The regexs in a range specification are delimited by forward slashes
-("/").  If you need to use a forward slash literally within a regex you
-can escape it with a backslash ("\/").
-
-The formal syntax of a range specification is:
-
-=over 4
-
-=item *
-
-/I<start-range-regex>/[../I<end-range-regex>/]
-
-=back
-
-Where each the item inside square brackets (the ".." followed by the
-end-range-regex) is optional. Each "range-regex" is of the form:
-
-    =cmd-expr text-expr
-
-Where I<cmd-expr> is intended to match the name of one or more POD
-commands, and I<text-expr> is intended to match the paragraph text for
-the command. If a range-regex is supposed to match a POD command, then
-the first character of the regex (the one after the initial '/')
-absolutely I<must> be a single '=' character; it may not be anything
-else (not even a regex meta-character) if it is supposed to match
-against the name of a POD command.
-
-If no I<=cmd-expr> is given then the text-expr will be matched against
-plain textblocks unless it is preceded by a space, in which case it is
-matched against verbatim text-blocks. If no I<text-expr> is given then
-only the command-portion of the paragraph is matched against.
-
-Note that these two expressions are each implicitly anchored. This
-means that when matching against the command-name, there will be an
-implicit '^' and '$' around the given I<=cmd-expr>; and when matching
-against the paragraph text there will be an implicit '\A' and '\Z'
-around the given I<text-expr>.
-
-Unlike with section-specs, the '!' character does I<not> have any special
-meaning (negation or otherwise) at the beginning of a range-spec!
-
-Some example range specifications follow.
-
-=over 4
-
-=item
-Match all C<=for html> paragraphs:
-
-C</=for html/>
-
-=item
-Match all paragraphs between C<=begin html> and C<=end html>
-(note that this will I<not> work correctly if such sections
-are nested):
-
-C</=begin html/../=end html/>
-
-=item
-Match all paragraphs between the given C<=item> name until the end of the
-current section:
-
-C</=item mine/../=head\d/>
-
-=item
-Match all paragraphs between the given C<=item> until the next item, or
-until the end of the itemized list (note that this will I<not> work as
-desired if the item contains an itemized list nested within it):
-
-C</=item mine/../=(item|back)/>
-
-=back 
-
-=end _NOT_IMPLEMENTED_
-
-=cut
-
-#############################################################################
-
-#use diagnostics;
-use Carp;
-use Pod::Parser 1.04;
-
-@ISA = qw(Pod::Parser);
-@EXPORT = qw(&podselect);
-
-## Maximum number of heading levels supported for '=headN' directives
-*MAX_HEADING_LEVEL = \3;
-
-#############################################################################
-
-=head1 OBJECT METHODS
-
-The following methods are provided in this module. Each one takes a
-reference to the object itself as an implicit first parameter.
-
-=cut
-
-##---------------------------------------------------------------------------
-
-## =begin _PRIVATE_
-## 
-## =head1 B<_init_headings()>
-## 
-## Initialize the current set of active section headings.
-## 
-## =cut
-## 
-## =end _PRIVATE_
-
-sub _init_headings {
-    my $self = shift;
-    local *myData = $self;
-
-    ## Initialize current section heading titles if necessary
-    unless (defined $myData{_SECTION_HEADINGS}) {
-        local *section_headings = $myData{_SECTION_HEADINGS} = [];
-        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
-            $section_headings[$i] = '';
-        }
-    }
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<curr_headings()>
-
-            ($head1, $head2, $head3, ...) = $parser->curr_headings();
-            $head1 = $parser->curr_headings(1);
-
-This method returns a list of the currently active section headings and
-subheadings in the document being parsed. The list of headings returned
-corresponds to the most recently parsed paragraph of the input.
-
-If an argument is given, it must correspond to the desired section
-heading number, in which case only the specified section heading is
-returned. If there is no current section heading at the specified
-level, then C<undef> is returned.
-
-=cut
-
-sub curr_headings {
-    my $self = shift;
-    $self->_init_headings()  unless (defined $self->{_SECTION_HEADINGS});
-    my @headings = @{ $self->{_SECTION_HEADINGS} };
-    return (@_ > 0  and  $_[0] =~ /^\d+$/) ? $headings[$_[0] - 1] : @headings;
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<select()>
-
-            $parser->select($section_spec1,$section_spec2,...);
-
-This method is used to select the particular sections and subsections of
-POD documentation that are to be printed and/or processed. The existing
-set of selected sections is I<replaced> with the given set of sections.
-See B<add_selection()> for adding to the current set of selected
-sections.
-
-Each of the C<$section_spec> arguments should be a section specification
-as described in L<"SECTION SPECIFICATIONS">.  The section specifications
-are parsed by this method and the resulting regular expressions are
-stored in the invoking object.
-
-If no C<$section_spec> arguments are given, then the existing set of
-selected sections is cleared out (which means C<all> sections will be
-processed).
-
-This method should I<not> normally be overridden by subclasses.
-
-=cut
-
-sub select {
-    my ($self, @sections) = @_;
-    local *myData = $self;
-    local $_;
-
-### NEED TO DISCERN A SECTION-SPEC FROM A RANGE-SPEC (look for m{^/.+/$}?)
-
-    ##---------------------------------------------------------------------
-    ## The following is a blatant hack for backward compatibility, and for
-    ## implementing add_selection(). If the *first* *argument* is the
-    ## string "+", then the remaining section specifications are *added*
-    ## to the current set of selections; otherwise the given section
-    ## specifications will *replace* the current set of selections.
-    ##
-    ## This should probably be fixed someday, but for the present time,
-    ## it seems incredibly unlikely that "+" would ever correspond to
-    ## a legitimate section heading
-    ##---------------------------------------------------------------------
-    my $add = ($sections[0] eq '+') ? shift(@sections) : '';
-
-    ## Reset the set of sections to use
-    unless (@sections) {
-        delete $myData{_SELECTED_SECTIONS}  unless ($add);
-        return;
-    }
-    $myData{_SELECTED_SECTIONS} = []
-        unless ($add  &&  exists $myData{_SELECTED_SECTIONS});
-    local *selected_sections = $myData{_SELECTED_SECTIONS};
-
-    ## Compile each spec
-    for my $spec (@sections) {
-        if ( defined($_ = _compile_section_spec($spec)) ) {
-            ## Store them in our sections array
-            push(@selected_sections, $_);
-        }
-        else {
-            carp qq{Ignoring section spec "$spec"!\n};
-        }
-    }
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<add_selection()>
-
-            $parser->add_selection($section_spec1,$section_spec2,...);
-
-This method is used to add to the currently selected sections and
-subsections of POD documentation that are to be printed and/or
-processed. See <select()> for replacing the currently selected sections.
-
-Each of the C<$section_spec> arguments should be a section specification
-as described in L<"SECTION SPECIFICATIONS">. The section specifications
-are parsed by this method and the resulting regular expressions are
-stored in the invoking object.
-
-This method should I<not> normally be overridden by subclasses.
-
-=cut
-
-sub add_selection {
-    my $self = shift;
-    return $self->select('+', @_);
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<clear_selections()>
-
-            $parser->clear_selections();
-
-This method takes no arguments, it has the exact same effect as invoking
-<select()> with no arguments.
-
-=cut
-
-sub clear_selections {
-    my $self = shift;
-    return $self->select();
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<match_section()>
-
-            $boolean = $parser->match_section($heading1,$heading2,...);
-
-Returns a value of true if the given section and subsection heading
-titles match any of the currently selected section specifications in
-effect from prior calls to B<select()> and B<add_selection()> (or if
-there are no explicitly selected/deselected sections).
-
-The arguments C<$heading1>, C<$heading2>, etc. are the heading titles of
-the corresponding sections, subsections, etc. to try and match.  If
-C<$headingN> is omitted then it defaults to the current corresponding
-section heading title in the input.
-
-This method should I<not> normally be overridden by subclasses.
-
-=cut
-
-sub match_section {
-    my $self = shift;
-    my (@headings) = @_;
-    local *myData = $self;
-
-    ## Return true if no restrictions were explicitly specified
-    my $selections = (exists $myData{_SELECTED_SECTIONS})
-                       ?  $myData{_SELECTED_SECTIONS}  :  undef;
-    return  1  unless ((defined $selections) && @{$selections});
-
-    ## Default any unspecified sections to the current one
-    my @current_headings = $self->curr_headings();
-    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
-        (defined $headings[$i])  or  $headings[$i] = $current_headings[$i];
-    }
-
-    ## Look for a match against the specified section expressions
-    for my $section_spec ( @{$selections} ) {
-        ##------------------------------------------------------
-        ## Each portion of this spec must match in order for
-        ## the spec to be matched. So we will start with a 
-        ## match-value of 'true' and logically 'and' it with
-        ## the results of matching a given element of the spec.
-        ##------------------------------------------------------
-        my $match = 1;
-        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
-            my $regex   = $section_spec->[$i];
-            my $negated = ($regex =~ s/^\!//);
-            $match  &= ($negated ? ($headings[$i] !~ /${regex}/)
-                                 : ($headings[$i] =~ /${regex}/));
-            last unless ($match);
-        }
-        return  1  if ($match);
-    }
-    return  0;  ## no match
-}
-
-##---------------------------------------------------------------------------
-
-=head1 B<is_selected()>
-
-            $boolean = $parser->is_selected($paragraph);
-
-This method is used to determine if the block of text given in
-C<$paragraph> falls within the currently selected set of POD sections
-and subsections to be printed or processed. This method is also
-responsible for keeping track of the current input section and
-subsections. It is assumed that C<$paragraph> is the most recently read
-(but not yet processed) input paragraph.
-
-The value returned will be true if the C<$paragraph> and the rest of the
-text in the same section as C<$paragraph> should be selected (included)
-for processing; otherwise a false value is returned.
-
-=cut
-
-sub is_selected {
-    my ($self, $paragraph) = @_;
-    local $_;
-    local *myData = $self;
-
-    $self->_init_headings()  unless (defined $myData{_SECTION_HEADINGS});
-
-    ## Keep track of current sections levels and headings
-    $_ = $paragraph;
-    if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*?)\s*$/)
-    {
-        ## This is a section heading command
-        my ($level, $heading) = ($2, $3);
-        $level = 1 + (length($1) / 3)  if ((! length $level) || (length $1));
-        ## Reset the current section heading at this level
-        $myData{_SECTION_HEADINGS}->[$level - 1] = $heading;
-        ## Reset subsection headings of this one to empty
-        for (my $i = $level; $i < $MAX_HEADING_LEVEL; ++$i) {
-            $myData{_SECTION_HEADINGS}->[$i] = '';
-        }
-    }
-
-    return  $self->match_section();
-}
-
-#############################################################################
-
-=head1 EXPORTED FUNCTIONS
-
-The following functions are exported by this module. Please note that
-these are functions (not methods) and therefore C<do not> take an
-implicit first argument.
-
-=cut
-
-##---------------------------------------------------------------------------
-
-=head1 B<podselect()>
-
-            podselect(\%options,@filelist);
-
-B<podselect> will print the raw (untranslated) POD paragraphs of all
-POD sections in the given input files specified by C<@filelist>
-according to the given options.
-
-If any argument to B<podselect> is a reference to a hash
-(associative array) then the values with the following keys are
-processed as follows:
-
-=over 4
-
-=item B<-output>
-
-A string corresponding to the desired output file (or ">&STDOUT"
-or ">&STDERR"). The default is to use standard output.
-
-=item B<-sections>
-
-A reference to an array of sections specifications (as described in
-L<"SECTION SPECIFICATIONS">) which indicate the desired set of POD
-sections and subsections to be selected from input. If no section
-specifications are given, then all sections of the PODs are used.
-
-=begin _NOT_IMPLEMENTED_
-
-=item B<-ranges>
-
-A reference to an array of range specifications (as described in
-L<"RANGE SPECIFICATIONS">) which indicate the desired range of POD
-paragraphs to be selected from the desired input sections. If no range
-specifications are given, then all paragraphs of the desired sections
-are used.
-
-=end _NOT_IMPLEMENTED_
-
-=back
-
-All other arguments should correspond to the names of input files
-containing POD sections. A file name of "-" or "<&STDIN" will
-be interpreted to mean standard input (which is the default if no
-filenames are given).
-
-=cut 
-
-sub podselect {
-    my(@argv) = @_;
-    my %defaults = ();
-    my $pod_parser = new Pod::Select(%defaults);
-    my $num_inputs = 0;
-    my $output = '>&STDOUT';
-    my %opts;
-    local $_;
-    for (@argv) {
-        if (ref($_)) {
-        next unless (ref($_) eq 'HASH');
-            %opts = (%defaults, %{$_});
-
-            ##-------------------------------------------------------------
-            ## Need this for backward compatibility since we formerly used
-            ## options that were all uppercase words rather than ones that
-            ## looked like Unix command-line options.
-            ## to be uppercase keywords)
-            ##-------------------------------------------------------------
-            %opts = map {
-                my ($key, $val) = (lc $_, $opts{$_});
-                $key =~ s/^(?=\w)/-/;
-                $key =~ /^-se[cl]/  and  $key  = '-sections';
-                #! $key eq '-range'    and  $key .= 's';
-                ($key => $val);
-            } (keys %opts);
-
-            ## Process the options
-            (exists $opts{'-output'})  and  $output = $opts{'-output'};
-
-            ## Select the desired sections
-            $pod_parser->select(@{ $opts{'-sections'} })
-                if ( (defined $opts{'-sections'})
-                     && ((ref $opts{'-sections'}) eq 'ARRAY') );
-
-            #! ## Select the desired paragraph ranges
-            #! $pod_parser->select(@{ $opts{'-ranges'} })
-            #!     if ( (defined $opts{'-ranges'})
-            #!          && ((ref $opts{'-ranges'}) eq 'ARRAY') );
-        }
-        else {
-            $pod_parser->parse_from_file($_, $output);
-            ++$num_inputs;
-        }
-    }
-    $pod_parser->parse_from_file('-')  unless ($num_inputs > 0);
-}
-
-#############################################################################
-
-=head1 PRIVATE METHODS AND DATA
-
-B<Pod::Select> makes uses a number of internal methods and data fields
-which clients should not need to see or use. For the sake of avoiding
-name collisions with client data and methods, these methods and fields
-are briefly discussed here. Determined hackers may obtain further
-information about them by reading the B<Pod::Select> source code.
-
-Private data fields are stored in the hash-object whose reference is
-returned by the B<new()> constructor for this class. The names of all
-private methods and data-fields used by B<Pod::Select> begin with a
-prefix of "_" and match the regular expression C</^_\w+$/>.
-
-=cut
-
-##---------------------------------------------------------------------------
-
-=begin _PRIVATE_
-
-=head1 B<_compile_section_spec()>
-
-            $listref = $parser->_compile_section_spec($section_spec);
-
-This function (note it is a function and I<not> a method) takes a
-section specification (as described in L<"SECTION SPECIFICATIONS">)
-given in C<$section_sepc>, and compiles it into a list of regular
-expressions. If C<$section_spec> has no syntax errors, then a reference
-to the list (array) of corresponding regular expressions is returned;
-otherwise C<undef> is returned and an error message is printed (using
-B<carp>) for each invalid regex.
-
-=end _PRIVATE_
-
-=cut
-
-sub _compile_section_spec {
-    my ($section_spec) = @_;
-    my (@regexs, $negated);
-
-    ## Compile the spec into a list of regexs
-    local $_ = $section_spec;
-    s{\\\\}{\001}g;  ## handle escaped backward slashes
-    s{\\/}{\002}g;   ## handle escaped forward slashes
-
-    ## Parse the regexs for the heading titles
-    @regexs = split(/\//, $_, $MAX_HEADING_LEVEL);
-
-    ## Set default regex for ommitted levels
-    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
-        $regexs[$i]  = '.*'  unless ((defined $regexs[$i])
-                                     && (length $regexs[$i]));
-    }
-    ## Modify the regexs as needed and validate their syntax
-    my $bad_regexs = 0;
-    for (@regexs) {
-        $_ .= '.+'  if ($_ eq '!');
-        s{\001}{\\\\}g;       ## restore escaped backward slashes
-        s{\002}{\\/}g;        ## restore escaped forward slashes
-        $negated = s/^\!//;   ## check for negation
-        eval "m{$_}";         ## check regex syntax
-        if ($@) {
-            ++$bad_regexs;
-            carp qq{Bad regular expression /$_/ in "$section_spec": $@\n};
-        }
-        else {
-            ## Add the forward and rear anchors (and put the negator back)
-            $_ = '^' . $_  unless (/^\^/);
-            $_ = $_ . '$'  unless (/\$$/);
-            $_ = '!' . $_  if ($negated);
-        }
-    }
-    return  (! $bad_regexs) ? [ @regexs ] : undef;
-}
-
-##---------------------------------------------------------------------------
-
-=begin _PRIVATE_
-
-=head2 $self->{_SECTION_HEADINGS}
-
-A reference to an array of the current section heading titles for each
-heading level (note that the first heading level title is at index 0).
-
-=end _PRIVATE_
-
-=cut
-
-##---------------------------------------------------------------------------
-
-=begin _PRIVATE_
-
-=head2 $self->{_SELECTED_SECTIONS}
-
-A reference to an array of references to arrays. Each subarray is a list
-of anchored regular expressions (preceded by a "!" if the expression is to
-be negated). The index of the expression in the subarray should correspond
-to the index of the heading title in C<$self-E<gt>{_SECTION_HEADINGS}>
-that it is to be matched against.
-
-=end _PRIVATE_
-
-=cut
-
-#############################################################################
-
-=head1 SEE ALSO
-
-L<Pod::Parser>
-
-=head1 AUTHOR
-
-Please report bugs using L<http://rt.cpan.org>.
-
-Brad Appleton E<lt>bradapp@enteract.comE<gt>
-
-Based on code for B<pod2text> written by
-Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>
-
-B<Pod::Select> is part of the L<Pod::Parser> distribution.
-
-=cut
-
-1;
-# vim: ts=4 sw=4 et
+#############################################################################\r
+# Pod/Select.pm -- function to select portions of POD docs\r
+#\r
+# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.\r
+# This file is part of "PodParser". PodParser is free software;\r
+# you can redistribute it and/or modify it under the same terms\r
+# as Perl itself.\r
+#############################################################################\r
+\r
+package Pod::Select;\r
+use strict;\r
+\r
+use vars qw($VERSION @ISA @EXPORT $MAX_HEADING_LEVEL %myData @section_headings @selected_sections);\r
+$VERSION = '1.60'; ## Current version of this package\r
+require  5.005;    ## requires this Perl version or later\r
+\r
+#############################################################################\r
+\r
+=head1 NAME\r
+\r
+Pod::Select, podselect() - extract selected sections of POD from input\r
+\r
+=head1 SYNOPSIS\r
+\r
+    use Pod::Select;\r
+\r
+    ## Select all the POD sections for each file in @filelist\r
+    ## and print the result on standard output.\r
+    podselect(@filelist);\r
+\r
+    ## Same as above, but write to tmp.out\r
+    podselect({-output => "tmp.out"}, @filelist):\r
+\r
+    ## Select from the given filelist, only those POD sections that are\r
+    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.\r
+    podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist):\r
+\r
+    ## Select the "DESCRIPTION" section of the PODs from STDIN and write\r
+    ## the result to STDERR.\r
+    podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN);\r
+\r
+or\r
+\r
+    use Pod::Select;\r
+\r
+    ## Create a parser object for selecting POD sections from the input\r
+    $parser = new Pod::Select();\r
+\r
+    ## Select all the POD sections for each file in @filelist\r
+    ## and print the result to tmp.out.\r
+    $parser->parse_from_file("<&STDIN", "tmp.out");\r
+\r
+    ## Select from the given filelist, only those POD sections that are\r
+    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.\r
+    $parser->select("NAME|SYNOPSIS", "OPTIONS");\r
+    for (@filelist) { $parser->parse_from_file($_); }\r
+\r
+    ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from\r
+    ## STDIN and write the result to STDERR.\r
+    $parser->select("DESCRIPTION");\r
+    $parser->add_selection("SEE ALSO");\r
+    $parser->parse_from_filehandle(\*STDIN, \*STDERR);\r
+\r
+=head1 REQUIRES\r
+\r
+perl5.005, Pod::Parser, Exporter, Carp\r
+\r
+=head1 EXPORTS\r
+\r
+podselect()\r
+\r
+=head1 DESCRIPTION\r
+\r
+B<podselect()> is a function which will extract specified sections of\r
+pod documentation from an input stream. This ability is provided by the\r
+B<Pod::Select> module which is a subclass of B<Pod::Parser>.\r
+B<Pod::Select> provides a method named B<select()> to specify the set of\r
+POD sections to select for processing/printing. B<podselect()> merely\r
+creates a B<Pod::Select> object and then invokes the B<podselect()>\r
+followed by B<parse_from_file()>.\r
+\r
+=head1 SECTION SPECIFICATIONS\r
+\r
+B<podselect()> and B<Pod::Select::select()> may be given one or more\r
+"section specifications" to restrict the text processed to only the\r
+desired set of sections and their corresponding subsections.  A section\r
+specification is a string containing one or more Perl-style regular\r
+expressions separated by forward slashes ("/").  If you need to use a\r
+forward slash literally within a section title you can escape it with a\r
+backslash ("\/").\r
+\r
+The formal syntax of a section specification is:\r
+\r
+=over 4\r
+\r
+=item *\r
+\r
+I<head1-title-regex>/I<head2-title-regex>/...\r
+\r
+=back\r
+\r
+Any omitted or empty regular expressions will default to ".*".\r
+Please note that each regular expression given is implicitly\r
+anchored by adding "^" and "$" to the beginning and end.  Also, if a\r
+given regular expression starts with a "!" character, then the\r
+expression is I<negated> (so C<!foo> would match anything I<except>\r
+C<foo>).\r
+\r
+Some example section specifications follow.\r
+\r
+=over 4\r
+\r
+=item *\r
+\r
+Match the C<NAME> and C<SYNOPSIS> sections and all of their subsections:\r
+\r
+C<NAME|SYNOPSIS>\r
+\r
+=item *\r
+\r
+Match only the C<Question> and C<Answer> subsections of the C<DESCRIPTION>\r
+section:\r
+\r
+C<DESCRIPTION/Question|Answer>\r
+\r
+=item *\r
+\r
+Match the C<Comments> subsection of I<all> sections:\r
+\r
+C</Comments>\r
+\r
+=item *\r
+\r
+Match all subsections of C<DESCRIPTION> I<except> for C<Comments>:\r
+\r
+C<DESCRIPTION/!Comments>\r
+\r
+=item *\r
+\r
+Match the C<DESCRIPTION> section but do I<not> match any of its subsections:\r
+\r
+C<DESCRIPTION/!.+>\r
+\r
+=item *\r
+\r
+Match all top level sections but none of their subsections:\r
+\r
+C</!.+>\r
+\r
+=back \r
+\r
+=begin _NOT_IMPLEMENTED_\r
+\r
+=head1 RANGE SPECIFICATIONS\r
+\r
+B<podselect()> and B<Pod::Select::select()> may be given one or more\r
+"range specifications" to restrict the text processed to only the\r
+desired ranges of paragraphs in the desired set of sections. A range\r
+specification is a string containing a single Perl-style regular\r
+expression (a regex), or else two Perl-style regular expressions\r
+(regexs) separated by a ".." (Perl's "range" operator is "..").\r
+The regexs in a range specification are delimited by forward slashes\r
+("/").  If you need to use a forward slash literally within a regex you\r
+can escape it with a backslash ("\/").\r
+\r
+The formal syntax of a range specification is:\r
+\r
+=over 4\r
+\r
+=item *\r
+\r
+/I<start-range-regex>/[../I<end-range-regex>/]\r
+\r
+=back\r
+\r
+Where each the item inside square brackets (the ".." followed by the\r
+end-range-regex) is optional. Each "range-regex" is of the form:\r
+\r
+    =cmd-expr text-expr\r
+\r
+Where I<cmd-expr> is intended to match the name of one or more POD\r
+commands, and I<text-expr> is intended to match the paragraph text for\r
+the command. If a range-regex is supposed to match a POD command, then\r
+the first character of the regex (the one after the initial '/')\r
+absolutely I<must> be a single '=' character; it may not be anything\r
+else (not even a regex meta-character) if it is supposed to match\r
+against the name of a POD command.\r
+\r
+If no I<=cmd-expr> is given then the text-expr will be matched against\r
+plain textblocks unless it is preceded by a space, in which case it is\r
+matched against verbatim text-blocks. If no I<text-expr> is given then\r
+only the command-portion of the paragraph is matched against.\r
+\r
+Note that these two expressions are each implicitly anchored. This\r
+means that when matching against the command-name, there will be an\r
+implicit '^' and '$' around the given I<=cmd-expr>; and when matching\r
+against the paragraph text there will be an implicit '\A' and '\Z'\r
+around the given I<text-expr>.\r
+\r
+Unlike with section-specs, the '!' character does I<not> have any special\r
+meaning (negation or otherwise) at the beginning of a range-spec!\r
+\r
+Some example range specifications follow.\r
+\r
+=over 4\r
+\r
+=item\r
+Match all C<=for html> paragraphs:\r
+\r
+C</=for html/>\r
+\r
+=item\r
+Match all paragraphs between C<=begin html> and C<=end html>\r
+(note that this will I<not> work correctly if such sections\r
+are nested):\r
+\r
+C</=begin html/../=end html/>\r
+\r
+=item\r
+Match all paragraphs between the given C<=item> name until the end of the\r
+current section:\r
+\r
+C</=item mine/../=head\d/>\r
+\r
+=item\r
+Match all paragraphs between the given C<=item> until the next item, or\r
+until the end of the itemized list (note that this will I<not> work as\r
+desired if the item contains an itemized list nested within it):\r
+\r
+C</=item mine/../=(item|back)/>\r
+\r
+=back \r
+\r
+=end _NOT_IMPLEMENTED_\r
+\r
+=cut\r
+\r
+#############################################################################\r
+\r
+#use diagnostics;\r
+use Carp;\r
+use Pod::Parser 1.04;\r
+\r
+@ISA = qw(Pod::Parser);\r
+@EXPORT = qw(&podselect);\r
+\r
+## Maximum number of heading levels supported for '=headN' directives\r
+*MAX_HEADING_LEVEL = \3;\r
+\r
+#############################################################################\r
+\r
+=head1 OBJECT METHODS\r
+\r
+The following methods are provided in this module. Each one takes a\r
+reference to the object itself as an implicit first parameter.\r
+\r
+=cut\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+## =begin _PRIVATE_\r
+## \r
+## =head1 B<_init_headings()>\r
+## \r
+## Initialize the current set of active section headings.\r
+## \r
+## =cut\r
+## \r
+## =end _PRIVATE_\r
+\r
+sub _init_headings {\r
+    my $self = shift;\r
+    local *myData = $self;\r
+\r
+    ## Initialize current section heading titles if necessary\r
+    unless (defined $myData{_SECTION_HEADINGS}) {\r
+        local *section_headings = $myData{_SECTION_HEADINGS} = [];\r
+        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {\r
+            $section_headings[$i] = '';\r
+        }\r
+    }\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<curr_headings()>\r
+\r
+            ($head1, $head2, $head3, ...) = $parser->curr_headings();\r
+            $head1 = $parser->curr_headings(1);\r
+\r
+This method returns a list of the currently active section headings and\r
+subheadings in the document being parsed. The list of headings returned\r
+corresponds to the most recently parsed paragraph of the input.\r
+\r
+If an argument is given, it must correspond to the desired section\r
+heading number, in which case only the specified section heading is\r
+returned. If there is no current section heading at the specified\r
+level, then C<undef> is returned.\r
+\r
+=cut\r
+\r
+sub curr_headings {\r
+    my $self = shift;\r
+    $self->_init_headings()  unless (defined $self->{_SECTION_HEADINGS});\r
+    my @headings = @{ $self->{_SECTION_HEADINGS} };\r
+    return (@_ > 0  and  $_[0] =~ /^\d+$/) ? $headings[$_[0] - 1] : @headings;\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<select()>\r
+\r
+            $parser->select($section_spec1,$section_spec2,...);\r
+\r
+This method is used to select the particular sections and subsections of\r
+POD documentation that are to be printed and/or processed. The existing\r
+set of selected sections is I<replaced> with the given set of sections.\r
+See B<add_selection()> for adding to the current set of selected\r
+sections.\r
+\r
+Each of the C<$section_spec> arguments should be a section specification\r
+as described in L<"SECTION SPECIFICATIONS">.  The section specifications\r
+are parsed by this method and the resulting regular expressions are\r
+stored in the invoking object.\r
+\r
+If no C<$section_spec> arguments are given, then the existing set of\r
+selected sections is cleared out (which means C<all> sections will be\r
+processed).\r
+\r
+This method should I<not> normally be overridden by subclasses.\r
+\r
+=cut\r
+\r
+sub select {\r
+    my ($self, @sections) = @_;\r
+    local *myData = $self;\r
+    local $_;\r
+\r
+### NEED TO DISCERN A SECTION-SPEC FROM A RANGE-SPEC (look for m{^/.+/$}?)\r
+\r
+    ##---------------------------------------------------------------------\r
+    ## The following is a blatant hack for backward compatibility, and for\r
+    ## implementing add_selection(). If the *first* *argument* is the\r
+    ## string "+", then the remaining section specifications are *added*\r
+    ## to the current set of selections; otherwise the given section\r
+    ## specifications will *replace* the current set of selections.\r
+    ##\r
+    ## This should probably be fixed someday, but for the present time,\r
+    ## it seems incredibly unlikely that "+" would ever correspond to\r
+    ## a legitimate section heading\r
+    ##---------------------------------------------------------------------\r
+    my $add = ($sections[0] eq '+') ? shift(@sections) : '';\r
+\r
+    ## Reset the set of sections to use\r
+    unless (@sections) {\r
+        delete $myData{_SELECTED_SECTIONS}  unless ($add);\r
+        return;\r
+    }\r
+    $myData{_SELECTED_SECTIONS} = []\r
+        unless ($add  &&  exists $myData{_SELECTED_SECTIONS});\r
+    local *selected_sections = $myData{_SELECTED_SECTIONS};\r
+\r
+    ## Compile each spec\r
+    for my $spec (@sections) {\r
+        if ( defined($_ = _compile_section_spec($spec)) ) {\r
+            ## Store them in our sections array\r
+            push(@selected_sections, $_);\r
+        }\r
+        else {\r
+            carp qq{Ignoring section spec "$spec"!\n};\r
+        }\r
+    }\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<add_selection()>\r
+\r
+            $parser->add_selection($section_spec1,$section_spec2,...);\r
+\r
+This method is used to add to the currently selected sections and\r
+subsections of POD documentation that are to be printed and/or\r
+processed. See <select()> for replacing the currently selected sections.\r
+\r
+Each of the C<$section_spec> arguments should be a section specification\r
+as described in L<"SECTION SPECIFICATIONS">. The section specifications\r
+are parsed by this method and the resulting regular expressions are\r
+stored in the invoking object.\r
+\r
+This method should I<not> normally be overridden by subclasses.\r
+\r
+=cut\r
+\r
+sub add_selection {\r
+    my $self = shift;\r
+    return $self->select('+', @_);\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<clear_selections()>\r
+\r
+            $parser->clear_selections();\r
+\r
+This method takes no arguments, it has the exact same effect as invoking\r
+<select()> with no arguments.\r
+\r
+=cut\r
+\r
+sub clear_selections {\r
+    my $self = shift;\r
+    return $self->select();\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<match_section()>\r
+\r
+            $boolean = $parser->match_section($heading1,$heading2,...);\r
+\r
+Returns a value of true if the given section and subsection heading\r
+titles match any of the currently selected section specifications in\r
+effect from prior calls to B<select()> and B<add_selection()> (or if\r
+there are no explicitly selected/deselected sections).\r
+\r
+The arguments C<$heading1>, C<$heading2>, etc. are the heading titles of\r
+the corresponding sections, subsections, etc. to try and match.  If\r
+C<$headingN> is omitted then it defaults to the current corresponding\r
+section heading title in the input.\r
+\r
+This method should I<not> normally be overridden by subclasses.\r
+\r
+=cut\r
+\r
+sub match_section {\r
+    my $self = shift;\r
+    my (@headings) = @_;\r
+    local *myData = $self;\r
+\r
+    ## Return true if no restrictions were explicitly specified\r
+    my $selections = (exists $myData{_SELECTED_SECTIONS})\r
+                       ?  $myData{_SELECTED_SECTIONS}  :  undef;\r
+    return  1  unless ((defined $selections) && @{$selections});\r
+\r
+    ## Default any unspecified sections to the current one\r
+    my @current_headings = $self->curr_headings();\r
+    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {\r
+        (defined $headings[$i])  or  $headings[$i] = $current_headings[$i];\r
+    }\r
+\r
+    ## Look for a match against the specified section expressions\r
+    for my $section_spec ( @{$selections} ) {\r
+        ##------------------------------------------------------\r
+        ## Each portion of this spec must match in order for\r
+        ## the spec to be matched. So we will start with a \r
+        ## match-value of 'true' and logically 'and' it with\r
+        ## the results of matching a given element of the spec.\r
+        ##------------------------------------------------------\r
+        my $match = 1;\r
+        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {\r
+            my $regex   = $section_spec->[$i];\r
+            my $negated = ($regex =~ s/^\!//);\r
+            $match  &= ($negated ? ($headings[$i] !~ /${regex}/)\r
+                                 : ($headings[$i] =~ /${regex}/));\r
+            last unless ($match);\r
+        }\r
+        return  1  if ($match);\r
+    }\r
+    return  0;  ## no match\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<is_selected()>\r
+\r
+            $boolean = $parser->is_selected($paragraph);\r
+\r
+This method is used to determine if the block of text given in\r
+C<$paragraph> falls within the currently selected set of POD sections\r
+and subsections to be printed or processed. This method is also\r
+responsible for keeping track of the current input section and\r
+subsections. It is assumed that C<$paragraph> is the most recently read\r
+(but not yet processed) input paragraph.\r
+\r
+The value returned will be true if the C<$paragraph> and the rest of the\r
+text in the same section as C<$paragraph> should be selected (included)\r
+for processing; otherwise a false value is returned.\r
+\r
+=cut\r
+\r
+sub is_selected {\r
+    my ($self, $paragraph) = @_;\r
+    local $_;\r
+    local *myData = $self;\r
+\r
+    $self->_init_headings()  unless (defined $myData{_SECTION_HEADINGS});\r
+\r
+    ## Keep track of current sections levels and headings\r
+    $_ = $paragraph;\r
+    if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*?)\s*$/)\r
+    {\r
+        ## This is a section heading command\r
+        my ($level, $heading) = ($2, $3);\r
+        $level = 1 + (length($1) / 3)  if ((! length $level) || (length $1));\r
+        ## Reset the current section heading at this level\r
+        $myData{_SECTION_HEADINGS}->[$level - 1] = $heading;\r
+        ## Reset subsection headings of this one to empty\r
+        for (my $i = $level; $i < $MAX_HEADING_LEVEL; ++$i) {\r
+            $myData{_SECTION_HEADINGS}->[$i] = '';\r
+        }\r
+    }\r
+\r
+    return  $self->match_section();\r
+}\r
+\r
+#############################################################################\r
+\r
+=head1 EXPORTED FUNCTIONS\r
+\r
+The following functions are exported by this module. Please note that\r
+these are functions (not methods) and therefore C<do not> take an\r
+implicit first argument.\r
+\r
+=cut\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=head1 B<podselect()>\r
+\r
+            podselect(\%options,@filelist);\r
+\r
+B<podselect> will print the raw (untranslated) POD paragraphs of all\r
+POD sections in the given input files specified by C<@filelist>\r
+according to the given options.\r
+\r
+If any argument to B<podselect> is a reference to a hash\r
+(associative array) then the values with the following keys are\r
+processed as follows:\r
+\r
+=over 4\r
+\r
+=item B<-output>\r
+\r
+A string corresponding to the desired output file (or ">&STDOUT"\r
+or ">&STDERR"). The default is to use standard output.\r
+\r
+=item B<-sections>\r
+\r
+A reference to an array of sections specifications (as described in\r
+L<"SECTION SPECIFICATIONS">) which indicate the desired set of POD\r
+sections and subsections to be selected from input. If no section\r
+specifications are given, then all sections of the PODs are used.\r
+\r
+=begin _NOT_IMPLEMENTED_\r
+\r
+=item B<-ranges>\r
+\r
+A reference to an array of range specifications (as described in\r
+L<"RANGE SPECIFICATIONS">) which indicate the desired range of POD\r
+paragraphs to be selected from the desired input sections. If no range\r
+specifications are given, then all paragraphs of the desired sections\r
+are used.\r
+\r
+=end _NOT_IMPLEMENTED_\r
+\r
+=back\r
+\r
+All other arguments should correspond to the names of input files\r
+containing POD sections. A file name of "-" or "<&STDIN" will\r
+be interpreted to mean standard input (which is the default if no\r
+filenames are given).\r
+\r
+=cut \r
+\r
+sub podselect {\r
+    my(@argv) = @_;\r
+    my %defaults = ();\r
+    my $pod_parser = new Pod::Select(%defaults);\r
+    my $num_inputs = 0;\r
+    my $output = '>&STDOUT';\r
+    my %opts;\r
+    local $_;\r
+    for (@argv) {\r
+        if (ref($_)) {\r
+        next unless (ref($_) eq 'HASH');\r
+            %opts = (%defaults, %{$_});\r
+\r
+            ##-------------------------------------------------------------\r
+            ## Need this for backward compatibility since we formerly used\r
+            ## options that were all uppercase words rather than ones that\r
+            ## looked like Unix command-line options.\r
+            ## to be uppercase keywords)\r
+            ##-------------------------------------------------------------\r
+            %opts = map {\r
+                my ($key, $val) = (lc $_, $opts{$_});\r
+                $key =~ s/^(?=\w)/-/;\r
+                $key =~ /^-se[cl]/  and  $key  = '-sections';\r
+                #! $key eq '-range'    and  $key .= 's';\r
+                ($key => $val);\r
+            } (keys %opts);\r
+\r
+            ## Process the options\r
+            (exists $opts{'-output'})  and  $output = $opts{'-output'};\r
+\r
+            ## Select the desired sections\r
+            $pod_parser->select(@{ $opts{'-sections'} })\r
+                if ( (defined $opts{'-sections'})\r
+                     && ((ref $opts{'-sections'}) eq 'ARRAY') );\r
+\r
+            #! ## Select the desired paragraph ranges\r
+            #! $pod_parser->select(@{ $opts{'-ranges'} })\r
+            #!     if ( (defined $opts{'-ranges'})\r
+            #!          && ((ref $opts{'-ranges'}) eq 'ARRAY') );\r
+        }\r
+        else {\r
+            $pod_parser->parse_from_file($_, $output);\r
+            ++$num_inputs;\r
+        }\r
+    }\r
+    $pod_parser->parse_from_file('-')  unless ($num_inputs > 0);\r
+}\r
+\r
+#############################################################################\r
+\r
+=head1 PRIVATE METHODS AND DATA\r
+\r
+B<Pod::Select> makes uses a number of internal methods and data fields\r
+which clients should not need to see or use. For the sake of avoiding\r
+name collisions with client data and methods, these methods and fields\r
+are briefly discussed here. Determined hackers may obtain further\r
+information about them by reading the B<Pod::Select> source code.\r
+\r
+Private data fields are stored in the hash-object whose reference is\r
+returned by the B<new()> constructor for this class. The names of all\r
+private methods and data-fields used by B<Pod::Select> begin with a\r
+prefix of "_" and match the regular expression C</^_\w+$/>.\r
+\r
+=cut\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=begin _PRIVATE_\r
+\r
+=head1 B<_compile_section_spec()>\r
+\r
+            $listref = $parser->_compile_section_spec($section_spec);\r
+\r
+This function (note it is a function and I<not> a method) takes a\r
+section specification (as described in L<"SECTION SPECIFICATIONS">)\r
+given in C<$section_sepc>, and compiles it into a list of regular\r
+expressions. If C<$section_spec> has no syntax errors, then a reference\r
+to the list (array) of corresponding regular expressions is returned;\r
+otherwise C<undef> is returned and an error message is printed (using\r
+B<carp>) for each invalid regex.\r
+\r
+=end _PRIVATE_\r
+\r
+=cut\r
+\r
+sub _compile_section_spec {\r
+    my ($section_spec) = @_;\r
+    my (@regexs, $negated);\r
+\r
+    ## Compile the spec into a list of regexs\r
+    local $_ = $section_spec;\r
+    s{\\\\}{\001}g;  ## handle escaped backward slashes\r
+    s{\\/}{\002}g;   ## handle escaped forward slashes\r
+\r
+    ## Parse the regexs for the heading titles\r
+    @regexs = split(/\//, $_, $MAX_HEADING_LEVEL);\r
+\r
+    ## Set default regex for ommitted levels\r
+    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {\r
+        $regexs[$i]  = '.*'  unless ((defined $regexs[$i])\r
+                                     && (length $regexs[$i]));\r
+    }\r
+    ## Modify the regexs as needed and validate their syntax\r
+    my $bad_regexs = 0;\r
+    for (@regexs) {\r
+        $_ .= '.+'  if ($_ eq '!');\r
+        s{\001}{\\\\}g;       ## restore escaped backward slashes\r
+        s{\002}{\\/}g;        ## restore escaped forward slashes\r
+        $negated = s/^\!//;   ## check for negation\r
+        eval "m{$_}";         ## check regex syntax\r
+        if ($@) {\r
+            ++$bad_regexs;\r
+            carp qq{Bad regular expression /$_/ in "$section_spec": $@\n};\r
+        }\r
+        else {\r
+            ## Add the forward and rear anchors (and put the negator back)\r
+            $_ = '^' . $_  unless (/^\^/);\r
+            $_ = $_ . '$'  unless (/\$$/);\r
+            $_ = '!' . $_  if ($negated);\r
+        }\r
+    }\r
+    return  (! $bad_regexs) ? [ @regexs ] : undef;\r
+}\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=begin _PRIVATE_\r
+\r
+=head2 $self->{_SECTION_HEADINGS}\r
+\r
+A reference to an array of the current section heading titles for each\r
+heading level (note that the first heading level title is at index 0).\r
+\r
+=end _PRIVATE_\r
+\r
+=cut\r
+\r
+##---------------------------------------------------------------------------\r
+\r
+=begin _PRIVATE_\r
+\r
+=head2 $self->{_SELECTED_SECTIONS}\r
+\r
+A reference to an array of references to arrays. Each subarray is a list\r
+of anchored regular expressions (preceded by a "!" if the expression is to\r
+be negated). The index of the expression in the subarray should correspond\r
+to the index of the heading title in C<$self-E<gt>{_SECTION_HEADINGS}>\r
+that it is to be matched against.\r
+\r
+=end _PRIVATE_\r
+\r
+=cut\r
+\r
+#############################################################################\r
+\r
+=head1 SEE ALSO\r
+\r
+L<Pod::Parser>\r
+\r
+=head1 AUTHOR\r
+\r
+Please report bugs using L<http://rt.cpan.org>.\r
+\r
+Brad Appleton E<lt>bradapp@enteract.comE<gt>\r
+\r
+Based on code for B<pod2text> written by\r
+Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>\r
+\r
+B<Pod::Select> is part of the L<Pod::Parser> distribution.\r
+\r
+=cut\r
+\r
+1;\r
+# vim: ts=4 sw=4 et\r