Skip to content

Commit 8046565

Browse files
authored
Add glossary search to Pod::Perldoc
This adds a glossary search in the 'perldoc' program that basically just spits out sections of text from `perldoc perlglossary`. Usage would be like: ```shell $ perldoc -g GlossaryTerm $ perldoc -g BSD $ perldoc -g Unix ```
1 parent 74e5032 commit 8046565

File tree

1 file changed

+100
-5
lines changed

1 file changed

+100
-5
lines changed

lib/Pod/Perldoc.pm

+100-5
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ $Pod2man = "pod2man" . ( $Config{'versiononly'} ? $Config{'version'} : '' );
9191
#
9292
# Option accessors...
9393

94-
foreach my $subname (map "opt_$_", split '', q{mhlDriFfXqnTdULva}) {
94+
foreach my $subname (map "opt_$_", split '', q{mhlDriFfXqnTdULvag}) {
9595
no strict 'refs';
9696
*$subname = do{ use strict 'refs'; sub () { shift->_elem($subname, @_) } };
9797
}
@@ -103,6 +103,7 @@ sub opt_q_with { shift->_elem('opt_q', @_) }
103103
sub opt_d_with { shift->_elem('opt_d', @_) }
104104
sub opt_L_with { shift->_elem('opt_L', @_) }
105105
sub opt_v_with { shift->_elem('opt_v', @_) }
106+
sub opt_g_with { shift->_elem('opt_g', @_) }
106107

107108
sub opt_w_with { # Specify an option for the formatter subclass
108109
my($self, $value) = @_;
@@ -272,6 +273,7 @@ perldoc [options] PageName|ModuleName|ProgramName|URL...
272273
perldoc [options] -f BuiltinFunction
273274
perldoc [options] -q FAQRegex
274275
perldoc [options] -v PerlVariable
276+
perldoc [options] -g GlossaryTerm
275277
276278
Options:
277279
-h Display this help message
@@ -298,6 +300,7 @@ Options:
298300
-f Search Perl built-in functions
299301
-a Search Perl API
300302
-v Search predefined Perl variables
303+
-g Search the glossary
301304
302305
PageName|ModuleName|ProgramName|URL...
303306
is the name of a piece of documentation that you want to look at. You
@@ -313,6 +316,9 @@ BuiltinFunction
313316
FAQRegex
314317
is a regex. Will search perlfaq[1-9] for and extract any
315318
questions that match.
319+
GlossaryTerm
320+
is the name of the glossary item. Will extract subtexts out of items
321+
from 'perlglossary'
316322
317323
Any switches in the PERLDOC environment variable will be used before the
318324
command line arguments. The optional pod index file contains a list of
@@ -404,6 +410,7 @@ Examples:
404410
$program_name -q FAQKeywords
405411
$program_name -v PerlVar
406412
$program_name -a PerlAPI
413+
$program_name -g GlossaryTerm
407414
408415
The -h option prints more help. Also try "$program_name perldoc" to get
409416
acquainted with the system. [Perldoc v$VERSION]
@@ -537,6 +544,7 @@ sub process {
537544
elsif( $self->opt_q) { @pages = ("perlfaq1" .. "perlfaq9") }
538545
elsif( $self->opt_v) { @pages = ("perlvar") }
539546
elsif( $self->opt_a) { @pages = ("perlapi") }
547+
elsif( $self->opt_g) { @pages = ("perlglossary") }
540548
else { @pages = @{$self->{'args'}};
541549
# @pages = __FILE__
542550
# if @pages == 1 and $pages[0] eq 'perldoc';
@@ -821,7 +829,8 @@ sub options_sanity {
821829
$count++ if $self->opt_f;
822830
$count++ if $self->opt_q;
823831
$count++ if $self->opt_a;
824-
$self->usage("Only one of -f or -q or -a") if $count > 1;
832+
$count++ if $self->opt_g;
833+
$self->usage("Only one of -f or -q or -a or -g") if $count > 1;
825834
$self->warn(
826835
"Perldoc is meant for reading one file at a time.\n",
827836
"So these parameters are being ignored: ",
@@ -952,20 +961,23 @@ sub maybe_generate_dynamic_pod {
952961

953962
$self->search_perlfaqs($found_things, \@dynamic_pod) if $self->opt_q;
954963

955-
if( ! $self->opt_f and ! $self->opt_q and ! $self->opt_v and ! $self->opt_a) {
964+
$self->search_perlglossary($found_things, \@dynamic_pod) if $self->opt_g;
965+
966+
if( ! $self->opt_f and ! $self->opt_q and ! $self->opt_v and ! $self->opt_a and ! $self->opt_g) {
956967
DEBUG > 4 and print "That's a non-dynamic pod search.\n";
957968
} elsif ( @dynamic_pod ) {
958969
$self->aside("Hm, I found some Pod from that search!\n");
959970
my ($buffd, $buffer) = $self->new_tempfile('pod', 'dyn');
960-
if ( $] >= 5.008 && $self->opt_L ) {
971+
if ( $] >= 5.008 && ($self->opt_L || $self->opt_g) ) {
972+
# let's make it UTF-8 by default for glossary items too...
961973
binmode($buffd, ":encoding(UTF-8)");
962974
print $buffd "=encoding utf8\n\n";
963975
}
964976

965977
push @{ $self->{'temp_file_list'} }, $buffer;
966978
# I.e., it MIGHT be deleted at the end.
967979

968-
my $in_list = !$self->not_dynamic && $self->opt_f || $self->opt_v || $self->opt_a;
980+
my $in_list = !$self->not_dynamic && $self->opt_f || $self->opt_v || $self->opt_a || $self->opt_g;
969981

970982
print $buffd "=over 8\n\n" if $in_list;
971983
print $buffd @dynamic_pod or $self->die( "Can't print $buffer: $!" );
@@ -1398,6 +1410,89 @@ sub search_perlfunc {
13981410

13991411
#..........................................................................
14001412

1413+
## This is largely cargo-culted from search_perlfunc, culling parts that
1414+
## are of no interest to glossary items. For example, adding translators would
1415+
## need this implemented in target callsites (Currently, I know of no such use for
1416+
## this item). Its arguments are not a regex. We just directly search off
1417+
## =item, so a glossary search for 'signal' would expectedly yield both 'signal'
1418+
## and 'signal handler'
1419+
sub search_perlglossary {
1420+
my($self, $found_things, $pod) = @_;
1421+
1422+
DEBUG > 2 and print "Search: @$found_things\n";
1423+
1424+
my $pglossary = shift @$found_things;
1425+
my $fh = $self->open_fh("<", $pglossary);
1426+
1427+
my $search_re = quotemeta($self->opt_g);
1428+
1429+
DEBUG > 2 and
1430+
print "Going to perlglossary-scan for $search_re in $pglossary\n";
1431+
1432+
my $re = 'DESCRIPTION';
1433+
1434+
# Skip introduction
1435+
local $_;
1436+
while (<$fh>) {
1437+
/^=encoding\s+(\S+)/ && $self->set_encoding($fh, $1);
1438+
last if /^=head1 (?:$re|DESCRIPTION)/;
1439+
}
1440+
1441+
# Look for our glossary item
1442+
my $found = 0;
1443+
my $inlist = 0;
1444+
my @related;
1445+
my $related_re;
1446+
while (<$fh>) { # "The Mothership Connection is here!"
1447+
if ( /^=over/ and not $found ) {
1448+
++$inlist;
1449+
}
1450+
elsif ( /^=back/ and not $found and $inlist ) {
1451+
--$inlist;
1452+
}
1453+
1454+
if ( m/^=item\s+$search_re\b/ and $inlist < 2 ) {
1455+
$found = 1;
1456+
}
1457+
elsif (@related > 1 and /^=item/) {
1458+
$related_re ||= join "|", @related;
1459+
if (m/^=item\s+(?:$related_re)\b/) {
1460+
$found = 1;
1461+
}
1462+
else {
1463+
last if $found > 1 and $inlist < 2;
1464+
}
1465+
}
1466+
elsif (/^=item|^=back/) {
1467+
last if $found > 1 and $inlist < 2;
1468+
}
1469+
elsif ($found and /^X<[^>]+>/) {
1470+
push @related, m/X<([^>]+)>/g;
1471+
}
1472+
next unless $found;
1473+
if (/^=over/) {
1474+
++$inlist;
1475+
}
1476+
elsif (/^=back/) {
1477+
--$inlist;
1478+
}
1479+
push @$pod, $_;
1480+
++$found if /^\w/; # found descriptive text
1481+
}
1482+
1483+
if (!@$pod) {
1484+
CORE::die( sprintf
1485+
"No documentation for '%s' found in perl glossary\n",
1486+
$self->opt_g )
1487+
;
1488+
}
1489+
close $fh or $self->die( "Can't close $pglossary: $!" );
1490+
1491+
return;
1492+
}
1493+
1494+
#..........................................................................
1495+
14011496
sub search_perlfaqs {
14021497
my( $self, $found_things, $pod) = @_;
14031498

0 commit comments

Comments
 (0)