File Coverage

blib/lib/App/Cmd.pm
Criterion Covered Total %
statement 186 196 94.9
branch 35 52 67.3
condition 16 30 53.3
subroutine 49 51 96.0
pod 21 22 95.4
total 307 351 87.4


line stmt bran cond sub pod time code
1             # The "experimental" below is not actually scary. The feature went on to be
2             # de-experimental-ized with no changes and is now on by default in perl v5.24
3             # and later. -- rjbs, 2021-03-14
4 17     17   161616 use 5.020;
  17         84  
5 17     17   86 use warnings;
  17         31  
  17         540  
6 17     17   5235 use experimental qw(postderef postderef_qq);
  17         38766  
  17         117  
7              
8             package App::Cmd 0.336;
9              
10 17     17   5623 use parent 'App::Cmd::ArgProcessor';
  17         1562  
  17         114  
11             # ABSTRACT: write command line apps with less suffering
12              
13 17     17   858 use File::Basename ();
  17         34  
  17         309  
14 17     17   8686 use Module::Pluggable::Object ();
  17         165221  
  17         424  
15 17     17   8056 use Class::Load ();
  17         210124  
  17         2009  
16              
17             use Sub::Exporter -setup => {
18             collectors => {
19             -ignore => \'_setup_ignore',
20             -command => \'_setup_command',
21             -run => sub {
22 0         0 warn "using -run to run your command is deprecated\n";
23 0         0 $_[1]->{class}->run; 1
  0         0  
24             },
25             },
26 17     17   4668 };
  17         26229  
  17         202  
27              
28             sub _setup_command {
29 5     5   2844 my ($self, $val, $data) = @_;
30 5         10 my $into = $data->{into};
31              
32 5 50       48 Carp::confess "App::Cmd -command setup requested for already-setup class"
33             if $into->isa('App::Cmd::Command');
34              
35             {
36 5         23 my $base = $self->_default_command_base;
  5         15  
37 5         23 Class::Load::load_class($base);
38 17     17   10012 no strict 'refs';
  17         35  
  17         24291  
39 5         403 push @{"$into\::ISA"}, $base;
  5         84  
40             }
41              
42 5         43 $self->_register_command($into);
43              
44 5         16 for my $plugin ($self->_plugin_plugins) {
45 4         18 $plugin->import_from_plugin({ into => $into });
46             }
47              
48 5         331 1;
49             }
50              
51             sub _setup_ignore {
52 1     1   716 my ($self, $val, $data) = @_;
53 1         2 my $into = $data->{into};
54              
55 1 50       10 Carp::confess "App::Cmd -ignore setup requested for already-setup class"
56             if $into->isa('App::Cmd::Command');
57              
58 1         5 $self->_register_ignore($into);
59              
60 1         2 1;
61             }
62              
63 0     0   0 sub _plugin_plugins { return }
64              
65             #pod =head1 SYNOPSIS
66             #pod
67             #pod in F:
68             #pod
69             #pod use YourApp;
70             #pod YourApp->run;
71             #pod
72             #pod in F:
73             #pod
74             #pod package YourApp;
75             #pod use App::Cmd::Setup -app;
76             #pod 1;
77             #pod
78             #pod in F:
79             #pod
80             #pod package YourApp::Command::blort;
81             #pod use YourApp -command;
82             #pod use strict; use warnings;
83             #pod
84             #pod sub abstract { "blortex algorithm" }
85             #pod
86             #pod sub description { "Long description on blortex algorithm" }
87             #pod
88             #pod sub opt_spec {
89             #pod return (
90             #pod [ "blortex|X", "use the blortex algorithm" ],
91             #pod [ "recheck|r", "recheck all results" ],
92             #pod );
93             #pod }
94             #pod
95             #pod sub validate_args {
96             #pod my ($self, $opt, $args) = @_;
97             #pod
98             #pod # no args allowed but options!
99             #pod $self->usage_error("No args allowed") if @$args;
100             #pod }
101             #pod
102             #pod sub execute {
103             #pod my ($self, $opt, $args) = @_;
104             #pod
105             #pod my $result = $opt->{blortex} ? blortex() : blort();
106             #pod
107             #pod recheck($result) if $opt->{recheck};
108             #pod
109             #pod print $result;
110             #pod }
111             #pod
112             #pod and, finally, at the command line:
113             #pod
114             #pod knight!rjbs$ yourcmd blort --recheck
115             #pod
116             #pod All blorts successful.
117             #pod
118             #pod =head1 DESCRIPTION
119             #pod
120             #pod App::Cmd is intended to make it easy to write complex command-line applications
121             #pod without having to think about most of the annoying things usually involved.
122             #pod
123             #pod For information on how to start using App::Cmd, see L.
124             #pod
125             #pod =method new
126             #pod
127             #pod my $cmd = App::Cmd->new(\%arg);
128             #pod
129             #pod This method returns a new App::Cmd object. During initialization, command
130             #pod plugins will be loaded.
131             #pod
132             #pod Valid arguments are:
133             #pod
134             #pod no_commands_plugin - if true, the command list plugin is not added
135             #pod
136             #pod no_help_plugin - if true, the help plugin is not added
137             #pod
138             #pod no_version_plugin - if true, the version plugin is not added
139             #pod
140             #pod show_version_cmd - if true, the version command will be shown in the
141             #pod command list
142             #pod
143             #pod plugin_search_path - The path to search for commands in. Defaults to
144             #pod results of plugin_search_path method
145             #pod
146             #pod If C is not given, L will be
147             #pod required, and it will be registered to handle all of its command names not
148             #pod handled by other plugins.
149             #pod
150             #pod If C is not given, L will be required,
151             #pod and it will be registered to handle all of its command names not handled by
152             #pod other plugins. B "help" is the default command, so if you do not load
153             #pod the default help plugin, you should provide your own or override the
154             #pod C method.
155             #pod
156             #pod If C is not given, L will be
157             #pod required to show the application's version with command C<--version>. By
158             #pod default, the version command is not included in the command list. Pass
159             #pod C to include the version command in the list.
160             #pod
161             #pod =cut
162              
163             sub new {
164 25     25 1 8207 my ($class, $arg) = @_;
165              
166 25         73 my $arg0 = $0;
167 25         1322 my $base = File::Basename::basename $arg0;
168              
169             my $self = {
170             arg0 => $base,
171             full_arg0 => $arg0,
172 25   100     262 show_version => $arg->{show_version_cmd} // 0,
173             };
174              
175 25         67 bless $self, $class;
176              
177 25         148 $self->{command} = $self->_command($arg);
178              
179 25         122 return $self;
180             }
181              
182             # effectively, returns the command-to-plugin mapping guts of a Cmd
183             # if called on a class or on a Cmd with no mapping, construct a new hashref
184             # suitable for use as the object's mapping
185             sub _command {
186 182     182   317 my ($self, $arg) = @_;
187 182 100 66     1384 return $self->{command} if ref $self and $self->{command};
188              
189             # TODO _default_command_base can be wrong if people are not using
190             # ::Setup and have no ::Command :(
191             #
192             # my $want_isa = $self->_default_command_base;
193             # -- kentnl, 2010-12
194 29         58 my $want_isa = 'App::Cmd::Command';
195              
196 29         49 my %plugin;
197 29         103 for my $plugin ($self->_plugins) {
198              
199 81         256 Class::Load::load_class($plugin);
200              
201             # relies on either the plugin itself registering as ignored
202             # during compile ( use MyApp::Cmd -ignore )
203             # or being explicitly registered elsewhere ( blacklisted )
204             # via $app_cmd->_register_ignore( $class )
205             # -- kentnl, 2011-09
206 81 50       186535 next if $self->should_ignore( $plugin );
207              
208 81 50       455 die "$plugin is not a " . $want_isa
209             unless $plugin->isa($want_isa);
210              
211 81 50       439 next unless $plugin->can("command_names");
212              
213 81         241 foreach my $command (map { lc } $plugin->command_names) {
  93         321  
214             die "two plugins for command $command: $plugin and $plugin{$command}\n"
215 93 50       247 if exists $plugin{$command};
216              
217 93         262 $plugin{$command} = $plugin;
218             }
219             }
220              
221 29         168 $self->_load_default_plugin($_, $arg, \%plugin) for qw(commands help version);
222              
223 29 100       184 if ($self->allow_any_unambiguous_abbrev) {
224             # add abbreviations to list of authorized commands
225 1         766 require Text::Abbrev;
226 1         49 my %abbrev = Text::Abbrev::abbrev( keys %plugin );
227 1         70 @plugin{ keys %abbrev } = @plugin{ values %abbrev };
228             }
229              
230 29         126 return \%plugin;
231             }
232              
233             # ->_plugins won't be called more than once on any given App::Cmd, but since
234             # finding plugins can be a bit expensive, we'll do a lousy cache here.
235             # -- rjbs, 2007-10-09
236             my %plugins_for;
237             sub _plugins {
238 30     30   1196 my ($self) = @_;
239 30   66     94 my $class = ref $self || $self;
240              
241 30 100       112 return $plugins_for{$class}->@* if $plugins_for{$class};
242              
243 11         69 my $finder = Module::Pluggable::Object->new(
244             search_path => $self->plugin_search_path,
245             $self->_module_pluggable_options,
246             );
247              
248 11         132 my @plugins = $finder->plugins;
249 11         20857 $plugins_for{$class} = \@plugins;
250              
251 11         148 return @plugins;
252             }
253              
254             sub _register_command {
255 5     5   14 my ($self, $cmd_class) = @_;
256 5         15 $self->_plugins;
257              
258 5   33     25 my $class = ref $self || $self;
259             push $plugins_for{ $class }->@*, $cmd_class
260 5 50       11 unless grep { $_ eq $cmd_class } $plugins_for{ $class }->@*;
  7         38  
261             }
262              
263             my %ignored_for;
264              
265             sub should_ignore {
266 81     81 0 178 my ($self, $cmd_class) = @_;
267 81   33     225 my $class = ref $self || $self;
268 81         220 for ($ignored_for{ $class }->@*) {
269 0 0       0 return 1 if $_ eq $cmd_class;
270             }
271 81         198 return;
272             }
273              
274             sub _register_ignore {
275 1     1   3 my ($self, $cmd_class) = @_;
276 1   33     4 my $class = ref $self || $self;
277             push $ignored_for{ $class }->@*, $cmd_class
278 1 50       7 unless grep { $_ eq $cmd_class } $ignored_for{ $class }->@*;
  0         0  
279             }
280              
281             sub _module_pluggable_options {
282             # my ($self) = @_; # no point in creating these ops, just to toss $self
283 11     11   75 return;
284             }
285              
286             # load one of the stock plugins, unless requested to squash; unlike normal
287             # plugin loading, command-to-plugin mapping conflicts are silently ignored
288             sub _load_default_plugin {
289 87     87   215 my ($self, $plugin_name, $arg, $plugin_href) = @_;
290 87 100       281 unless ($arg->{"no_$plugin_name\_plugin"}) {
291 79         191 my $plugin = "App::Cmd::Command::$plugin_name";
292 79         205 Class::Load::load_class($plugin);
293 79         4103 for my $command (map { lc } $plugin->command_names) {
  191         471  
294 191   33     881 $plugin_href->{$command} //= $plugin;
295             }
296             }
297             }
298              
299             #pod =method run
300             #pod
301             #pod $cmd->run;
302             #pod
303             #pod This method runs the application. If called the class, it will instantiate a
304             #pod new App::Cmd object to run.
305             #pod
306             #pod It determines the requested command (generally by consuming the first
307             #pod command-line argument), finds the plugin to handle that command, parses the
308             #pod remaining arguments according to that plugin's rules, and runs the plugin.
309             #pod
310             #pod It passes the contents of the global argument array (C<@ARGV>) to
311             #pod L>, but C<@ARGV> is not altered by running an App::Cmd.
312             #pod
313             #pod =cut
314              
315             sub run {
316 25     25 1 6373 my ($self) = @_;
317              
318             # We should probably use Class::Default.
319 25 50       84 $self = $self->new unless ref $self;
320              
321             # prepare the command we're going to run...
322 25         89 my @argv = $self->prepare_args();
323 25         118 my ($cmd, $opt, @args) = $self->prepare_command(@argv);
324              
325             # ...and then run it
326 23         117 $self->execute_command($cmd, $opt, @args);
327             }
328              
329             #pod =method prepare_args
330             #pod
331             #pod Normally App::Cmd uses C<@ARGV> for its commandline arguments. You can override
332             #pod this method to change that behavior for testing or otherwise.
333             #pod
334             #pod =cut
335              
336             sub prepare_args {
337 25     25 1 57 my ($self) = @_;
338 25 100       106 return scalar(@ARGV)
339             ? (@ARGV)
340             : ($self->default_args->@*);
341             }
342              
343             #pod =method default_args
344             #pod
345             #pod If C> is not changed and there are no arguments in C<@ARGV>,
346             #pod this method is called and should return an arrayref to be used as the arguments
347             #pod to the program. By default, it returns an empty arrayref.
348             #pod
349             #pod =cut
350              
351 17     17   141 use constant default_args => [];
  17         33  
  17         31254  
352              
353             #pod =method abstract
354             #pod
355             #pod sub abstract { "command description" }
356             #pod
357             #pod Defines the command abstract: a short description that will be printed in the
358             #pod main command options list.
359             #pod
360             #pod =method description
361             #pod
362             #pod sub description { "Long description" }
363             #pod
364             #pod Defines a longer command description that will be shown when the user asks for
365             #pod help on a specific command.
366             #pod
367             #pod =method arg0
368             #pod
369             #pod =method full_arg0
370             #pod
371             #pod my $program_name = $app->arg0;
372             #pod
373             #pod my $full_program_name = $app->full_arg0;
374             #pod
375             #pod These methods return the name of the program invoked to run this application.
376             #pod This is determined by inspecting C<$0> when the App::Cmd object is
377             #pod instantiated, so it's probably correct, but doing weird things with App::Cmd
378             #pod could lead to weird values from these methods.
379             #pod
380             #pod If the program was run like this:
381             #pod
382             #pod knight!rjbs$ ~/bin/rpg dice 3d6
383             #pod
384             #pod Then the methods return:
385             #pod
386             #pod arg0 - rpg
387             #pod full_arg0 - /Users/rjbs/bin/rpg
388             #pod
389             #pod These values are captured when the App::Cmd object is created, so it is safe to
390             #pod assign to C<$0> later.
391             #pod
392             #pod =cut
393              
394 2     2 1 10 sub arg0 { $_[0]->{arg0} }
395 2     2 1 15 sub full_arg0 { $_[0]->{full_arg0} }
396              
397             #pod =method prepare_command
398             #pod
399             #pod my ($cmd, $opt, @args) = $app->prepare_command(@ARGV);
400             #pod
401             #pod This method will load the plugin for the requested command, use its options to
402             #pod parse the command line arguments, and eventually return everything necessary to
403             #pod actually execute the command.
404             #pod
405             #pod =cut
406              
407             sub prepare_command {
408 32     32 1 176 my ($self, @args) = @_;
409              
410             # figure out first-level dispatch
411 32         121 my ($command, $opt, @sub_args) = $self->get_command(@args);
412              
413             # set up the global options (which we just determined)
414 31         139 $self->set_global_options($opt);
415              
416             # find its plugin or else call default plugin (default default is help)
417 31 50       75 if ($command) {
418 31         143 $self->_prepare_command($command, $opt, @sub_args);
419             } else {
420 0         0 $self->_prepare_default_command($opt, @sub_args);
421             }
422             }
423              
424             sub _prepare_command {
425 33     33   103 my ($self, $command, $opt, @args) = @_;
426 33 100       102 if (my $plugin = $self->plugin_for($command)) {
427 32         302 return $plugin->prepare($self, @args);
428             } else {
429 1         24 return $self->_bad_command($command, $opt, @args);
430             }
431             }
432              
433             sub _prepare_default_command {
434 1     1   3 my ($self, $opt, @sub_args) = @_;
435 1         5 $self->_prepare_command($self->default_command, $opt, @sub_args);
436             }
437              
438             sub _bad_command {
439 1     1   4 my ($self, $command, $opt, @args) = @_;
440 1 50       8 print "Unrecognized command: $command.\n\nUsage:\n" if defined($command);
441              
442             # This should be class data so that, in Bizarro World, two App::Cmds will not
443             # conflict.
444 1         18 our $_bad++;
445 1         6 $self->prepare_command(qw(commands --stderr));
446             }
447              
448 17 50   17   30156 END { exit 1 if our $_bad };
449              
450             #pod =method default_command
451             #pod
452             #pod This method returns the name of the command to run if none is given on the
453             #pod command line. The default default is "help"
454             #pod
455             #pod =cut
456              
457 1     1 1 5 sub default_command { "help" }
458              
459             #pod =method execute_command
460             #pod
461             #pod $app->execute_command($cmd, \%opt, @args);
462             #pod
463             #pod This method will invoke C and then C on C<$cmd>.
464             #pod
465             #pod =cut
466              
467             sub execute_command {
468 23     23 1 70 my ($self, $cmd, $opt, @args) = @_;
469              
470 23         45 local our $active_cmd = $cmd;
471              
472 23         144 $cmd->validate_args($opt, \@args);
473 22         85 $cmd->execute($opt, \@args);
474             }
475              
476             #pod =method plugin_search_path
477             #pod
478             #pod This method returns the plugin_search_path as set. The default implementation,
479             #pod if called on "YourApp::Cmd" will return "YourApp::Cmd::Command"
480             #pod
481             #pod This is a method because it's fun to override it with, for example:
482             #pod
483             #pod use constant plugin_search_path => __PACKAGE__;
484             #pod
485             #pod =cut
486              
487             sub _default_command_base {
488 25     25   49 my ($self) = @_;
489 25   66     121 my $class = ref $self || $self;
490 25         81 return "$class\::Command";
491             }
492              
493             sub _default_plugin_base {
494 10     10   36 my ($self) = @_;
495 10   66     56 my $class = ref $self || $self;
496 10         54 return "$class\::Plugin";
497             }
498              
499             sub plugin_search_path {
500 10     10 1 38 my ($self) = @_;
501              
502 10         36 my $dcb = $self->_default_command_base;
503 10 100       59 my $ccb = $dcb eq 'App::Cmd::Command'
504             ? $self->App::Cmd::_default_command_base
505             : $self->_default_command_base;
506              
507 10         54 my @default = ($ccb, $self->_default_plugin_base);
508              
509 10 100       78 if (ref $self) {
510 8   50     96 return $self->{plugin_search_path} //= \@default;
511             } else {
512 2         13 return \@default;
513             }
514             }
515              
516             #pod =method allow_any_unambiguous_abbrev
517             #pod
518             #pod If this method returns true (which, by default, it does I), then any
519             #pod unambiguous abbreviation for a registered command name will be allowed as a
520             #pod means to use that command. For example, given the following commands:
521             #pod
522             #pod reticulate
523             #pod reload
524             #pod rasterize
525             #pod
526             #pod Then the user could use C for C or C for C and
527             #pod so on.
528             #pod
529             #pod =cut
530              
531 28     28 1 118 sub allow_any_unambiguous_abbrev { return 0 }
532              
533             #pod =method global_options
534             #pod
535             #pod if ($cmd->app->global_options->{verbose}) { ... }
536             #pod
537             #pod This method returns the running application's global options as a hashref. If
538             #pod there are no options specified, an empty hashref is returned.
539             #pod
540             #pod =cut
541              
542             sub global_options {
543 2     2 1 11 my $self = shift;
544 2 50 50     20 return $self->{global_options} //= {} if ref $self;
545 0         0 return {};
546             }
547              
548             #pod =method set_global_options
549             #pod
550             #pod $app->set_global_options(\%opt);
551             #pod
552             #pod This method sets the global options.
553             #pod
554             #pod =cut
555              
556             sub set_global_options {
557 33     33 1 67 my ($self, $opt) = @_;
558 33         69 return $self->{global_options} = $opt;
559             }
560              
561             #pod =method command_names
562             #pod
563             #pod my @names = $cmd->command_names;
564             #pod
565             #pod This returns the commands names which the App::Cmd object will handle.
566             #pod
567             #pod =cut
568              
569             sub command_names {
570 6     6 1 592 my ($self) = @_;
571 6         28 keys $self->_command->%*;
572             }
573              
574             #pod =method command_groups
575             #pod
576             #pod my @groups = $cmd->commands_groups;
577             #pod
578             #pod This method can be implemented to return a grouped list of command names with
579             #pod optional headers. Each group is given as arrayref and each header as string.
580             #pod If an empty list is returned, the commands plugin will show two groups without
581             #pod headers: the first group is for the "help" and "commands" commands, and all
582             #pod other commands are in the second group.
583             #pod
584             #pod =cut
585              
586       4 1   sub command_groups { }
587              
588             #pod =method command_plugins
589             #pod
590             #pod my @plugins = $cmd->command_plugins;
591             #pod
592             #pod This method returns the package names of the plugins that implement the
593             #pod App::Cmd object's commands.
594             #pod
595             #pod =cut
596              
597             sub command_plugins {
598 8     8 1 21 my ($self) = @_;
599 8         22 my %seen = map {; $_ => 1 } values $self->_command->%*;
  90         160  
600 8         72 keys %seen;
601             }
602              
603             #pod =method plugin_for
604             #pod
605             #pod my $plugin = $cmd->plugin_for($command);
606             #pod
607             #pod This method returns the plugin (module) for the given command. If no plugin
608             #pod implements the command, it returns false.
609             #pod
610             #pod =cut
611              
612             sub plugin_for {
613 73     73 1 140 my ($self, $command) = @_;
614 73 50       213 return unless $command;
615 73 100       184 return unless exists $self->_command->{ $command };
616              
617 70         155 return $self->_command->{ $command };
618             }
619              
620             #pod =method get_command
621             #pod
622             #pod my ($command_name, $opt, @args) = $app->get_command(@args);
623             #pod
624             #pod Process arguments and into a command name and (optional) global options.
625             #pod
626             #pod =cut
627              
628             sub get_command {
629 34     34 1 83 my ($self, @args) = @_;
630              
631 34         139 my ($opt, $args, %fields)
632             = $self->_process_args(\@args, $self->_global_option_processing_params);
633              
634             # map --help to help command
635 33 100       267 if ($opt->{help}) {
636 2         7 unshift @$args, 'help';
637 2         7 delete $opt->{help};
638             }
639              
640 33         154 my ($command, $rest) = $self->_cmd_from_args($args);
641              
642 33         100 $self->{usage} = $fields{usage};
643              
644 33         137 return ($command, $opt, @$rest);
645             }
646              
647             sub _cmd_from_args {
648 27     27   62 my ($self, $args) = @_;
649              
650 27         53 my $command = shift @$args;
651 27         70 return ($command, $args);
652             }
653              
654             sub _global_option_processing_params {
655 34     34   72 my ($self, @args) = @_;
656              
657             return (
658 34         122 $self->usage_desc(@args),
659             $self->global_opt_spec(@args),
660             { getopt_conf => $self->_getopt_conf },
661             );
662             }
663              
664             sub _getopt_conf {
665 31     31   271 return [qw/pass_through/];
666             }
667              
668             #pod =method usage
669             #pod
670             #pod print $self->app->usage->text;
671             #pod
672             #pod Returns the usage object for the global options.
673             #pod
674             #pod =cut
675              
676 1     1 1 4 sub usage { $_[0]{usage} };
677              
678             #pod =method usage_desc
679             #pod
680             #pod The top level usage line. Looks something like
681             #pod
682             #pod "yourapp [options]"
683             #pod
684             #pod =cut
685              
686             sub usage_desc {
687             # my ($self) = @_; # no point in creating these ops, just to toss $self
688 32     32 1 105 return "%c %o";
689             }
690              
691             #pod =method global_opt_spec
692             #pod
693             #pod Returns a list with help command unless C has been specified or
694             #pod an empty list. Can be overridden for pre-dispatch option processing. This is
695             #pod useful for flags like --verbose.
696             #pod
697             #pod =cut
698              
699             sub global_opt_spec {
700 30     30 1 54 my ($self) = @_;
701              
702 30         56 my $cmd = $self->{command};
703 30         44 my %seen;
704 120         325 my @help = grep { ! $seen{$_}++ }
705 120         368 reverse sort map { s/^--?//; $_ }
  120         335  
706 30         143 grep { $cmd->{$_} eq 'App::Cmd::Command::help' } keys %$cmd;
  322         572  
707              
708 30 50       269 return (@help ? [ join('|', @help) => "show help" ] : ());
709             }
710              
711             #pod =method usage_error
712             #pod
713             #pod $self->usage_error("Something's wrong!");
714             #pod
715             #pod Used to die with nice usage output, during C.
716             #pod
717             #pod =cut
718              
719             sub usage_error {
720 0     0 1 0 my ($self, $error) = @_;
721 0         0 die "Error: $error\nUsage: " . $self->_usage_text;
722             }
723              
724             sub _usage_text {
725 1     1   4 my ($self) = @_;
726 1         6 my $text = $self->usage->text;
727 1         192 $text =~ s/\A(\s+)/!/;
728 1         4 return $text;
729             }
730              
731             #pod =head1 TODO
732             #pod
733             #pod =for :list
734             #pod * publish and bring in Log::Speak (simple quiet/verbose output)
735             #pod * publish and use our internal enhanced describe_options
736             #pod * publish and use our improved simple input routines
737             #pod
738             #pod =cut
739              
740             1;
741              
742             __END__