File Coverage

blib/lib/App/CmdDispatch/Help.pm
Criterion Covered Total %
statement 110 110 100.0
branch 58 62 93.5
condition 8 11 72.7
subroutine 25 25 100.0
pod 5 5 100.0
total 206 213 96.7


line stmt bran cond sub pod time code
1             package App::CmdDispatch::Help;
2              
3 9     9   38651 use warnings;
  9         18  
  9         352  
4 9     9   45 use strict;
  9         16  
  9         20283  
5              
6             our $VERSION = '0.42';
7              
8             sub new
9             {
10 39     39 1 2325 my ( $class, $owner, $commands, $config ) = @_;
11 39   100     124 $config ||= {};
12 39 100       149 die "Command definition is not a hashref.\n" unless ref $commands eq ref {};
13 37 100       68 die "No commands specified.\n" unless keys %{$commands};
  37         134  
14 36 100       121 die "Config parameter is not a hashref.\n" unless ref $config eq ref {};
15 35 100       94 die "Invalid owner object.\n" unless eval { $owner->isa( 'App::CmdDispatch' ); };
  35         252  
16 34         103 _extend_table_with_help( $commands );
17 34         88 my %conf = (
18             indent_hint => ' ',
19             indent_help => ' ',
20             _extract_config_parm( $config, 'indent_hint' ),
21             _extract_config_parm( $config, 'pre_hint' ),
22             _extract_config_parm( $config, 'post_hint' ),
23             _extract_config_parm( $config, 'indent_help' ),
24             _extract_config_parm( $config, 'pre_help' ),
25             _extract_config_parm( $config, 'post_help' ),
26             );
27 34         324 return bless { owner => $owner, %conf }, $class;
28             }
29              
30             sub _extract_config_parm
31             {
32 204     204   270 my ( $config, $parm ) = @_;
33 204 100       953 return unless defined $config->{"help:$parm"};
34 6         234 return ( $parm => $config->{"help:$parm"} );
35             }
36              
37             sub _extend_table_with_help
38             {
39 34     34   55 my ( $commands ) = @_;
40 34         170 $commands->{help} = {
41             code => \&_dispatch_help,
42             clue => "help [command|alias]",
43             abstract => 'Display complete help',
44             help => "Display help about commands and/or aliases. Limit display with the\nargument.",
45             };
46 34         160 $commands->{hint} = {
47             code => \&_dispatch_hint,
48             clue => "hint [command|alias]",
49             abstract => 'Display command hints',
50             help => 'A list of commands and/or aliases. Limit display with the argument.',
51             };
52 34         62 return;
53             }
54              
55             sub _dispatch_help
56             {
57 22     22   30 my $owner = shift;
58 22         64 return $owner->{_helper}->help( @_ );
59             }
60              
61             sub _dispatch_hint
62             {
63 24     24   34 my $owner = shift;
64 24         82 return $owner->{_helper}->hint( @_ );
65             }
66              
67             sub _hint_string
68             {
69 80     80   130 my ( $self, $cmd, $maxlen ) = @_;
70 80         213 my $desc = $self->_table->get_command( $cmd );
71 80 50       193 return '' unless $desc;
72 80 100       263 my $indent = ( $maxlen ? ' ' x ( 3 + $maxlen - length $desc->{clue} ) : ' ' );
73 80 100       480 return $desc->{clue} . ( $desc->{abstract} ? $indent . $desc->{abstract} : '' );
74             }
75              
76             sub _clue_string
77             {
78 55     55   121 my ( $self, $cmd ) = @_;
79 55         94 my $desc = $self->_table->get_command( $cmd );
80 55 50       120 return '' unless $desc;
81 55         173 return $desc->{clue};
82             }
83              
84             sub _alias_hint
85             {
86 16     16   35 my ($self, $alias) = @_;
87 16         47 return "$alias\t: " . $self->_table->get_alias( $alias );
88             }
89              
90             sub _help_string
91             {
92 55     55   71 my ( $self, $cmd ) = @_;
93 55         93 my $desc = $self->_table->get_command( $cmd );
94              
95 55 100       141 return '' unless defined $desc->{help};
96 54         154 return join( "\n", map { $self->{indent_help} . $_ } split /\n/, $desc->{help} );
  65         328  
97             }
98              
99             sub _list_command
100             {
101 39     39   67 my ( $self, $code ) = @_;
102 39         92 $self->_print( "\nCommands:\n" );
103 39         434 foreach my $c ( $self->{owner}->command_list() )
104             {
105             # The following should not be possible. But I'll keep this until
106             # I'm absolutely certain.
107 125 50 33     975 next if $c eq '' or !$self->_table->get_command( $c );
108 125         300 $self->_print( $code->( $c ) );
109             }
110 39         369 return;
111             }
112              
113             sub _list_aliases
114             {
115 39     39   56 my ( $self ) = @_;
116 39 100       96 return unless $self->_table->has_aliases;
117              
118 11         39 $self->_print( "\nAliases:\n" );
119 11         87 foreach my $c ( $self->{owner}->alias_list() )
120             {
121 14         65 $self->_print( $self->{indent_hint} . $self->_alias_hint( $c ) . "\n" );
122             }
123 11         89 return;
124             }
125              
126 61   100 61   356 sub _is_missing { return !defined $_[0] || $_[0] eq ''; }
127              
128             sub _get_abstract_offset
129             {
130 23     23   41 my ( $self ) = @_;
131              
132 23         37 my $maxlen = 0;
133 23         28 my $len;
134 23         56 foreach my $cmd ( $self->_table->command_list() )
135             {
136 76         152 $len = length $self->_table->get_command( $cmd )->{clue};
137 76 100       234 $maxlen = $len if $len > $maxlen;
138             }
139 23         67 return $maxlen;
140             }
141              
142             sub hint
143             {
144 33     33 1 103 my ( $self, $arg ) = @_;
145              
146 33 100       82 if( _is_missing( $arg ) )
147             {
148 20         286 my $maxlen = $self->_get_abstract_offset();
149 20 100       94 $self->_print( "\n$self->{pre_hint}\n" ) if $self->{pre_hint};
150             $self->_list_command(
151 20     64   156 sub { $self->{indent_hint}, $self->_hint_string( $_[0], $maxlen ), "\n"; } );
  64         198  
152 20         100 $self->_list_aliases();
153 20 100       70 $self->_print( "\n$self->{post_hint}\n" ) if $self->{post_hint};
154 20         94 return;
155             }
156              
157 13 100       44 if( $self->_table->get_command( $arg ) )
    100          
    100          
    100          
158             {
159 4         16 $self->_print( "\n", $self->_hint_string( $arg ), "\n" );
160             }
161             elsif( $self->_table->get_alias( $arg ) )
162             {
163 1         3 $self->_print( "\n", $self->_alias_hint( $arg ), "\n" );
164             }
165             elsif( $arg eq 'commands' )
166             {
167 3         12 my $maxlen = $self->_get_abstract_offset();
168 3     12   25 $self->_list_command( sub { $self->{indent_hint}, $self->_hint_string( $_[0], $maxlen ), "\n"; } );
  12         41  
169             }
170             elsif( $arg eq 'aliases' )
171             {
172 3         326 $self->_list_aliases();
173             }
174             else
175             {
176 2         9 $self->_print( "Unrecognized command '$arg'\n" );
177             }
178              
179 13         83 return;
180             }
181              
182             sub help
183             {
184 28     28 1 87 my ( $self, $arg ) = @_;
185              
186 28 100       59 if( _is_missing( $arg ) )
187             {
188 13 100       37 $self->_print( "\n$self->{pre_help}\n" ) if $self->{pre_help};
189             $self->_list_command(
190             sub {
191 37     37   93 $self->{indent_hint}, $self->_clue_string( $_[0] ), "\n",
192             $self->_help_string( $_[0] ), "\n";
193             }
194 13         75 );
195 13         61 $self->_list_aliases();
196 13 100       42 $self->_print( "\n$self->{post_help}\n" ) if $self->{post_help};
197 13         33 return;
198             }
199              
200 15 100       41 if( $self->_table->get_command( $arg ) )
    100          
    100          
    100          
201             {
202 6   66     20 $self->_print( "\n", $self->_clue_string( $arg ),
203             "\n", ( $self->_help_string( $arg ) || $self->{indent_help} . "No help for '$arg'" ),
204             "\n" );
205             }
206             elsif( $self->_table->get_alias( $arg ) )
207             {
208 1         4 $self->_print( "\n", $self->_alias_hint( $arg ), "\n" );
209             }
210             elsif( $arg eq 'commands' )
211             {
212             $self->_list_command(
213             sub {
214 12     12   34 $self->{indent_hint}, $self->_clue_string( $_[0] ), "\n",
215             $self->_help_string( $_[0] ), "\n";
216             }
217 3         17 );
218             }
219             elsif( $arg eq 'aliases' )
220             {
221 3         10 $self->_list_aliases();
222             }
223             else
224             {
225 2         8 $self->_print( "Unrecognized command '$arg'\n" );
226             }
227              
228 15         98 return;
229             }
230              
231             sub normalize_command_help
232             {
233 22     22 1 36 my ( $self, $table ) = @_;
234 22         73 foreach my $cmd ( $table->command_list )
235             {
236 87         236 my $desc = $table->get_command( $cmd );
237 87 100       266 $desc->{clue} = $cmd unless defined $desc->{clue};
238 87 50       242 $desc->{hint} = '' unless defined $desc->{hint};
239 87 100       234 $desc->{help} = '' unless defined $desc->{help};
240             }
241 22         77 return;
242             }
243              
244             sub sort_commands
245             {
246 31 100   31 1 386 return ( sort grep { $_ ne 'hint' && $_ ne 'help' } @_ ), 'hint', 'help';
  123         655  
247             }
248              
249             sub _print
250             {
251 209     209   298 my ( $self ) = shift;
252 209         750 return $self->{owner}->_print( @_ );
253             }
254              
255 515     515   1989 sub _table { return $_[0]->{owner}->{table}; }
256              
257             1;
258             __END__