File Coverage

lib/Getopt/Compact/PodMunger.pm
Criterion Covered Total %
statement 70 75 93.3
branch 21 22 95.4
condition 3 3 100.0
subroutine 16 17 94.1
pod 8 8 100.0
total 118 125 94.4


line stmt bran cond sub pod time code
1             # $Id: PodMunger.pm 15 2006-09-04 20:00:01Z andrew $
2             # Copyright (c) 2006 Andrew Stewart Williams. All rights reserved.
3             # This program is free software; you can redistribute it and/or
4             # modify it under the same terms as Perl itself.
5              
6             package Getopt::Compact::PodMunger;
7 1     1   747 use strict;
  1         2  
  1         35  
8 1     1   5 use Pod::Parser;
  1         2  
  1         54  
9 1     1   6 use base qw/Pod::Parser/;
  1         1  
  1         98  
10 1     1   5 use vars qw/$VERSION/;
  1         2  
  1         61  
11              
12             $VERSION = "0.04";
13              
14             # section ordering.
15 1         883 use constant SECTION_ORDER =>
16             (qw/NAME SYNOPSIS USAGE REQUIRES EXPORTS DESCRIPTION METHODS DIAGNOSTICS
17             NOTES VERSION AUTHOR/, 'SEE ALSO', qw/BUGS ACKNOWLEDGEMENTS/,
18 1     1   4 'COPYRIGHT AND LICENSE');
  1         2  
19              
20             ###################
21             # Pod::Parser API #
22             sub command {
23 52     52 1 78 my($self, $command, $paragraph, $line_num) = @_;
24 52         116 my($sect) = $paragraph =~ /(\w+)/;
25 52 100       124 $self->_addsect($sect) if $command eq 'head1';
26 52         122 $self->_addpod("=$command $paragraph");
27             }
28              
29             sub verbatim {
30 1     1 1 4 my($self, $paragraph, $line_num) = @_;
31 1         3 $self->_addpod($paragraph);
32             }
33              
34             sub textblock {
35 28     28 1 38 my($self, $paragraph, $line_num) = @_;
36 28         46 $self->_addpod($paragraph);
37             }
38              
39             sub begin_input {
40 6     6 1 6470 my $self = shift;
41             # use _pod as a scratch space between sections (chunks)
42 6         12 $self->{_pod} = '';
43 6         11 $self->{_sections} = {};
44 6         550 $self->{_chunk} = [];
45             }
46              
47             sub end_input {
48 6     6 1 9 my $self = shift;
49 6         12 $self->_addsect; # add the final section
50             }
51             ####################
52              
53             # return the pod as a single chunk of text. make sure commands are
54             # separated by a blank line.
55             sub as_string {
56 7     7 1 26 my $self = shift;
57 7         8 my @chunks;
58 7         15 for my $c ($self->_chunks) {
59 35         129 $c =~ s/\s+$//s;
60 35         55 push @chunks, $c;
61             }
62 7         34 return join("\n\n", @chunks);
63             }
64              
65             sub print_manpage {
66 0     0 1 0 my $self = shift;
67 0         0 my $pod = $self->as_string;
68            
69 0         0 require Pod::Simple::Text::Termcap;
70 0         0 my $pt = new Pod::Simple::Text::Termcap;
71 0         0 $pt->parse_string_document($pod);
72             }
73              
74             sub insert {
75 9     9 1 735 my($self, $section, $content, $is_verbatim) = @_;
76            
77 9         15 $section = uc($section);
78 9 100       18 return if $self->_has_section($section); # don't clobber existing sections
79 8 100       16 return unless defined $content; # skip undefined content
80              
81 7         12 my @chunks = $self->_chunks;
82 7         16 my %known_section = map { $_ => 1 } SECTION_ORDER;
  105         1527  
83 7         14 my(@newchunks, $pod, $after);
84            
85             # decide where to insert section
86 7         26 my @sects = reverse SECTION_ORDER;
87 7         19 while(@sects) {
88 79         86 $after = shift @sects;
89             # find section we are inserting in reverse section order list.
90 79 100 100     324 next unless $after eq $section || !$known_section{$section};
91             # find the next highest existing section. we will insert after that
92 7         18 ($after) = grep $self->_has_section($_), @sects;
93 7         8 last;
94             }
95              
96 7 100       21 $content =~ s/^(\s*\S+)/ $1/gm if $is_verbatim; # indent
97 7         13 $pod = qq/=head1 $section\n\n$content/;
98              
99 7 100       12 if(defined $after) {
100 4         27 for my $c (@chunks) {
101 17         24 push @newchunks, $c;
102 17 100       99 push @newchunks, $pod if $c =~ /^=head1 $after/;
103             }
104             } else {
105 3         7 @newchunks = ($pod, @chunks);
106             }
107 7         12 $self->{_chunk} = \@newchunks;
108 7         44 $self->{_sections}->{$section} = 1;
109             }
110              
111             # private methods
112              
113             sub _addpod {
114 81     81   126 my($self, @text) = @_;
115 81         3238 $self->{_pod} .= join('', @text);
116             }
117              
118             sub _addsect {
119 28     28   33 my($self, $sect) = @_;
120 28 50       72 push @{$self->{_chunk}}, $self->{_pod} if $self->{_pod};
  28         55  
121 28 100       80 $self->{_sections}->{$sect} = 1 if defined $sect;
122 28         214 $self->{_pod} = '';
123             }
124              
125             sub _chunks {
126 14     14   18 my($self) = @_;
127 14 100       12 return @{$self->{_chunk} || []};
  14         70  
128             }
129              
130             sub _has_section {
131 35     35   283 my($self, $sect) = @_;
132 35 100       129 return $self->{_sections}->{$sect} ? 1 : 0;
133             }
134              
135             1;
136              
137             =head1 NAME
138              
139             Getopt::Compact::PodMunger - script POD munging
140              
141             =head1 SYNOPSIS
142              
143             my $p = new Getopt::Compact::PodMunger();
144             $p->parse_from_file('foo.pl');
145             $p->insert('USAGE', $usage_string);
146             print $p->as_string;
147              
148             =head1 DESCRIPTION
149              
150             Getopt::Compact::PodMunger is used internally by Getopt::Compact to
151             parse POD in command line scripts. The parsed POD is then munged via
152             the C method. This is only required when the --man option is
153             used.
154              
155             =head1 METHODS
156              
157             =over 4
158              
159             =item new(), command(), verbatim(), textblock(), begin_input(), end_input()
160              
161             These methods are inherited from L. Refer to
162             L for more information.
163              
164             =item $p->insert($section, $content, $is_verbatim)
165              
166             Modifies the parsed pod by inserting a new section as a C with
167             $content under it. Correct ordering of sections (eg. C,
168             C, C) is attempted. If $is_verbatim is true,
169             the content will be indented by four spaces.
170              
171             =item $pod = $p->as_string()
172              
173             Returns the parsed POD as a string.
174              
175             =item $p->print_manpage()
176              
177             Prints the parsed POD as a manpage, using Pod::Simple::Text::Termcap.
178              
179             =back
180              
181             =head1 VERSION
182              
183             $Revision: 15 $
184              
185             =head1 AUTHOR
186              
187             Andrew Stewart Williams
188              
189             =head1 SEE ALSO
190              
191             L, L
192              
193             =cut