File Coverage

blib/lib/App/Grok/Resource/Spec.pm
Criterion Covered Total %
statement 19 76 25.0
branch 0 26 0.0
condition n/a
subroutine 7 12 58.3
pod 4 4 100.0
total 30 118 25.4


line stmt bran cond sub pod time code
1             package App::Grok::Resource::Spec;
2             BEGIN {
3 1     1   33 $App::Grok::Resource::Spec::AUTHORITY = 'cpan:HINRIK';
4             }
5             {
6             $App::Grok::Resource::Spec::VERSION = '0.26';
7             }
8              
9 1     1   6 use strict;
  1         1  
  1         36  
10 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         46  
11 1     1   1174 use App::Grok::Common qw<data_dir download>;
  1         3  
  1         75  
12 1     1   7 use File::ShareDir qw<dist_dir>;
  1         2  
  1         44  
13 1     1   4 use File::Spec::Functions qw<catdir catfile splitpath>;
  1         3  
  1         53  
14              
15 1     1   5 use base qw(Exporter);
  1         1  
  1         1624  
16             our @EXPORT_OK = qw(spec_index spec_fetch spec_locate spec_update);
17             our %EXPORT_TAGS = ( ALL => [@EXPORT_OK] );
18              
19             my %index;
20             my $dist_dir = dist_dir('Perl6-Doc');
21             my %docs = map {
22             substr($_, 0, 1) => catdir($dist_dir, $_)
23             } qw<Apocalypse Exegesis Magazine Synopsis>;
24              
25             sub spec_update {
26 0     0 1   my $res_dir = catdir(data_dir(), 'resources', 'spec');
27 0 0         if (!-d $res_dir) {
28 0 0         mkdir $res_dir or die "Can't create $res_dir: $!\n";
29              
30             }
31 0           my $s32_dir = catdir($res_dir, 'S32-setting-library');
32 0 0         if (!-d $s32_dir) {
33 0 0         mkdir $s32_dir or die "Can't create $s32_dir: $!\n";
34             }
35              
36 0           print "Downloading specs...\n";
37 0           my @specs = map { chomp; $_ } <DATA>;
  0            
  0            
38              
39 0           my $i = 0;
40 0           for my $spec_url (@specs) {
41 0           $i++;
42 0           my $s32 = $spec_url =~ /S32/;
43 0           my ($filename) = $spec_url =~ m{(?<=/)([^/]+)$};
44 0 0         my $title = "($i/".scalar @specs.") ".($s32?'S32-setting-library/': '').$filename;
45 0           my $content = download($title, $spec_url);
46 0 0         my $file = catfile(($s32 ? $s32_dir : $res_dir), $filename);
47 0 0         open my $fh, '>:encoding(utf8)', $file or die "Can't open $file: $!\n";
48 0           print $fh $content;
49 0           close $fh;
50             }
51              
52 0           return;
53             }
54              
55             sub spec_fetch {
56 0     0 1   my ($topic) = @_;
57 0 0         _build_index() if !%index;
58            
59 0           for my $doc (keys %index) {
60 0 0         if ($doc =~ /^\Q$topic/i) {
61 0 0         open my $handle, '<', $index{$doc} or die "Can't open $index{$doc}: $!";
62 0           my $pod = do { local $/ = undef; scalar <$handle> };
  0            
  0            
63 0           close $handle;
64 0           return $pod;
65             }
66             }
67 0           return;
68             }
69              
70             sub spec_index {
71 0 0   0 1   _build_index() if !%index;
72 0           return keys %index;
73             }
74              
75             sub spec_locate {
76 0     0 1   my ($topic) = @_;
77 0 0         _build_index() if !%index;
78            
79 0           for my $doc (keys %index) {
80 0 0         return $index{$doc} if $doc =~ /^$topic/i;
81             }
82              
83 0           return;
84             }
85              
86             sub _build_index {
87 0     0     while (my ($type, $dir) = each %docs) {
88 0           for my $file (glob "$dir/*.pod") {
89 0           my $name = (splitpath($file))[2];
90 0           $name =~ s/\.pod$//;
91 0           $index{$name} = $file;
92             }
93             }
94              
95             # man pages (perlintro, etc)
96 0           my $pages_dir = catdir($dist_dir, 'man_pages');
97 0           for my $file (glob "$pages_dir/*.pod") {
98 0           my $name = (splitpath($file))[2];
99 0           $name =~ s/\.pod$//;
100 0           $index{$name} = $file;
101             }
102              
103             # synopsis 32
104 0           my $S32_dir = catdir($docs{S}, 'S32-setting-library');
105 0           for my $file (glob "$S32_dir/*.pod") {
106 0           my $name = (splitpath($file))[2];
107 0           $name =~ s/\.pod$//;
108 0           $name = "S32-$name";
109 0           $index{$name} = $file;
110             }
111              
112 0           return;
113             }
114              
115             1;
116              
117             =encoding utf8
118              
119             =head1 NAME
120              
121             App::Grok::Resource::Spec - Perl 6 specification resource for grok
122              
123             =head1 SYNOPSIS
124              
125             use strict;
126             use warnings;
127             use App::Grok::Resource::Spec qw<:ALL>;
128              
129             # list of all Synopsis, Exegeses, etc
130             my @index = spec_index();
131              
132             # get the contents of Synopsis 02
133             my $pod = spec_fetch('s02');
134              
135             # filename containing S02
136             my $file = spec_locate('s02');
137              
138             =head1 DESCRIPTION
139              
140             This module the locates Apocalypses, Exegeses, Synopsis and magazine articles
141             distributed with L<Perl6::Doc>.
142              
143             It also includes user documentation like F<perlintro> and F<perlsyn>.
144              
145             =head1 FUNCTIONS
146              
147             =head2 C<spec_update>
148              
149             Takes no arguments. Downloads the latest specifications (Synopses) into
150             grok's data dir.
151              
152             =head2 C<spec_index>
153              
154             Doesn't take any arguments. Returns a list of all documents known to this
155             resource.
156              
157             =head2 C<spec_fetch>
158              
159             Takes the name of a document as an argument. It is case-insensitive and you
160             only need to specify the first three characters (though more are allowed),
161             e.g. C<spec_fetch('s02')>. Returns the Pod text of the document.
162              
163             =head2 C<spec_locate>
164              
165             Takes the same argument as L<C<spec_fetch>|/spec_fetch>. Returns the filename
166             corresponding to the given document.
167              
168             =cut
169             __DATA__
170             https://github.com/perl6/specs/raw/master/S01-overview.pod
171             https://github.com/perl6/specs/raw/master/S02-bits.pod
172             https://github.com/perl6/specs/raw/master/S03-operators.pod
173             https://github.com/perl6/specs/raw/master/S04-control.pod
174             https://github.com/perl6/specs/raw/master/S05-regex.pod
175             https://github.com/perl6/specs/raw/master/S06-routines.pod
176             https://github.com/perl6/specs/raw/master/S07-iterators.pod
177             https://github.com/perl6/specs/raw/master/S08-capture.pod
178             https://github.com/perl6/specs/raw/master/S09-data.pod
179             https://github.com/perl6/specs/raw/master/S10-packages.pod
180             https://github.com/perl6/specs/raw/master/S11-modules.pod
181             https://github.com/perl6/specs/raw/master/S12-objects.pod
182             https://github.com/perl6/specs/raw/master/S13-overloading.pod
183             https://github.com/perl6/specs/raw/master/S14-roles-and-parametric-types.pod
184             https://github.com/perl6/specs/raw/master/S16-io.pod
185             https://github.com/perl6/specs/raw/master/S17-concurrency.pod
186             https://github.com/perl6/specs/raw/master/S19-commandline.pod
187             https://github.com/perl6/specs/raw/master/S21-calling-foreign-code.pod
188             https://github.com/perl6/specs/raw/master/S22-package-format.pod
189             https://github.com/perl6/specs/raw/master/S24-testing.pod
190             https://github.com/perl6/specs/raw/master/S26-documentation.pod
191             https://github.com/perl6/specs/raw/master/S28-special-names.pod
192             https://github.com/perl6/specs/raw/master/S29-functions.pod
193             https://github.com/perl6/specs/raw/master/S31-pragmatic-modules.pod
194             https://github.com/perl6/specs/raw/master/S32-setting-library/Basics.pod
195             https://github.com/perl6/specs/raw/master/S32-setting-library/Callable.pod
196             https://github.com/perl6/specs/raw/master/S32-setting-library/Containers.pod
197             https://github.com/perl6/specs/raw/master/S32-setting-library/Exception.pod
198             https://github.com/perl6/specs/raw/master/S32-setting-library/IO.pod
199             https://github.com/perl6/specs/raw/master/S32-setting-library/Numeric.pod
200             https://github.com/perl6/specs/raw/master/S32-setting-library/Rules.pod
201             https://github.com/perl6/specs/raw/master/S32-setting-library/Str.pod
202             https://github.com/perl6/specs/raw/master/S32-setting-library/Temporal.pod