File Coverage

blib/lib/App/Grok/Resource/Functions.pm
Criterion Covered Total %
statement 19 76 25.0
branch 0 38 0.0
condition 0 3 0.0
subroutine 7 11 63.6
pod 3 3 100.0
total 29 131 22.1


line stmt bran cond sub pod time code
1             package App::Grok::Resource::Functions;
2             BEGIN {
3 1     1   33 $App::Grok::Resource::Functions::AUTHORITY = 'cpan:HINRIK';
4             }
5             {
6             $App::Grok::Resource::Functions::VERSION = '0.26';
7             }
8              
9 1     1   5 use strict;
  1         2  
  1         31  
10 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         36  
11 1     1   1655 use File::ShareDir qw<dist_dir>;
  1         10447  
  1         123  
12 1     1   14 use File::Spec::Functions qw<catdir catfile splitpath>;
  1         2  
  1         63  
13              
14 1     1   6 use base qw(Exporter);
  1         2  
  1         138  
15             our @EXPORT_OK = qw(func_index func_fetch func_locate);
16             our %EXPORT_TAGS = ( ALL => [@EXPORT_OK] );
17             use constant {
18 1         1389 NAME => 0,
19             POD => 1,
20             FILE => 2,
21 1     1   6 };
  1         3  
22              
23             my %functions;
24             my $syn_dir = catdir(dist_dir('Perl6-Doc'), 'Synopsis');
25              
26             sub func_fetch {
27 0     0 1   my ($func) = @_;
28 0 0         _read_functions() if !%functions;
29            
30 0 0         return $functions{$func}[POD] if defined $functions{$func};
31 0           return;
32             }
33              
34             sub func_index {
35 0 0   0 1   _read_functions() if !%functions;
36 0           return keys %functions;
37             }
38              
39             sub func_locate {
40 0     0 1   my ($func) = @_;
41 0 0         _read_functions() if !%functions;
42 0 0         return if !defined $functions{$func};
43 0           return $functions{$func}[FILE];
44             }
45              
46             ## no critic (Subroutines::ProhibitExcessComplexity)
47             sub _read_functions {
48 0     0     my ($self) = @_;
49              
50 0           my $S29_file = catfile(dist_dir('Perl6-Doc'), 'Synopsis', 'S29-functions.pod');
51              
52             ## no critic (InputOutput::RequireBriefOpen)
53 0 0         open my $S29, '<', $S29_file or die "Can't open '$S29_file': $!";
54              
55             # read until you find 'Function Packages'
56 0           until (<$S29> =~ /Function Packages/) {}
57              
58 0           my (%S29_funcs, $func_name);
59 0           while (my $line = <$S29>) {
60 0 0         if (my ($directive, $title) = $line =~ /^=(\S+)(?: +(.+))?/) {
    0          
61 0 0         if ($directive eq 'item') {
62             # Found Perl6 function name
63 0 0         if (my ($reference) = $title =~ /-- (see S\d+.*)/) {
64             # one-line entries
65 0           (my $func = $title) =~ s/^(\S+).*/$1/;
66 0           $S29_funcs{$func} = $reference;
67             }
68             else {
69 0           $title =~ s/\(.*\)//;
70 0           $func_name = $title;
71             }
72             }
73             else {
74 0           $func_name = undef;
75             }
76             }
77             elsif ($func_name) {
78             # Adding documentation to the function name
79 0           $S29_funcs{$func_name} .= $line;
80             }
81             }
82              
83 0           my %S29_sanitized;
84 0           while (my ($func, $body) = each %S29_funcs) {
85 0           $body = "=encoding utf8\n\n=head2 C<<< $func >>>\n$body";
86 0 0         $S29_sanitized{$func} = [$func, $body, $S29_file] if $func !~ /\s/;
87              
88 0 0         if ($func =~ /,/) {
89 0           my @funcs = split /,\s+/, $func;
90 0           $S29_sanitized{$_} = [$func, $body, $S29_file] for @funcs;
91             }
92             }
93            
94 0           %functions = %S29_sanitized;
95            
96             # read S32
97 0           my $S32_dir = catdir($syn_dir, 'S32-setting-library');
98 0           my @sections = map { (splitpath($_))[2] } glob "$S32_dir/*.pod";
  0            
99 0           $_ = catdir($S32_dir, $_) for @sections;
100              
101 0           for my $section (@sections) {
102             ## no critic (InputOutput::RequireBriefOpen)
103 0 0         open my $handle, '<', $section or die "Can't open $section: $!";
104              
105 0           my @new_func;
106 0           while (my $line = <$handle>) {
107 0 0         if (my ($directive, $title) = $line =~ /^=(\S+)(?: +(.+))?/) {
    0          
108 0 0         if (defined $new_func[NAME]) {
109 0           my $name = $new_func[NAME];
110            
111             # S32 only overwrites S29 if the new definition is wordier
112 0 0 0       if (!defined $functions{$name} ||
113             length $new_func[POD] > length $functions{$name}[POD]) {
114 0           $functions{$new_func[NAME]} = [@new_func];
115             }
116 0           @new_func = ();
117             }
118 0 0         if ($directive eq 'item') {
119 0           $title =~ s/.*?method\s*//;
120 0           $title =~ s/^(\S+)\s*\(.*/$1/;
121 0 0         if ($title =~ /^\S+$/) {
122 0           $new_func[NAME] = $title;
123 0           $new_func[POD] = "=encoding utf8\n\n=head2 C<<< $title >>>\n";
124 0           $new_func[FILE] = $section;
125             }
126             }
127             }
128             elsif (defined $new_func[FILE]) {
129             # Adding documentation to the function name
130 0           $new_func[POD] .= $line;
131             }
132             }
133              
134 0           close $handle;
135             }
136              
137 0           return;
138             }
139              
140             1;
141              
142             =encoding utf8
143              
144             =head1 NAME
145              
146             App::Grok::Resource::Functions - S29/S32 functions resource for grok
147              
148             =head1 SYNOPSIS
149              
150             use strict;
151             use warnings;
152             use App::Grok::Resource::Functions qw<:ALL>;
153              
154             # a list of all functions
155             my @index = func_index();
156              
157             # documentation for a specific functions
158             my $pod = func_fetch('split');
159              
160             # the file where the function was found
161             my $file = func_locate('split');
162              
163             =head1 DESCRIPTION
164              
165             This resource reads Synopses 29 and 32, and allows you to look up the
166             functions therein.
167              
168             =head1 FUNCTIONS
169              
170             =head2 C<func_index>
171              
172             Takes no arguments. Returns a list of all known function names.
173              
174             =head2 C<func_fetch>
175              
176             Takes the name of a function as an argument. Returns the documentation for
177             that function.
178              
179             =head2 C<func_locate>
180              
181             Takes the same argument as L<C<func_fetch>|/func_fetch>. Returns the path to
182             the Synopsis file where the given function was found.
183              
184             =cut