File Coverage

blib/lib/Getopt/Long/Descriptive/Usage.pm
Criterion Covered Total %
statement 109 115 94.7
branch 38 52 73.0
condition 9 13 69.2
subroutine 15 16 93.7
pod 6 6 100.0
total 177 202 87.6


line stmt bran cond sub pod time code
1 2     2   13 use strict;
  2         5  
  2         75  
2 2     2   10 use warnings;
  2         6  
  2         91  
3             package Getopt::Long::Descriptive::Usage 0.111;
4             # ABSTRACT: the usage description for GLD
5              
6 2     2   10 use List::Util qw(max);
  2         4  
  2         3101  
7              
8             #pod =head1 SYNOPSIS
9             #pod
10             #pod use Getopt::Long::Descriptive;
11             #pod my ($opt, $usage) = describe_options( ... );
12             #pod
13             #pod $usage->text; # complete usage message
14             #pod
15             #pod $usage->die; # die with usage message
16             #pod
17             #pod =head1 DESCRIPTION
18             #pod
19             #pod This document only describes the methods of the Usage object. For information
20             #pod on how to use L<Getopt::Long::Descriptive>, consult its documentation.
21             #pod
22             #pod =head1 METHODS
23             #pod
24             #pod =head2 new
25             #pod
26             #pod my $usage = Getopt::Long::Descriptive::Usage->new(\%arg);
27             #pod
28             #pod You B<really> don't need to call this. GLD will do it for you.
29             #pod
30             #pod Valid arguments are:
31             #pod
32             #pod options - an arrayref of options
33             #pod leader_text - the text that leads the usage; this may go away!
34             #pod
35             #pod =cut
36              
37             sub new {
38 29     29 1 62 my ($class, $arg) = @_;
39              
40 29         76 my @to_copy = qw(leader_text options show_defaults);
41              
42 29         49 my %copy;
43 29         105 @copy{ @to_copy } = @$arg{ @to_copy };
44              
45 29         103 bless \%copy => $class;
46             }
47              
48             #pod =head2 text
49             #pod
50             #pod This returns the full text of the usage message.
51             #pod
52             #pod =cut
53              
54             sub text {
55 15     15 1 136 my ($self) = @_;
56              
57 15         47 return join qq{\n}, $self->leader_text, $self->option_text;
58             }
59              
60             #pod =head2 leader_text
61             #pod
62             #pod This returns the text that comes at the beginning of the usage message.
63             #pod
64             #pod =cut
65              
66 15     15 1 118 sub leader_text { $_[0]->{leader_text} }
67              
68             #pod =head2 option_text
69             #pod
70             #pod This returns the text describing the available options.
71             #pod
72             #pod =cut
73              
74             sub option_text {
75 15     15 1 35 my ($self) = @_;
76              
77 15         29 my $string = q{};
78              
79 15 50       25 my @options = @{ $self->{options} || [] };
  15         62  
80 15         37 my @specs = map { $_->{spec} } grep { $_->{desc} ne 'spacer' } @options;
  39         83  
  50         112  
81 15   100     40 my $length = (max(map { _option_length($_) } @specs) || 0);
82 15         40 my $spec_fmt = "\t%-${length}s";
83              
84 15         39 while (@options) {
85 50         81 my $opt = shift @options;
86 50         93 my $spec = $opt->{spec};
87 50         75 my $desc = $opt->{desc};
88              
89 50 100       103 if ($desc eq 'spacer') {
90 11 100       28 if (ref $opt->{spec}) {
91 2         4 $string .= "${ $opt->{spec} }\n";
  2         6  
92 2         6 next;
93             } else {
94 9         23 my @lines = $self->_split_description($length, $opt->{spec});
95              
96 9 100       40 $string .= length($_) ? sprintf("$spec_fmt\n", $_) : "\n" for @lines;
97 9         24 next;
98             }
99             }
100              
101 39         103 ($spec, my $assign) = Getopt::Long::Descriptive->_strip_assignment($spec);
102              
103 39         88 my ($pre, $post) = _parse_assignment($assign);
104 39         96 my @names = split /\|/, $spec;
105              
106 39         71 my $primary = shift @names;
107 39         60 my $short;
108 39         87 my ($i) = grep {; length $names[$_] == 1 } (0 .. $#names);
  15         40  
109 39 100       90 if (defined $i) {
110 15         29 $short = splice @names, $i, 1;
111             }
112              
113 39 50       119 $spec = length $primary > 1 ? "--$pre$primary$post" : "-$primary$post";
114 39 100       82 $spec .= " (or -$short)" if $short;
115              
116 39         89 my @desc = $self->_split_description($length, $desc);
117              
118 39 50       84 if (@names) {
119             push @desc,
120 0 0       0 "aka " . join q{, }, map { length > 1 ? "--$_" : "-$_" } @names;
  0         0  
121             }
122              
123             # add default value if it exists
124 39 0 33     92 if (exists $opt->{constraint}->{default} and $self->{show_defaults}) {
125 0         0 my $dflt = $opt->{constraint}->{default};
126 0 0       0 $dflt = ! defined $dflt ? '(undef)'
    0          
127             : ! length $dflt ? '(empty string)'
128             : $dflt;
129 0         0 push @desc, "(default value: $dflt)";
130             }
131              
132 39         156 $string .= sprintf "$spec_fmt %s\n", $spec, shift @desc;
133 39         137 for my $line (@desc) {
134 2         5 $string .= "\t";
135 2         6 $string .= q{ } x ( $length + 2 );
136 2         19 $string .= "$line\n";
137             }
138             }
139              
140 15         105 return $string;
141             }
142              
143             sub _option_length {
144 39     39   68 my ($fullspec) = @_;
145              
146 39         110 my ($spec, $argspec) = Getopt::Long::Descriptive->_strip_assignment($fullspec);
147              
148 39         94 my ($pre, $post) = _parse_assignment($argspec);
149 39         104 my @names = split /\|/, $spec;
150              
151 39         74 my $primary = shift @names;
152 39 100 66     132 my $short = (@names && length $names[0] eq 1)
153             ? shift @names
154             : undef;
155              
156 39 50       103 $spec = length $primary > 1 ? "--$pre$primary$post" : "-$primary$post";
157 39 100       89 $spec .= " (or -$short)" if $short;
158              
159 39         122 return length $spec;
160             }
161              
162             sub _max_line_length {
163 48     48   98 return $Getopt::Long::Descriptive::TERM_WIDTH - 2;
164             }
165              
166             sub _split_description {
167 48     48   94 my ($self, $length, $desc) = @_;
168              
169             # 8 for a tab, 2 for the space between option & desc, 2 more for gutter
170 48         91 my $max_length = $self->_max_line_length - ( $length + 8 + 2 );
171              
172 48 100       141 return $desc if length $desc <= $max_length;
173              
174 3         6 my @lines;
175 3         8 while (length $desc > $max_length) {
176 5         13 my $idx = rindex( substr( $desc, 0, $max_length ), q{ }, );
177 5 100       14 last unless $idx >= 0;
178 4         10 push @lines, substr($desc, 0, $idx);
179 4         11 substr($desc, 0, $idx + 1) = q{};
180             }
181 3         6 push @lines, $desc;
182              
183 3         10 return @lines;
184             }
185              
186             sub _parse_assignment {
187 96     96   2443 my ($assign_spec) = @_;
188              
189 96         150 my $result = 'STR';
190 96         138 my $desttype;
191 96 100       198 if (length($assign_spec) < 2) {
192             # empty, ! or +
193 62 100       131 return ('[no-]', '') if $assign_spec eq '!';
194 58         131 return ('', '');
195             }
196              
197 34         79 my $optional = substr($assign_spec, 0, 1) eq ':';
198 34         63 my $argument = substr $assign_spec, 1, 2;
199              
200 34 100 100     201 if ($argument =~ m/^[io]/ or $assign_spec =~ m/^:[+0-9]/) {
    100          
201 10         19 $result = 'INT';
202             } elsif ($argument =~ m/^f/) {
203 4         9 $result = 'NUM';
204             }
205              
206 34 100       84 if (length($assign_spec) > 2) {
207 16         29 $desttype = substr($assign_spec, 2, 1);
208 16 100       38 if ($desttype eq '@') {
    50          
209             # Imply it can be repeated
210 8         15 $result .= '...';
211             } elsif ($desttype eq '%') {
212 8         18 $result = "KEY=${result}...";
213             }
214             }
215              
216 34 100       76 if ($optional) {
217 10         50 return ("", "[=$result]");
218             }
219              
220             # with leading space so it can just blindly be appended.
221 24         91 return ("", " $result");
222             }
223              
224             #pod =head2 warn
225             #pod
226             #pod This warns with the usage message.
227             #pod
228             #pod =cut
229              
230 0     0 1 0 sub warn { warn shift->text }
231              
232             #pod =head2 die
233             #pod
234             #pod This throws the usage message as an exception.
235             #pod
236             #pod $usage_obj->die(\%arg);
237             #pod
238             #pod Some arguments can be provided
239             #pod
240             #pod pre_text - text to be prepended to the usage message
241             #pod post_text - text to be appended to the usage message
242             #pod
243             #pod The C<pre_text> and C<post_text> arguments are concatenated with the usage
244             #pod message with no line breaks, so supply this if you need them.
245             #pod
246             #pod =cut
247              
248             sub die {
249 3     3 1 7 my $self = shift;
250 3   50     10 my $arg = shift || {};
251              
252             die(
253 9         77 join q{}, grep { defined } $arg->{pre_text}, $self->text, $arg->{post_text}
254 3         14 );
255             }
256              
257             use overload (
258             q{""} => "text",
259              
260             # This is only needed because Usage used to be a blessed coderef that worked
261             # this way. Later we can toss a warning in here. -- rjbs, 2009-08-19
262             '&{}' => sub {
263 2     2   6 my ($self) = @_;
264 2         318 Carp::cluck("use of __PACKAGE__ objects as a code ref is deprecated");
265 2 50   2   114 return sub { return $_[0] ? $self->text : $self->warn; };
  2         11  
266             }
267 2     2   15 );
  2         5  
  2         22  
268              
269             1;
270              
271             __END__
272              
273             =pod
274              
275             =encoding UTF-8
276              
277             =head1 NAME
278              
279             Getopt::Long::Descriptive::Usage - the usage description for GLD
280              
281             =head1 VERSION
282              
283             version 0.111
284              
285             =head1 SYNOPSIS
286              
287             use Getopt::Long::Descriptive;
288             my ($opt, $usage) = describe_options( ... );
289              
290             $usage->text; # complete usage message
291              
292             $usage->die; # die with usage message
293              
294             =head1 DESCRIPTION
295              
296             This document only describes the methods of the Usage object. For information
297             on how to use L<Getopt::Long::Descriptive>, consult its documentation.
298              
299             =head1 PERL VERSION
300              
301             This library should run on perls released even a long time ago. It should work
302             on any version of perl released in the last five years.
303              
304             Although it may work on older versions of perl, no guarantee is made that the
305             minimum required version will not be increased. The version may be increased
306             for any reason, and there is no promise that patches will be accepted to lower
307             the minimum required perl.
308              
309             =head1 METHODS
310              
311             =head2 new
312              
313             my $usage = Getopt::Long::Descriptive::Usage->new(\%arg);
314              
315             You B<really> don't need to call this. GLD will do it for you.
316              
317             Valid arguments are:
318              
319             options - an arrayref of options
320             leader_text - the text that leads the usage; this may go away!
321              
322             =head2 text
323              
324             This returns the full text of the usage message.
325              
326             =head2 leader_text
327              
328             This returns the text that comes at the beginning of the usage message.
329              
330             =head2 option_text
331              
332             This returns the text describing the available options.
333              
334             =head2 warn
335              
336             This warns with the usage message.
337              
338             =head2 die
339              
340             This throws the usage message as an exception.
341              
342             $usage_obj->die(\%arg);
343              
344             Some arguments can be provided
345              
346             pre_text - text to be prepended to the usage message
347             post_text - text to be appended to the usage message
348              
349             The C<pre_text> and C<post_text> arguments are concatenated with the usage
350             message with no line breaks, so supply this if you need them.
351              
352             =head1 AUTHORS
353              
354             =over 4
355              
356             =item *
357              
358             Hans Dieter Pearcey <hdp@cpan.org>
359              
360             =item *
361              
362             Ricardo Signes <cpan@semiotic.systems>
363              
364             =back
365              
366             =head1 COPYRIGHT AND LICENSE
367              
368             This software is copyright (c) 2005 by Hans Dieter Pearcey.
369              
370             This is free software; you can redistribute it and/or modify it under
371             the same terms as the Perl 5 programming language system itself.
372              
373             =cut