File Coverage

lib/Devel/Trepan/CmdProcessor/Command/Subcmd/Subsubcmd.pm
Criterion Covered Total %
statement 70 142 49.3
branch 4 32 12.5
condition 2 5 40.0
subroutine 18 34 52.9
pod n/a
total 94 213 44.1


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2013 Rocky Bernstein <rocky@cpan.org>
3             # A base class for debugger subcommands.
4             #
5 12     12   82 use Exporter;
  12         32  
  12         532  
6 12     12   78 use warnings;
  12         40  
  12         312  
7 12     12   62 no warnings 'redefine';
  12         37  
  12         332  
8              
9 12     12   67 use rlib '../../../../..';
  12         28  
  12         70  
10 12     12   5215 use Devel::Trepan::CmdProcessor::Command::Subcmd::Core;
  12         33  
  12         559  
11              
12             package Devel::Trepan::CmdProcessor::Command::Subsubcmd;
13 12     12   81 use Devel::Trepan::CmdProcessor::Validate;
  12         30  
  12         573  
14              
15             BEGIN {
16 12     12   219 @SUBCMD_VARS = qw($HELP $IN_LIST $RUN_CMD $MIN_ABBREV
17             $NAME $SHORT_HELP @SUBCMD_VARS
18             @SUBCMD_ISA);
19             }
20 12     12   119 use strict;
  12         29  
  12         507  
21              
22             my $NotImplementedMessage =
23             "This method must be overridden in a subsubclass";
24              
25 12     12   71 use vars qw(@SUBCMD_VARS @EXPORT @ISA @SUBCMD_ISA);
  12         34  
  12         803  
26 12     12   153 use vars @SUBCMD_VARS;
  12         31  
  12         1238  
27             @ISA = qw(Exporter);
28              
29             @SUBCMD_ISA = qw(Devel::Trepan::CmdProcessor::Command::Subsubcmd);
30             @EXPORT = @SUBCMD_VARS;
31              
32             # attr_reader :name
33              
34             $IN_LIST = 1; # Show item in help list of commands
35             $RUN_CMD = 1; # Run subcommand for those subcommands like "show"
36             # which append current settings to list output.
37 12     12   83 use constant MIN_ARGS => 0;
  12         31  
  12         912  
38 12     12   76 use constant MAX_ARGS => 0;
  12         27  
  12         607  
39             $MIN_ABBREV = 1;
40 12     12   69 use constant NEED_STACK => 0;
  12         34  
  12         13470  
41             $NAME = 'your_command_name';
42              
43              
44             # $cmd contains the command object that this
45             # command is invoked through. A debugger field gives access to
46             # the stack frame and I/O.
47             sub new($$$)
48             {
49 431     431   1565 my ($class, $parent, $name) = @_;
50 431         1541 my $self = {parent => $parent};
51              
52             # Convenience class access. We don't expect that any of these
53             # will change over the course of the program execution like
54             # errmsg(), msg(), and msg_nocr() might. (See the note below
55             # on these latter 3 methods.)
56             #
57 431         1368 $self->{dbgr} = $parent->{dbgr};
58 431         1676 $self->{proc} = $parent->{proc};
59              
60             # FIXME: Inheritence of vars is not working the way I had hoped.
61             # So this is a workaround.
62 431         992 my $base_prefix="Devel::Trepan::CmdProcessor::Command::Subcmd::";
63 431         1345 for my $field (@SUBCMD_VARS) {
64 3448         9681 my $sigil = substr($field, 0, 1);
65 3448 50       10897 my $new_field = index('$@', $sigil) >= 0 ? substr($field, 1) : $field;
66 3448 100       9433 if ($sigil eq '$') {
    50          
67 2586         138225 $self->{lc $new_field} =
68             eval "\$${class}::${new_field} || \$${base_prefix}${new_field}";
69             } elsif ($sigil eq '@') {
70 862         42728 $self->{lc $new_field} = eval "[\@${class}::${new_field}]";
71             } else {
72 0         0 die "Woah - bad sigil: $sigil";
73             }
74             }
75             # Done after above since $NAME is in @SUBCMD_VARS;
76 431         1393 $self->{name} = $name;
77 431   66     1766 $self->{short_help} ||= $self->{help};
78 431         1269 bless $self, $class;
79 431         3164 $self->set_name_prefix($class);
80 431         12629 $self;
81             }
82              
83             # Convenience short-hand for @proc.confirm
84             sub confirm($$;$) {
85 0     0   0 my ($self, $msg, $default) = @_;
86 0         0 return($self->{proc}->confirm($msg, $default));
87             }
88              
89             # Set a Boolean-valued debugger setting.
90             sub run_set_bool($$;$)
91             {
92 0     0   0 my ($self, $args, $default) = @_;
93 0 0       0 $default = 1 if scalar @_ < 3;
94 0 0       0 my $onoff_arg = @$args < 4 ? 'on' : $args->[3];
95 0         0 my $key = $self->{subcmd_setting_key};
96 0         0 $self->{proc}{settings}{$key} = $self->{proc}->get_onoff($onoff_arg);
97 0         0 $self->run_show_bool();
98             }
99              
100             # set an Integer-valued debugger setting.
101             sub run_set_int($$$;$$)
102             {
103 0     0   0 my ($self, $arg, $msg_on_error, $min_value, $max_value) = @_;
104 0         0 my $proc = $self->{proc};
105 0 0       0 if ($arg =~/^\s*$/) {
106 0         0 $proc->errmsg('You need to supply a number.');
107 0         0 return undef;
108             }
109 0         0 my $val = $proc->get_an_int($arg,
110             {max_value => $max_value,
111             min_value => $min_value,
112             msg_on_error => $msg_on_error
113             });
114 0 0       0 if (defined ($val)) {
115 0         0 my $subcmd_setting_key = $self->{subcmd_setting_key};
116 0         0 $proc->{settings}{$subcmd_setting_key} = $val;
117 0         0 $self->run_show_int();
118             }
119             }
120              
121             # Generic subcommand showing a boolean-valued debugger setting.
122             sub run_show_bool($;$)
123             {
124 0     0   0 my ($self, $what) = @_;
125 0         0 my $proc = $self->{proc};
126 0         0 my $key = $self->{subcmd_setting_key};
127 0         0 my $val = $self->show_onoff($proc->{settings}{$key});
128 0 0       0 $what = $self->{cmd_str} unless $what;
129 0         0 $proc->msg(sprintf "%s is %s.", $what, $val);
130             }
131              
132             # Generic subcommand integer value display
133             sub run_show_int($;$)
134             {
135 0     0   0 my ($self, $what) = @_;
136 0         0 my $proc = $self->{proc};
137 0         0 my $subcmd_setting_key = $self->{subcmd_setting_key};
138 0         0 my $val = $proc->{settings}{$subcmd_setting_key};
139 0 0       0 $what = $self->{cmd_str} unless ($what);
140 0         0 $proc->msg(sprintf "%s is %d.", $what, $val);
141             }
142              
143             # Generic subcommand value display. Pass in a hash which may
144             # which optionally contain:
145             #
146             # :name - the String name of key in settings to use. If :value
147             # (described below) is set, then setting :name does
148             # nothing.
149             #
150             # :what - the String name of what we are showing. If none is
151             # given, then we use the part of the SHORT_HELP string.
152             #
153             # :value - a String value associated with "what" above. If none
154             # is given, then we pick up the value from settings.
155             #
156             sub run_show_val($;$)
157             {
158 0     0   0 my ($self, $opts) = @_;
159 0   0     0 $opts ||= {};
160 0 0       0 my $what = exists $opts->{what} ? $opts->{what} : $self->{string_in_show};
161 0 0       0 my $name = exists $opts->{name} ? $opts->{name} : $self->{name};
162 0 0       0 my $val = exists $opts->{value} ? $opts->{value} : $self->{settings}{$name};
163 0         0 my $msg = sprintf("%s is %s.", $what, $val);
164 0         0 $self->msg($msg);
165             }
166              
167             # sub save_command_from_settings
168             # ["${subcmd_prefix_string} ${settings[subcmd_setting_key]}"]
169             # }
170              
171             sub subcmd_prefix_string($)
172             {
173 0     0   0 my $self = shift;
174 0         0 join(' ', $self->{prefix});
175             }
176              
177             sub subcmd_setting_key($)
178             {
179 0     0   0 my $self = shift;
180 0 0       0 return $self->{subcmd_setting_key} if $self->{subcmd_setting_key};
181 0         0 my @prefix = @{$self->{prefix}}; shift @prefix;
  0         0  
  0         0  
182 0         0 $self->{subcmd_setting_key} = join('', @prefix);
183             }
184              
185             # Return 'on' for true and 'off' for false, and ?? for anything else.
186             sub show_onoff($$)
187             {
188 0     0   0 my ($self, $bool) = @_;
189 0 0       0 if (!defined($bool)) {
    0          
190 0         0 return 'unset';
191             } elsif ($bool) {
192 0         0 return 'on';
193             } else {
194 0         0 return 'off'
195             }
196             }
197              
198             sub set_name_prefix($$)
199             {
200 431     431   1277 my ($self, $class) = @_;
201 431         3031 my @prefix = split(/::/, $class);
202 431         1454 splice(@prefix, 0, 4); # Remove Devel::Trepan::CmdProcessor::Command
203 431         1239 @prefix = map {lc $_} @prefix;
  1293         4100  
204 431         2822 $self->{prefix} = \@prefix;
205 431         1945 $self->{cmd_str} = join(' ', @prefix);
206 431         1704 $self->{subcmd_setting_key} = "$prefix[1]$prefix[2]";
207             }
208              
209             sub string_in_show($)
210             {
211 0     0     my ($self, $bool) = @_;
212 0           my $skip_len = length('Show ');
213 0           ucfirst substr($self->{short_help}, $skip_len);
214             }
215              
216             sub summary_help($$)
217             {
218 0     0     my ($self, $subcmd_name) = @_;
219 0           my $msg = sprintf("%-12s: %s", $subcmd_name, $self->{short_help});
220 0           $self->msg_nocr($msg);
221             }
222              
223              
224             package Devel::Trepan::CmdProcessor::Command::SetBoolSubsubcmd;
225 12     12   100 use vars qw(@ISA);
  12         38  
  12         2437  
226             @ISA = qw(Exporter Devel::Trepan::CmdProcessor::Command::Subsubcmd);
227              
228             our $MIN_ARGS = 0;
229             our $MAX_ARGS = 1;
230              
231             sub complete($$)
232             {
233 0     0     my ($self, $prefix) = @_;
234 0           Devel::Trepan::Complete::complete_token(['on', 'off'],
235             $prefix);
236             }
237              
238             sub run($$) {
239 0     0     my ($self, $args) = @_;
240 0           $self->run_set_bool($args);
241             }
242              
243             sub save_command($) {
244 0     0     my ($self) = @_;
245 0           my %settings = $self->{settings};
246 0 0         my $val = $settings{$self->subcmd_setting_key()} ? 'on' : 'off';
247 0           [$self->subcmd_prefix_string . " ${val}"];
248             }
249              
250             package Devel::Trepan::CmdProcessor::Command::ShowBoolSubsubcmd;
251 12     12   94 use vars qw(@ISA);
  12         29  
  12         1065  
252             @ISA = qw(Exporter Devel::Trepan::CmdProcessor::Command::Subsubcmd);
253              
254             sub run($)
255             {
256 0     0     my ($self, $args) = @_;
257 0           $self->run_show_bool($self->string_in_show());
258             }
259              
260             package Devel::Trepan::CmdProcessor::Command::ShowIntSubsubcmd;
261 12     12   82 use vars qw(@ISA);
  12         32  
  12         1474  
262             @ISA = qw(Exporter Devel::Trepan::CmdProcessor::Command::Subsubcmd);
263              
264             sub run($) {
265 0     0     my ($self, $args) = @_;
266 0           my $doc = $self->{short_help};
267 0           my $len = length($doc) - 5;
268 0           $doc = ucfirst substr($doc, 5, $len);
269 0           $self->run_show_int($doc);
270             }
271              
272             unless (caller) {
273             # Demo it.
274             # require Devel::Trepan::CmdProcessor::Mock;
275             # my $proc = Devel::Trepan::CmdProcessor::Mock::setup();
276             # my %cmds = %{$proc->{commands}};
277             # print join(', ', keys %cmds), "\n";
278             # my $subcmd =
279             # Devel::Trepan::CmdProcessor::Command::Subcmd->new($cmds{'quit'});
280             # print join(', ', keys %{$subcmd->{settings}}), "\n";
281             # print $subcmd->show_onoff($subcmd->{settings}{autoeval}), "\n";
282             # $subcmd->run_set_int($proc, 'Just a test');
283             }
284              
285             1;