xref: /openbsd-src/gnu/usr.bin/perl/cpan/Pod-Usage/t/inc/Pod/Select.pm (revision 256a93a44f36679bee503f12e49566c2183f6181)
15759b3d2Safresh1#############################################################################
25759b3d2Safresh1# Pod/Select.pm -- function to select portions of POD docs
35759b3d2Safresh1#
45759b3d2Safresh1# Copyright (C) 1996-2000 by Bradford Appleton. All rights reserved.
55759b3d2Safresh1# This file is part of "PodParser". PodParser is free software;
65759b3d2Safresh1# you can redistribute it and/or modify it under the same terms
75759b3d2Safresh1# as Perl itself.
85759b3d2Safresh1#############################################################################
95759b3d2Safresh1
105759b3d2Safresh1package Pod::Select;
115759b3d2Safresh1use strict;
12*256a93a4Safresh1use warnings;
135759b3d2Safresh1
145759b3d2Safresh1use vars qw($VERSION @ISA @EXPORT $MAX_HEADING_LEVEL %myData @section_headings @selected_sections);
155759b3d2Safresh1$VERSION = '1.60'; ## Current version of this package
165759b3d2Safresh1require  5.005;    ## requires this Perl version or later
175759b3d2Safresh1
185759b3d2Safresh1#############################################################################
195759b3d2Safresh1
205759b3d2Safresh1=head1 NAME
215759b3d2Safresh1
225759b3d2Safresh1Pod::Select, podselect() - extract selected sections of POD from input
235759b3d2Safresh1
245759b3d2Safresh1=head1 SYNOPSIS
255759b3d2Safresh1
265759b3d2Safresh1    use Pod::Select;
275759b3d2Safresh1
285759b3d2Safresh1    ## Select all the POD sections for each file in @filelist
295759b3d2Safresh1    ## and print the result on standard output.
305759b3d2Safresh1    podselect(@filelist);
315759b3d2Safresh1
325759b3d2Safresh1    ## Same as above, but write to tmp.out
335759b3d2Safresh1    podselect({-output => "tmp.out"}, @filelist):
345759b3d2Safresh1
355759b3d2Safresh1    ## Select from the given filelist, only those POD sections that are
365759b3d2Safresh1    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
375759b3d2Safresh1    podselect({-sections => ["NAME|SYNOPSIS", "OPTIONS"]}, @filelist):
385759b3d2Safresh1
395759b3d2Safresh1    ## Select the "DESCRIPTION" section of the PODs from STDIN and write
405759b3d2Safresh1    ## the result to STDERR.
415759b3d2Safresh1    podselect({-output => ">&STDERR", -sections => ["DESCRIPTION"]}, \*STDIN);
425759b3d2Safresh1
435759b3d2Safresh1or
445759b3d2Safresh1
455759b3d2Safresh1    use Pod::Select;
465759b3d2Safresh1
475759b3d2Safresh1    ## Create a parser object for selecting POD sections from the input
48*256a93a4Safresh1    $parser = Pod::Select->new();
495759b3d2Safresh1
505759b3d2Safresh1    ## Select all the POD sections for each file in @filelist
515759b3d2Safresh1    ## and print the result to tmp.out.
525759b3d2Safresh1    $parser->parse_from_file("<&STDIN", "tmp.out");
535759b3d2Safresh1
545759b3d2Safresh1    ## Select from the given filelist, only those POD sections that are
555759b3d2Safresh1    ## within a 1st level section named any of: NAME, SYNOPSIS, OPTIONS.
565759b3d2Safresh1    $parser->select("NAME|SYNOPSIS", "OPTIONS");
575759b3d2Safresh1    for (@filelist) { $parser->parse_from_file($_); }
585759b3d2Safresh1
595759b3d2Safresh1    ## Select the "DESCRIPTION" and "SEE ALSO" sections of the PODs from
605759b3d2Safresh1    ## STDIN and write the result to STDERR.
615759b3d2Safresh1    $parser->select("DESCRIPTION");
625759b3d2Safresh1    $parser->add_selection("SEE ALSO");
635759b3d2Safresh1    $parser->parse_from_filehandle(\*STDIN, \*STDERR);
645759b3d2Safresh1
655759b3d2Safresh1=head1 REQUIRES
665759b3d2Safresh1
675759b3d2Safresh1perl5.005, Pod::Parser, Exporter, Carp
685759b3d2Safresh1
695759b3d2Safresh1=head1 EXPORTS
705759b3d2Safresh1
715759b3d2Safresh1podselect()
725759b3d2Safresh1
735759b3d2Safresh1=head1 DESCRIPTION
745759b3d2Safresh1
755759b3d2Safresh1B<podselect()> is a function which will extract specified sections of
765759b3d2Safresh1pod documentation from an input stream. This ability is provided by the
775759b3d2Safresh1B<Pod::Select> module which is a subclass of B<Pod::Parser>.
785759b3d2Safresh1B<Pod::Select> provides a method named B<select()> to specify the set of
795759b3d2Safresh1POD sections to select for processing/printing. B<podselect()> merely
805759b3d2Safresh1creates a B<Pod::Select> object and then invokes the B<podselect()>
815759b3d2Safresh1followed by B<parse_from_file()>.
825759b3d2Safresh1
835759b3d2Safresh1=head1 SECTION SPECIFICATIONS
845759b3d2Safresh1
855759b3d2Safresh1B<podselect()> and B<Pod::Select::select()> may be given one or more
865759b3d2Safresh1"section specifications" to restrict the text processed to only the
875759b3d2Safresh1desired set of sections and their corresponding subsections.  A section
885759b3d2Safresh1specification is a string containing one or more Perl-style regular
895759b3d2Safresh1expressions separated by forward slashes ("/").  If you need to use a
905759b3d2Safresh1forward slash literally within a section title you can escape it with a
915759b3d2Safresh1backslash ("\/").
925759b3d2Safresh1
935759b3d2Safresh1The formal syntax of a section specification is:
945759b3d2Safresh1
955759b3d2Safresh1=over 4
965759b3d2Safresh1
975759b3d2Safresh1=item *
985759b3d2Safresh1
995759b3d2Safresh1I<head1-title-regex>/I<head2-title-regex>/...
1005759b3d2Safresh1
1015759b3d2Safresh1=back
1025759b3d2Safresh1
1035759b3d2Safresh1Any omitted or empty regular expressions will default to ".*".
1045759b3d2Safresh1Please note that each regular expression given is implicitly
1055759b3d2Safresh1anchored by adding "^" and "$" to the beginning and end.  Also, if a
1065759b3d2Safresh1given regular expression starts with a "!" character, then the
1075759b3d2Safresh1expression is I<negated> (so C<!foo> would match anything I<except>
1085759b3d2Safresh1C<foo>).
1095759b3d2Safresh1
1105759b3d2Safresh1Some example section specifications follow.
1115759b3d2Safresh1
1125759b3d2Safresh1=over 4
1135759b3d2Safresh1
1145759b3d2Safresh1=item *
1155759b3d2Safresh1
1165759b3d2Safresh1Match the C<NAME> and C<SYNOPSIS> sections and all of their subsections:
1175759b3d2Safresh1
1185759b3d2Safresh1C<NAME|SYNOPSIS>
1195759b3d2Safresh1
1205759b3d2Safresh1=item *
1215759b3d2Safresh1
1225759b3d2Safresh1Match only the C<Question> and C<Answer> subsections of the C<DESCRIPTION>
1235759b3d2Safresh1section:
1245759b3d2Safresh1
1255759b3d2Safresh1C<DESCRIPTION/Question|Answer>
1265759b3d2Safresh1
1275759b3d2Safresh1=item *
1285759b3d2Safresh1
1295759b3d2Safresh1Match the C<Comments> subsection of I<all> sections:
1305759b3d2Safresh1
1315759b3d2Safresh1C</Comments>
1325759b3d2Safresh1
1335759b3d2Safresh1=item *
1345759b3d2Safresh1
1355759b3d2Safresh1Match all subsections of C<DESCRIPTION> I<except> for C<Comments>:
1365759b3d2Safresh1
1375759b3d2Safresh1C<DESCRIPTION/!Comments>
1385759b3d2Safresh1
1395759b3d2Safresh1=item *
1405759b3d2Safresh1
1415759b3d2Safresh1Match the C<DESCRIPTION> section but do I<not> match any of its subsections:
1425759b3d2Safresh1
1435759b3d2Safresh1C<DESCRIPTION/!.+>
1445759b3d2Safresh1
1455759b3d2Safresh1=item *
1465759b3d2Safresh1
1475759b3d2Safresh1Match all top level sections but none of their subsections:
1485759b3d2Safresh1
1495759b3d2Safresh1C</!.+>
1505759b3d2Safresh1
1515759b3d2Safresh1=back
1525759b3d2Safresh1
1535759b3d2Safresh1=begin _NOT_IMPLEMENTED_
1545759b3d2Safresh1
1555759b3d2Safresh1=head1 RANGE SPECIFICATIONS
1565759b3d2Safresh1
1575759b3d2Safresh1B<podselect()> and B<Pod::Select::select()> may be given one or more
1585759b3d2Safresh1"range specifications" to restrict the text processed to only the
1595759b3d2Safresh1desired ranges of paragraphs in the desired set of sections. A range
1605759b3d2Safresh1specification is a string containing a single Perl-style regular
1615759b3d2Safresh1expression (a regex), or else two Perl-style regular expressions
1625759b3d2Safresh1(regexs) separated by a ".." (Perl's "range" operator is "..").
1635759b3d2Safresh1The regexs in a range specification are delimited by forward slashes
1645759b3d2Safresh1("/").  If you need to use a forward slash literally within a regex you
1655759b3d2Safresh1can escape it with a backslash ("\/").
1665759b3d2Safresh1
1675759b3d2Safresh1The formal syntax of a range specification is:
1685759b3d2Safresh1
1695759b3d2Safresh1=over 4
1705759b3d2Safresh1
1715759b3d2Safresh1=item *
1725759b3d2Safresh1
1735759b3d2Safresh1/I<start-range-regex>/[../I<end-range-regex>/]
1745759b3d2Safresh1
1755759b3d2Safresh1=back
1765759b3d2Safresh1
1775759b3d2Safresh1Where each the item inside square brackets (the ".." followed by the
1785759b3d2Safresh1end-range-regex) is optional. Each "range-regex" is of the form:
1795759b3d2Safresh1
1805759b3d2Safresh1    =cmd-expr text-expr
1815759b3d2Safresh1
1825759b3d2Safresh1Where I<cmd-expr> is intended to match the name of one or more POD
1835759b3d2Safresh1commands, and I<text-expr> is intended to match the paragraph text for
1845759b3d2Safresh1the command. If a range-regex is supposed to match a POD command, then
1855759b3d2Safresh1the first character of the regex (the one after the initial '/')
1865759b3d2Safresh1absolutely I<must> be a single '=' character; it may not be anything
1875759b3d2Safresh1else (not even a regex meta-character) if it is supposed to match
1885759b3d2Safresh1against the name of a POD command.
1895759b3d2Safresh1
1905759b3d2Safresh1If no I<=cmd-expr> is given then the text-expr will be matched against
1915759b3d2Safresh1plain textblocks unless it is preceded by a space, in which case it is
1925759b3d2Safresh1matched against verbatim text-blocks. If no I<text-expr> is given then
1935759b3d2Safresh1only the command-portion of the paragraph is matched against.
1945759b3d2Safresh1
1955759b3d2Safresh1Note that these two expressions are each implicitly anchored. This
1965759b3d2Safresh1means that when matching against the command-name, there will be an
1975759b3d2Safresh1implicit '^' and '$' around the given I<=cmd-expr>; and when matching
1985759b3d2Safresh1against the paragraph text there will be an implicit '\A' and '\Z'
1995759b3d2Safresh1around the given I<text-expr>.
2005759b3d2Safresh1
2015759b3d2Safresh1Unlike with section-specs, the '!' character does I<not> have any special
2025759b3d2Safresh1meaning (negation or otherwise) at the beginning of a range-spec!
2035759b3d2Safresh1
2045759b3d2Safresh1Some example range specifications follow.
2055759b3d2Safresh1
2065759b3d2Safresh1=over 4
2075759b3d2Safresh1
2085759b3d2Safresh1=item
2095759b3d2Safresh1Match all C<=for html> paragraphs:
2105759b3d2Safresh1
2115759b3d2Safresh1C</=for html/>
2125759b3d2Safresh1
2135759b3d2Safresh1=item
2145759b3d2Safresh1Match all paragraphs between C<=begin html> and C<=end html>
2155759b3d2Safresh1(note that this will I<not> work correctly if such sections
2165759b3d2Safresh1are nested):
2175759b3d2Safresh1
2185759b3d2Safresh1C</=begin html/../=end html/>
2195759b3d2Safresh1
2205759b3d2Safresh1=item
2215759b3d2Safresh1Match all paragraphs between the given C<=item> name until the end of the
2225759b3d2Safresh1current section:
2235759b3d2Safresh1
2245759b3d2Safresh1C</=item mine/../=head\d/>
2255759b3d2Safresh1
2265759b3d2Safresh1=item
2275759b3d2Safresh1Match all paragraphs between the given C<=item> until the next item, or
2285759b3d2Safresh1until the end of the itemized list (note that this will I<not> work as
2295759b3d2Safresh1desired if the item contains an itemized list nested within it):
2305759b3d2Safresh1
2315759b3d2Safresh1C</=item mine/../=(item|back)/>
2325759b3d2Safresh1
2335759b3d2Safresh1=back
2345759b3d2Safresh1
2355759b3d2Safresh1=end _NOT_IMPLEMENTED_
2365759b3d2Safresh1
2375759b3d2Safresh1=cut
2385759b3d2Safresh1
2395759b3d2Safresh1#############################################################################
2405759b3d2Safresh1
2415759b3d2Safresh1#use diagnostics;
2425759b3d2Safresh1use Carp;
2435759b3d2Safresh1use Pod::Parser 1.04;
2445759b3d2Safresh1
2455759b3d2Safresh1@ISA = qw(Pod::Parser);
2465759b3d2Safresh1@EXPORT = qw(&podselect);
2475759b3d2Safresh1
2485759b3d2Safresh1## Maximum number of heading levels supported for '=headN' directives
2495759b3d2Safresh1*MAX_HEADING_LEVEL = \3;
2505759b3d2Safresh1
2515759b3d2Safresh1#############################################################################
2525759b3d2Safresh1
2535759b3d2Safresh1=head1 OBJECT METHODS
2545759b3d2Safresh1
2555759b3d2Safresh1The following methods are provided in this module. Each one takes a
2565759b3d2Safresh1reference to the object itself as an implicit first parameter.
2575759b3d2Safresh1
2585759b3d2Safresh1=cut
2595759b3d2Safresh1
2605759b3d2Safresh1##---------------------------------------------------------------------------
2615759b3d2Safresh1
2625759b3d2Safresh1## =begin _PRIVATE_
2635759b3d2Safresh1##
2645759b3d2Safresh1## =head1 B<_init_headings()>
2655759b3d2Safresh1##
2665759b3d2Safresh1## Initialize the current set of active section headings.
2675759b3d2Safresh1##
2685759b3d2Safresh1## =cut
2695759b3d2Safresh1##
2705759b3d2Safresh1## =end _PRIVATE_
2715759b3d2Safresh1
2725759b3d2Safresh1sub _init_headings {
2735759b3d2Safresh1    my $self = shift;
2745759b3d2Safresh1    local *myData = $self;
2755759b3d2Safresh1
2765759b3d2Safresh1    ## Initialize current section heading titles if necessary
2775759b3d2Safresh1    unless (defined $myData{_SECTION_HEADINGS}) {
2785759b3d2Safresh1        local *section_headings = $myData{_SECTION_HEADINGS} = [];
2795759b3d2Safresh1        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
2805759b3d2Safresh1            $section_headings[$i] = '';
2815759b3d2Safresh1        }
2825759b3d2Safresh1    }
2835759b3d2Safresh1}
2845759b3d2Safresh1
2855759b3d2Safresh1##---------------------------------------------------------------------------
2865759b3d2Safresh1
2875759b3d2Safresh1=head1 B<curr_headings()>
2885759b3d2Safresh1
2895759b3d2Safresh1            ($head1, $head2, $head3, ...) = $parser->curr_headings();
2905759b3d2Safresh1            $head1 = $parser->curr_headings(1);
2915759b3d2Safresh1
2925759b3d2Safresh1This method returns a list of the currently active section headings and
2935759b3d2Safresh1subheadings in the document being parsed. The list of headings returned
2945759b3d2Safresh1corresponds to the most recently parsed paragraph of the input.
2955759b3d2Safresh1
2965759b3d2Safresh1If an argument is given, it must correspond to the desired section
2975759b3d2Safresh1heading number, in which case only the specified section heading is
2985759b3d2Safresh1returned. If there is no current section heading at the specified
2995759b3d2Safresh1level, then C<undef> is returned.
3005759b3d2Safresh1
3015759b3d2Safresh1=cut
3025759b3d2Safresh1
3035759b3d2Safresh1sub curr_headings {
3045759b3d2Safresh1    my $self = shift;
3055759b3d2Safresh1    $self->_init_headings()  unless (defined $self->{_SECTION_HEADINGS});
3065759b3d2Safresh1    my @headings = @{ $self->{_SECTION_HEADINGS} };
3075759b3d2Safresh1    return (@_ > 0  and  $_[0] =~ /^\d+$/) ? $headings[$_[0] - 1] : @headings;
3085759b3d2Safresh1}
3095759b3d2Safresh1
3105759b3d2Safresh1##---------------------------------------------------------------------------
3115759b3d2Safresh1
3125759b3d2Safresh1=head1 B<select()>
3135759b3d2Safresh1
3145759b3d2Safresh1            $parser->select($section_spec1,$section_spec2,...);
3155759b3d2Safresh1
3165759b3d2Safresh1This method is used to select the particular sections and subsections of
3175759b3d2Safresh1POD documentation that are to be printed and/or processed. The existing
3185759b3d2Safresh1set of selected sections is I<replaced> with the given set of sections.
3195759b3d2Safresh1See B<add_selection()> for adding to the current set of selected
3205759b3d2Safresh1sections.
3215759b3d2Safresh1
3225759b3d2Safresh1Each of the C<$section_spec> arguments should be a section specification
3235759b3d2Safresh1as described in L<"SECTION SPECIFICATIONS">.  The section specifications
3245759b3d2Safresh1are parsed by this method and the resulting regular expressions are
3255759b3d2Safresh1stored in the invoking object.
3265759b3d2Safresh1
3275759b3d2Safresh1If no C<$section_spec> arguments are given, then the existing set of
3285759b3d2Safresh1selected sections is cleared out (which means C<all> sections will be
3295759b3d2Safresh1processed).
3305759b3d2Safresh1
3315759b3d2Safresh1This method should I<not> normally be overridden by subclasses.
3325759b3d2Safresh1
3335759b3d2Safresh1=cut
3345759b3d2Safresh1
3355759b3d2Safresh1sub select {
3365759b3d2Safresh1    my ($self, @sections) = @_;
3375759b3d2Safresh1    local *myData = $self;
3385759b3d2Safresh1    local $_;
3395759b3d2Safresh1
3405759b3d2Safresh1### NEED TO DISCERN A SECTION-SPEC FROM A RANGE-SPEC (look for m{^/.+/$}?)
3415759b3d2Safresh1
3425759b3d2Safresh1    ##---------------------------------------------------------------------
3435759b3d2Safresh1    ## The following is a blatant hack for backward compatibility, and for
3445759b3d2Safresh1    ## implementing add_selection(). If the *first* *argument* is the
3455759b3d2Safresh1    ## string "+", then the remaining section specifications are *added*
3465759b3d2Safresh1    ## to the current set of selections; otherwise the given section
3475759b3d2Safresh1    ## specifications will *replace* the current set of selections.
3485759b3d2Safresh1    ##
3495759b3d2Safresh1    ## This should probably be fixed someday, but for the present time,
3505759b3d2Safresh1    ## it seems incredibly unlikely that "+" would ever correspond to
3515759b3d2Safresh1    ## a legitimate section heading
3525759b3d2Safresh1    ##---------------------------------------------------------------------
3535759b3d2Safresh1    my $add = ($sections[0] eq '+') ? shift(@sections) : '';
3545759b3d2Safresh1
3555759b3d2Safresh1    ## Reset the set of sections to use
3565759b3d2Safresh1    unless (@sections) {
3575759b3d2Safresh1        delete $myData{_SELECTED_SECTIONS}  unless ($add);
3585759b3d2Safresh1        return;
3595759b3d2Safresh1    }
3605759b3d2Safresh1    $myData{_SELECTED_SECTIONS} = []
3615759b3d2Safresh1        unless ($add  &&  exists $myData{_SELECTED_SECTIONS});
3625759b3d2Safresh1    local *selected_sections = $myData{_SELECTED_SECTIONS};
3635759b3d2Safresh1
3645759b3d2Safresh1    ## Compile each spec
3655759b3d2Safresh1    for my $spec (@sections) {
3665759b3d2Safresh1        if ( defined($_ = _compile_section_spec($spec)) ) {
3675759b3d2Safresh1            ## Store them in our sections array
3685759b3d2Safresh1            push(@selected_sections, $_);
3695759b3d2Safresh1        }
3705759b3d2Safresh1        else {
3715759b3d2Safresh1            carp qq{Ignoring section spec "$spec"!\n};
3725759b3d2Safresh1        }
3735759b3d2Safresh1    }
3745759b3d2Safresh1}
3755759b3d2Safresh1
3765759b3d2Safresh1##---------------------------------------------------------------------------
3775759b3d2Safresh1
3785759b3d2Safresh1=head1 B<add_selection()>
3795759b3d2Safresh1
3805759b3d2Safresh1            $parser->add_selection($section_spec1,$section_spec2,...);
3815759b3d2Safresh1
3825759b3d2Safresh1This method is used to add to the currently selected sections and
3835759b3d2Safresh1subsections of POD documentation that are to be printed and/or
3845759b3d2Safresh1processed. See <select()> for replacing the currently selected sections.
3855759b3d2Safresh1
3865759b3d2Safresh1Each of the C<$section_spec> arguments should be a section specification
3875759b3d2Safresh1as described in L<"SECTION SPECIFICATIONS">. The section specifications
3885759b3d2Safresh1are parsed by this method and the resulting regular expressions are
3895759b3d2Safresh1stored in the invoking object.
3905759b3d2Safresh1
3915759b3d2Safresh1This method should I<not> normally be overridden by subclasses.
3925759b3d2Safresh1
3935759b3d2Safresh1=cut
3945759b3d2Safresh1
3955759b3d2Safresh1sub add_selection {
3965759b3d2Safresh1    my $self = shift;
3975759b3d2Safresh1    return $self->select('+', @_);
3985759b3d2Safresh1}
3995759b3d2Safresh1
4005759b3d2Safresh1##---------------------------------------------------------------------------
4015759b3d2Safresh1
4025759b3d2Safresh1=head1 B<clear_selections()>
4035759b3d2Safresh1
4045759b3d2Safresh1            $parser->clear_selections();
4055759b3d2Safresh1
4065759b3d2Safresh1This method takes no arguments, it has the exact same effect as invoking
4075759b3d2Safresh1<select()> with no arguments.
4085759b3d2Safresh1
4095759b3d2Safresh1=cut
4105759b3d2Safresh1
4115759b3d2Safresh1sub clear_selections {
4125759b3d2Safresh1    my $self = shift;
4135759b3d2Safresh1    return $self->select();
4145759b3d2Safresh1}
4155759b3d2Safresh1
4165759b3d2Safresh1##---------------------------------------------------------------------------
4175759b3d2Safresh1
4185759b3d2Safresh1=head1 B<match_section()>
4195759b3d2Safresh1
4205759b3d2Safresh1            $boolean = $parser->match_section($heading1,$heading2,...);
4215759b3d2Safresh1
4225759b3d2Safresh1Returns a value of true if the given section and subsection heading
4235759b3d2Safresh1titles match any of the currently selected section specifications in
4245759b3d2Safresh1effect from prior calls to B<select()> and B<add_selection()> (or if
4255759b3d2Safresh1there are no explicitly selected/deselected sections).
4265759b3d2Safresh1
4275759b3d2Safresh1The arguments C<$heading1>, C<$heading2>, etc. are the heading titles of
4285759b3d2Safresh1the corresponding sections, subsections, etc. to try and match.  If
4295759b3d2Safresh1C<$headingN> is omitted then it defaults to the current corresponding
4305759b3d2Safresh1section heading title in the input.
4315759b3d2Safresh1
4325759b3d2Safresh1This method should I<not> normally be overridden by subclasses.
4335759b3d2Safresh1
4345759b3d2Safresh1=cut
4355759b3d2Safresh1
4365759b3d2Safresh1sub match_section {
4375759b3d2Safresh1    my $self = shift;
4385759b3d2Safresh1    my (@headings) = @_;
4395759b3d2Safresh1    local *myData = $self;
4405759b3d2Safresh1
4415759b3d2Safresh1    ## Return true if no restrictions were explicitly specified
4425759b3d2Safresh1    my $selections = (exists $myData{_SELECTED_SECTIONS})
4435759b3d2Safresh1                       ?  $myData{_SELECTED_SECTIONS}  :  undef;
4445759b3d2Safresh1    return  1  unless ((defined $selections) && @{$selections});
4455759b3d2Safresh1
4465759b3d2Safresh1    ## Default any unspecified sections to the current one
4475759b3d2Safresh1    my @current_headings = $self->curr_headings();
4485759b3d2Safresh1    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
4495759b3d2Safresh1        (defined $headings[$i])  or  $headings[$i] = $current_headings[$i];
4505759b3d2Safresh1    }
4515759b3d2Safresh1
4525759b3d2Safresh1    ## Look for a match against the specified section expressions
4535759b3d2Safresh1    for my $section_spec ( @{$selections} ) {
4545759b3d2Safresh1        ##------------------------------------------------------
4555759b3d2Safresh1        ## Each portion of this spec must match in order for
4565759b3d2Safresh1        ## the spec to be matched. So we will start with a
4575759b3d2Safresh1        ## match-value of 'true' and logically 'and' it with
4585759b3d2Safresh1        ## the results of matching a given element of the spec.
4595759b3d2Safresh1        ##------------------------------------------------------
4605759b3d2Safresh1        my $match = 1;
4615759b3d2Safresh1        for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
4625759b3d2Safresh1            my $regex   = $section_spec->[$i];
4635759b3d2Safresh1            my $negated = ($regex =~ s/^\!//);
4645759b3d2Safresh1            $match  &= ($negated ? ($headings[$i] !~ /${regex}/)
4655759b3d2Safresh1                                 : ($headings[$i] =~ /${regex}/));
4665759b3d2Safresh1            last unless ($match);
4675759b3d2Safresh1        }
4685759b3d2Safresh1        return  1  if ($match);
4695759b3d2Safresh1    }
4705759b3d2Safresh1    return  0;  ## no match
4715759b3d2Safresh1}
4725759b3d2Safresh1
4735759b3d2Safresh1##---------------------------------------------------------------------------
4745759b3d2Safresh1
4755759b3d2Safresh1=head1 B<is_selected()>
4765759b3d2Safresh1
4775759b3d2Safresh1            $boolean = $parser->is_selected($paragraph);
4785759b3d2Safresh1
4795759b3d2Safresh1This method is used to determine if the block of text given in
4805759b3d2Safresh1C<$paragraph> falls within the currently selected set of POD sections
4815759b3d2Safresh1and subsections to be printed or processed. This method is also
4825759b3d2Safresh1responsible for keeping track of the current input section and
4835759b3d2Safresh1subsections. It is assumed that C<$paragraph> is the most recently read
4845759b3d2Safresh1(but not yet processed) input paragraph.
4855759b3d2Safresh1
4865759b3d2Safresh1The value returned will be true if the C<$paragraph> and the rest of the
4875759b3d2Safresh1text in the same section as C<$paragraph> should be selected (included)
4885759b3d2Safresh1for processing; otherwise a false value is returned.
4895759b3d2Safresh1
4905759b3d2Safresh1=cut
4915759b3d2Safresh1
4925759b3d2Safresh1sub is_selected {
4935759b3d2Safresh1    my ($self, $paragraph) = @_;
4945759b3d2Safresh1    local $_;
4955759b3d2Safresh1    local *myData = $self;
4965759b3d2Safresh1
4975759b3d2Safresh1    $self->_init_headings()  unless (defined $myData{_SECTION_HEADINGS});
4985759b3d2Safresh1
4995759b3d2Safresh1    ## Keep track of current sections levels and headings
5005759b3d2Safresh1    $_ = $paragraph;
5015759b3d2Safresh1    if (/^=((?:sub)*)(?:head(?:ing)?|sec(?:tion)?)(\d*)\s+(.*?)\s*$/)
5025759b3d2Safresh1    {
5035759b3d2Safresh1        ## This is a section heading command
5045759b3d2Safresh1        my ($level, $heading) = ($2, $3);
5055759b3d2Safresh1        $level = 1 + (length($1) / 3)  if ((! length $level) || (length $1));
5065759b3d2Safresh1        ## Reset the current section heading at this level
5075759b3d2Safresh1        $myData{_SECTION_HEADINGS}->[$level - 1] = $heading;
5085759b3d2Safresh1        ## Reset subsection headings of this one to empty
5095759b3d2Safresh1        for (my $i = $level; $i < $MAX_HEADING_LEVEL; ++$i) {
5105759b3d2Safresh1            $myData{_SECTION_HEADINGS}->[$i] = '';
5115759b3d2Safresh1        }
5125759b3d2Safresh1    }
5135759b3d2Safresh1
5145759b3d2Safresh1    return  $self->match_section();
5155759b3d2Safresh1}
5165759b3d2Safresh1
5175759b3d2Safresh1#############################################################################
5185759b3d2Safresh1
5195759b3d2Safresh1=head1 EXPORTED FUNCTIONS
5205759b3d2Safresh1
5215759b3d2Safresh1The following functions are exported by this module. Please note that
5225759b3d2Safresh1these are functions (not methods) and therefore C<do not> take an
5235759b3d2Safresh1implicit first argument.
5245759b3d2Safresh1
5255759b3d2Safresh1=cut
5265759b3d2Safresh1
5275759b3d2Safresh1##---------------------------------------------------------------------------
5285759b3d2Safresh1
5295759b3d2Safresh1=head1 B<podselect()>
5305759b3d2Safresh1
5315759b3d2Safresh1            podselect(\%options,@filelist);
5325759b3d2Safresh1
5335759b3d2Safresh1B<podselect> will print the raw (untranslated) POD paragraphs of all
5345759b3d2Safresh1POD sections in the given input files specified by C<@filelist>
5355759b3d2Safresh1according to the given options.
5365759b3d2Safresh1
5375759b3d2Safresh1If any argument to B<podselect> is a reference to a hash
5385759b3d2Safresh1(associative array) then the values with the following keys are
5395759b3d2Safresh1processed as follows:
5405759b3d2Safresh1
5415759b3d2Safresh1=over 4
5425759b3d2Safresh1
5435759b3d2Safresh1=item B<-output>
5445759b3d2Safresh1
5455759b3d2Safresh1A string corresponding to the desired output file (or ">&STDOUT"
5465759b3d2Safresh1or ">&STDERR"). The default is to use standard output.
5475759b3d2Safresh1
5485759b3d2Safresh1=item B<-sections>
5495759b3d2Safresh1
5505759b3d2Safresh1A reference to an array of sections specifications (as described in
5515759b3d2Safresh1L<"SECTION SPECIFICATIONS">) which indicate the desired set of POD
5525759b3d2Safresh1sections and subsections to be selected from input. If no section
5535759b3d2Safresh1specifications are given, then all sections of the PODs are used.
5545759b3d2Safresh1
5555759b3d2Safresh1=begin _NOT_IMPLEMENTED_
5565759b3d2Safresh1
5575759b3d2Safresh1=item B<-ranges>
5585759b3d2Safresh1
5595759b3d2Safresh1A reference to an array of range specifications (as described in
5605759b3d2Safresh1L<"RANGE SPECIFICATIONS">) which indicate the desired range of POD
5615759b3d2Safresh1paragraphs to be selected from the desired input sections. If no range
5625759b3d2Safresh1specifications are given, then all paragraphs of the desired sections
5635759b3d2Safresh1are used.
5645759b3d2Safresh1
5655759b3d2Safresh1=end _NOT_IMPLEMENTED_
5665759b3d2Safresh1
5675759b3d2Safresh1=back
5685759b3d2Safresh1
5695759b3d2Safresh1All other arguments should correspond to the names of input files
5705759b3d2Safresh1containing POD sections. A file name of "-" or "<&STDIN" will
5715759b3d2Safresh1be interpreted to mean standard input (which is the default if no
5725759b3d2Safresh1filenames are given).
5735759b3d2Safresh1
5745759b3d2Safresh1=cut 
5755759b3d2Safresh1
5765759b3d2Safresh1sub podselect {
5775759b3d2Safresh1    my(@argv) = @_;
5785759b3d2Safresh1    my %defaults = ();
579*256a93a4Safresh1    my $pod_parser = Pod::Select->new(%defaults);
5805759b3d2Safresh1    my $num_inputs = 0;
5815759b3d2Safresh1    my $output = '>&STDOUT';
5825759b3d2Safresh1    my %opts;
5835759b3d2Safresh1    local $_;
5845759b3d2Safresh1    for (@argv) {
5855759b3d2Safresh1        if (ref($_)) {
5865759b3d2Safresh1        next unless (ref($_) eq 'HASH');
5875759b3d2Safresh1            %opts = (%defaults, %{$_});
5885759b3d2Safresh1
5895759b3d2Safresh1            ##-------------------------------------------------------------
5905759b3d2Safresh1            ## Need this for backward compatibility since we formerly used
5915759b3d2Safresh1            ## options that were all uppercase words rather than ones that
5925759b3d2Safresh1            ## looked like Unix command-line options.
5935759b3d2Safresh1            ## to be uppercase keywords)
5945759b3d2Safresh1            ##-------------------------------------------------------------
5955759b3d2Safresh1            %opts = map {
5965759b3d2Safresh1                my ($key, $val) = (lc $_, $opts{$_});
5975759b3d2Safresh1                $key =~ s/^(?=\w)/-/;
5985759b3d2Safresh1                $key =~ /^-se[cl]/  and  $key  = '-sections';
5995759b3d2Safresh1                #! $key eq '-range'    and  $key .= 's';
6005759b3d2Safresh1                ($key => $val);
6015759b3d2Safresh1            } (keys %opts);
6025759b3d2Safresh1
6035759b3d2Safresh1            ## Process the options
6045759b3d2Safresh1            (exists $opts{'-output'})  and  $output = $opts{'-output'};
6055759b3d2Safresh1
6065759b3d2Safresh1            ## Select the desired sections
6075759b3d2Safresh1            $pod_parser->select(@{ $opts{'-sections'} })
6085759b3d2Safresh1                if ( (defined $opts{'-sections'})
6095759b3d2Safresh1                     && ((ref $opts{'-sections'}) eq 'ARRAY') );
6105759b3d2Safresh1
6115759b3d2Safresh1            #! ## Select the desired paragraph ranges
6125759b3d2Safresh1            #! $pod_parser->select(@{ $opts{'-ranges'} })
6135759b3d2Safresh1            #!     if ( (defined $opts{'-ranges'})
6145759b3d2Safresh1            #!          && ((ref $opts{'-ranges'}) eq 'ARRAY') );
6155759b3d2Safresh1        }
6165759b3d2Safresh1        else {
6175759b3d2Safresh1            $pod_parser->parse_from_file($_, $output);
6185759b3d2Safresh1            ++$num_inputs;
6195759b3d2Safresh1        }
6205759b3d2Safresh1    }
6215759b3d2Safresh1    $pod_parser->parse_from_file('-')  unless ($num_inputs > 0);
6225759b3d2Safresh1}
6235759b3d2Safresh1
6245759b3d2Safresh1#############################################################################
6255759b3d2Safresh1
6265759b3d2Safresh1=head1 PRIVATE METHODS AND DATA
6275759b3d2Safresh1
6285759b3d2Safresh1B<Pod::Select> makes uses a number of internal methods and data fields
6295759b3d2Safresh1which clients should not need to see or use. For the sake of avoiding
6305759b3d2Safresh1name collisions with client data and methods, these methods and fields
6315759b3d2Safresh1are briefly discussed here. Determined hackers may obtain further
6325759b3d2Safresh1information about them by reading the B<Pod::Select> source code.
6335759b3d2Safresh1
6345759b3d2Safresh1Private data fields are stored in the hash-object whose reference is
6355759b3d2Safresh1returned by the B<new()> constructor for this class. The names of all
6365759b3d2Safresh1private methods and data-fields used by B<Pod::Select> begin with a
6375759b3d2Safresh1prefix of "_" and match the regular expression C</^_\w+$/>.
6385759b3d2Safresh1
6395759b3d2Safresh1=cut
6405759b3d2Safresh1
6415759b3d2Safresh1##---------------------------------------------------------------------------
6425759b3d2Safresh1
6435759b3d2Safresh1=begin _PRIVATE_
6445759b3d2Safresh1
6455759b3d2Safresh1=head1 B<_compile_section_spec()>
6465759b3d2Safresh1
6475759b3d2Safresh1            $listref = $parser->_compile_section_spec($section_spec);
6485759b3d2Safresh1
6495759b3d2Safresh1This function (note it is a function and I<not> a method) takes a
6505759b3d2Safresh1section specification (as described in L<"SECTION SPECIFICATIONS">)
6515759b3d2Safresh1given in C<$section_sepc>, and compiles it into a list of regular
6525759b3d2Safresh1expressions. If C<$section_spec> has no syntax errors, then a reference
6535759b3d2Safresh1to the list (array) of corresponding regular expressions is returned;
6545759b3d2Safresh1otherwise C<undef> is returned and an error message is printed (using
6555759b3d2Safresh1B<carp>) for each invalid regex.
6565759b3d2Safresh1
6575759b3d2Safresh1=end _PRIVATE_
6585759b3d2Safresh1
6595759b3d2Safresh1=cut
6605759b3d2Safresh1
6615759b3d2Safresh1sub _compile_section_spec {
6625759b3d2Safresh1    my ($section_spec) = @_;
6635759b3d2Safresh1    my (@regexs, $negated);
6645759b3d2Safresh1
6655759b3d2Safresh1    ## Compile the spec into a list of regexs
6665759b3d2Safresh1    local $_ = $section_spec;
6675759b3d2Safresh1    s{\\\\}{\001}g;  ## handle escaped backward slashes
6685759b3d2Safresh1    s{\\/}{\002}g;   ## handle escaped forward slashes
6695759b3d2Safresh1
6705759b3d2Safresh1    ## Parse the regexs for the heading titles
6715759b3d2Safresh1    @regexs = split(/\//, $_, $MAX_HEADING_LEVEL);
6725759b3d2Safresh1
6735759b3d2Safresh1    ## Set default regex for ommitted levels
6745759b3d2Safresh1    for (my $i = 0; $i < $MAX_HEADING_LEVEL; ++$i) {
6755759b3d2Safresh1        $regexs[$i]  = '.*'  unless ((defined $regexs[$i])
6765759b3d2Safresh1                                     && (length $regexs[$i]));
6775759b3d2Safresh1    }
6785759b3d2Safresh1    ## Modify the regexs as needed and validate their syntax
6795759b3d2Safresh1    my $bad_regexs = 0;
6805759b3d2Safresh1    for (@regexs) {
6815759b3d2Safresh1        $_ .= '.+'  if ($_ eq '!');
6825759b3d2Safresh1        s{\001}{\\\\}g;       ## restore escaped backward slashes
6835759b3d2Safresh1        s{\002}{\\/}g;        ## restore escaped forward slashes
6845759b3d2Safresh1        $negated = s/^\!//;   ## check for negation
6855759b3d2Safresh1        eval "m{$_}";         ## check regex syntax
6865759b3d2Safresh1        if ($@) {
6875759b3d2Safresh1            ++$bad_regexs;
6885759b3d2Safresh1            carp qq{Bad regular expression /$_/ in "$section_spec": $@\n};
6895759b3d2Safresh1        }
6905759b3d2Safresh1        else {
6915759b3d2Safresh1            ## Add the forward and rear anchors (and put the negator back)
6925759b3d2Safresh1            $_ = '^' . $_  unless (/^\^/);
6935759b3d2Safresh1            $_ = $_ . '$'  unless (/\$$/);
6945759b3d2Safresh1            $_ = '!' . $_  if ($negated);
6955759b3d2Safresh1        }
6965759b3d2Safresh1    }
6975759b3d2Safresh1    return  (! $bad_regexs) ? [ @regexs ] : undef;
6985759b3d2Safresh1}
6995759b3d2Safresh1
7005759b3d2Safresh1##---------------------------------------------------------------------------
7015759b3d2Safresh1
7025759b3d2Safresh1=begin _PRIVATE_
7035759b3d2Safresh1
7045759b3d2Safresh1=head2 $self->{_SECTION_HEADINGS}
7055759b3d2Safresh1
7065759b3d2Safresh1A reference to an array of the current section heading titles for each
7075759b3d2Safresh1heading level (note that the first heading level title is at index 0).
7085759b3d2Safresh1
7095759b3d2Safresh1=end _PRIVATE_
7105759b3d2Safresh1
7115759b3d2Safresh1=cut
7125759b3d2Safresh1
7135759b3d2Safresh1##---------------------------------------------------------------------------
7145759b3d2Safresh1
7155759b3d2Safresh1=begin _PRIVATE_
7165759b3d2Safresh1
7175759b3d2Safresh1=head2 $self->{_SELECTED_SECTIONS}
7185759b3d2Safresh1
7195759b3d2Safresh1A reference to an array of references to arrays. Each subarray is a list
7205759b3d2Safresh1of anchored regular expressions (preceded by a "!" if the expression is to
7215759b3d2Safresh1be negated). The index of the expression in the subarray should correspond
7225759b3d2Safresh1to the index of the heading title in C<$self-E<gt>{_SECTION_HEADINGS}>
7235759b3d2Safresh1that it is to be matched against.
7245759b3d2Safresh1
7255759b3d2Safresh1=end _PRIVATE_
7265759b3d2Safresh1
7275759b3d2Safresh1=cut
7285759b3d2Safresh1
7295759b3d2Safresh1#############################################################################
7305759b3d2Safresh1
7315759b3d2Safresh1=head1 SEE ALSO
7325759b3d2Safresh1
7335759b3d2Safresh1L<Pod::Parser>
7345759b3d2Safresh1
7355759b3d2Safresh1=head1 AUTHOR
7365759b3d2Safresh1
7375759b3d2Safresh1Please report bugs using L<http://rt.cpan.org>.
7385759b3d2Safresh1
7395759b3d2Safresh1Brad Appleton E<lt>bradapp@enteract.comE<gt>
7405759b3d2Safresh1
7415759b3d2Safresh1Based on code for B<pod2text> written by
7425759b3d2Safresh1Tom Christiansen E<lt>tchrist@mox.perl.comE<gt>
7435759b3d2Safresh1
7445759b3d2Safresh1B<Pod::Select> is part of the L<Pod::Parser> distribution.
7455759b3d2Safresh1
7465759b3d2Safresh1=cut
7475759b3d2Safresh1
7485759b3d2Safresh11;
7495759b3d2Safresh1# vim: ts=4 sw=4 et
750