File Coverage

blib/lib/Pod/Abstract/Filter.pm
Criterion Covered Total %
statement 12 68 17.6
branch 0 12 0.0
condition 0 6 0.0
subroutine 4 11 36.3
pod 6 7 85.7
total 22 104 21.1


line stmt bran cond sub pod time code
1             package Pod::Abstract::Filter;
2 1     1   4062 use strict;
  1         2  
  1         45  
3 1     1   6 use warnings;
  1         1  
  1         65  
4              
5 1     1   7 use Pod::Abstract;
  1         2  
  1         37  
6              
7 1     1   710 use Module::Pluggable require => 1, search_path => ['Pod::Abstract::Filter'];
  1         14569  
  1         9  
8              
9             our $VERSION = '0.26';
10              
11             =head1 NAME
12              
13             Pod::Abstract::Filter - Generic Pod-in to Pod-out filter.
14              
15             =head1 DESCRIPTION
16              
17             This is a superclass for filter modules using
18             Pod::Abstract. Subclasses should override the C
19             sub. Pod::Abstract::Filter classes in the Pod::Abstract::Filter
20             namespace will be used by the C utility.
21              
22             To create a filter, you need to implement:
23              
24             =over
25              
26             =item filter
27              
28             Takes a Pod::Abstract::Node tree, and returns either another tree, or
29             a string. If a string is returned, it will be re-parsed to be input to
30             any following filter, or output directly if it is the last filter in
31             the list.
32              
33             It is recommended your filter method produce a Node tree if you are able
34             to, as this will improve interoperability with other C
35             based software.
36              
37             =item require_params
38              
39             If you want positional arguments following your filter in the style of:
40              
41             paf find [thing] Pod::Abstract
42              
43             then override require_params to list the named arguments that are to
44             be accepted after the filter name.
45              
46             =back
47              
48             =head1 METHODS
49              
50             =head2 new
51              
52             Create a new filter with the specified arguments.
53              
54             =cut
55              
56             sub new {
57 0     0 1   my $class = shift;
58 0           my %args = @_;
59            
60 0           return bless { %args }, $class;
61             }
62              
63             =head2 plugins_info
64              
65             my $info = Pod::Abstract::Filter->plugins_info;
66              
67             Gets information for each paf command/plugin.
68              
69             =cut
70              
71             sub plugins_info {
72 0     0 1   my $class = shift;
73              
74 0           my @plugins = $class->plugins;
75 0           my $info = {};
76 0           foreach my $p (@plugins) {
77 0           $p =~ m/^Pod::Abstract::Filter::(.*)$/;
78 0           my $cmd = $1;
79              
80 0           $info->{$cmd} = {
81             class => $p,
82             command => $cmd,
83             summary => $class->summarise( $p ),
84             };
85             }
86              
87 0           return $info;
88             }
89              
90             sub summarise {
91 0     0 0   my $class = shift;
92 0           my $mod = shift;
93            
94 0           $mod =~ s/::/\//g;
95 0           $mod .= '.pm';
96 0           my $filepath = '';
97 0           foreach my $path (@INC) {
98 0 0         if(-r "$path/$mod") {
99 0           $filepath = "$path/$mod";
100 0           last;
101             }
102             }
103              
104 0           my $pa = Pod::Abstract->load_file($filepath);
105 0           my @texts = $pa->select('/head1[@heading eq \'NAME\']/:paragraph');
106 0 0         return [] unless @texts;
107            
108 0           my $pt = join '', map { $_->pod } @texts;
  0            
109 0           $pt =~ s/^Pod::Abstract::Filter:://;
110 0           my ($command, $rest) = split / - /, $pt, 2;
111 0 0 0       return [ ] unless $command && $rest; # Never mind if the module doesn't follow standard
112              
113 0           $rest =~ s/[\r\n]//g;
114              
115              
116             # Reflow to max 72 chars.
117 0           my $out = '';
118 0           while( $rest ) {
119 0 0         if( length $rest <= 72 ) {
120 0           $out .= ' '.$rest;
121 0           $rest = '';
122             } else {
123 0           my $i = 72;
124 0   0       while( substr($rest, $i, 1) !~ /^\s$/ && $i > 0 ) {
125 0           $i --;
126             }
127 0 0         if( $i == 0 ) {
128             # Give up and finish the string.
129 0           $out .= ' '.$rest;
130             } else {
131 0           $out .= ' '.substr( $rest, 0, $i, '')."\n";
132 0           $rest =~ s/^\s*//;
133             }
134             }
135              
136             }
137              
138 0           return [ $command, $out ];
139             }
140              
141             =head2 require_params
142              
143             Override to return a list of parameters that must be provided. This
144             will be accepted in order on the command line, unless they are first
145             set using the C<-flag=xxx> notation.
146              
147             =cut
148              
149             sub require_params {
150 0     0 1   return ( );
151             }
152              
153             =head2 param
154              
155             Get the named param. Read only.
156              
157             =cut
158              
159             sub param {
160 0     0 1   my $self = shift;
161 0           my $param_name = shift;
162 0           return $self->{$param_name};
163             }
164              
165             =head2 filter
166              
167             Stub method. Does nothing, just returns the original tree.
168              
169             =cut
170              
171             sub filter {
172 0     0 1   my $self = shift;
173 0           my $pa = shift;
174            
175 0           return $pa;
176             }
177              
178             =head2 run
179              
180             Run the filter. If $arg is a string, it will be parsed
181             first. Otherwise, the Abstract tree will be used. Returns either a
182             string or an abstract tree (which may be the original tree, modified).
183              
184             =cut
185              
186             sub run {
187 0     0 1   my $self = shift;
188 0           my $arg = shift;
189            
190 0 0         if( eval { $arg->isa( 'Pod::Abstract::Node' ) } ) {
  0            
191 0           return $self->filter($arg);
192             } else {
193 0           my $pa = Pod::Abstract->load_string($arg);
194 0           return $self->filter($pa);
195             }
196             }
197              
198             =head1 AUTHOR
199              
200             Ben Lilburne
201              
202             =head1 COPYRIGHT AND LICENSE
203              
204             Copyright (C) 2009-2025 Ben Lilburne
205              
206             This program is free software; you can redistribute it and/or modify
207             it under the same terms as Perl itself.
208              
209             =cut
210              
211             1;