File Coverage

lib/Devel/Trepan/CmdProcessor/Load.pm
Criterion Covered Total %
statement 67 76 88.1
branch 14 28 50.0
condition 1 3 33.3
subroutine 12 12 100.0
pod 0 5 0.0
total 94 124 75.8


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2012, 2014 Rocky Bernstein <rocky@cpan.org>
3              
4             # Part of Devel::Trepan::CmdProcessor that loads up debugger commands from
5             # builtin and user directories.
6             # Sets @commands, @aliases, @macros
7 12     12   35763 use rlib '../../..';
  12         35  
  12         90  
8              
9             package Devel::Trepan::CmdProcessor;
10             $Load_seen = 1;
11 12     12   4579 use warnings; use strict;
  12     12   34  
  12         349  
  12         162  
  12         27  
  12         298  
12 12     12   111 no warnings 'redefine';
  12         41  
  12         412  
13              
14 12     12   67 use File::Spec;
  12         33  
  12         282  
15 12     12   71 use File::Basename;
  12         33  
  12         913  
16 12     12   110 use Cwd 'abs_path';
  12         31  
  12         10202  
17              
18             =head2 load_cmds_initialize
19              
20             load_debugger_commands($self) -> undef
21              
22             Loads in our built-in commands.
23              
24             Called from Devel::Trepan::CmdProcessor->new in CmdProcessor.pm
25             =cut
26              
27             sub load_cmds_initialize($)
28             {
29 13     13 0 39 my $self = shift;
30 13         59 $self->{commands} = {};
31 13         60 $self->{aliases} = {};
32 13         49 $self->{macros} = {};
33              
34             my @cmd_dirs = (
35             File::Spec->catfile(dirname(__FILE__), 'Command'),
36 13         1345 @{$self->{settings}{cmddir}}
  13         93  
37             );
38 13         69 for my $cmd_dir (@cmd_dirs) {
39 13 50       581 $self->load_debugger_commands($cmd_dir) if -d $cmd_dir;
40             }
41             }
42              
43             =head2 load_debugger_commands
44              
45             load_debugger_commands($self, $file_or_dir) -> @errors
46              
47             Loads in debugger commands by require'ing each Perl file in the
48             'command' directory. Then a new instance of each class of the
49             form Trepan::xxCommand is added to @commands and that array
50             is returned.
51             =cut
52             sub load_debugger_commands($$)
53             {
54 13     13 0 72 my ($self, $file_or_dir) = @_;
55 13         59 my @errors = ();
56 13 50       262 if ( -d $file_or_dir ) {
    0          
57 13         1027 my $dir = abs_path($file_or_dir);
58             # change $0 so it doesn't get in the way of __FILE__ eq $0
59             # old_dollar0 = $0
60             # $0 = ''
61 13         8143 for my $pm (glob(File::Spec->catfile($dir, '*.pm'))) {
62 494         1792 my $err = $self->load_debugger_command($pm);
63 494 50       1912 push @errors, $err if $err;
64             }
65             # $0 = old_dollar0
66             } elsif (-r $file_or_dir) {
67 0         0 my $err = $self->load_debugger_command($file_or_dir);
68 0 0       0 push @errors, $err if $err;
69             }
70 13         192 return @errors;
71             }
72              
73             =head2 load_debugger_command
74              
75             load_debugger_command($self, $command_file, [$force])
76              
77             Loads a debugger command. Returns a string containing the error or '' if no error.
78             =cut
79              
80             sub load_debugger_command($$;$)
81             {
82 494     494 0 1529 my ($self, $command_file, $force) = @_;
83 494 50       14737 return unless -r $command_file;
84 494         1374 my $rc = '';
85 494         1067 eval { $rc = do $command_file; };
  494         177900  
86 494 50 33     4357 if (!$rc or $rc eq 'Skip me!') {
    50          
87 0         0 return 'skipped';
88             } elsif ($rc) {
89             # Instantiate each Command class found by the above require(s).
90 494         16501 my $name = basename($command_file, '.pm');
91 494         2450 return $self->setup_command($name);
92             } else {
93 0         0 my $errmsg = "Trouble reading ${command_file}: $@";
94 0         0 $self->errmsg($errmsg);
95 0         0 return $errmsg;
96             }
97             }
98              
99             =head2 run_cmd
100              
101             run_cmd($self, $cmd_arry)
102              
103             Looks up cmd_array[0] in @commands and runs that. We do lots of
104             validity testing on cmd_array.
105              
106             =cut
107             sub run_cmd($$)
108             {
109 3     3 0 2590 my ($self, $cmd_array) = @_;
110 3 100       14 unless ('ARRAY' eq ref $cmd_array) {
111 1 50       5 my $ref_msg = ref($cmd_array) ? ", got: " . ref($cmd_array): '';
112 1         7 $self->errmsg("run_cmd argument should be an Array reference$ref_msg");
113 1         4 return;
114             }
115             # if ($cmd_array.detect{|item| !item.is_a?(String)}) {
116             # $self ->errmsg("run_cmd argument Array should only contain strings. " .
117             # "Got #{cmd_array.inspect}");
118             # return;
119             # }
120 2 100       7 if (0 == scalar @$cmd_array) {
121 1         7 $self->errmsg("run_cmd Array should have at least one item");
122 1         3 return;
123             }
124 1         3 my $cmd_name = $cmd_array->[0];
125 1 50       4 if (exists($self->{commands}{$cmd_name})) {
126 1         7 $self->{commands}{$cmd_name}->run($cmd_array);
127             }
128             }
129              
130             # sub save_commands(opts)
131             # {
132             # save_filename = opts[:filename] ||
133             # File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(['trepanning-save', '.txt'], nil))
134             # begin
135             # save_file = File.open(save_filename, 'w')
136             # rescue => exc
137             # errmsg("Can't open #{save_filename} for writing.")
138             # errmsg("System reports: #{exc.inspect}")
139             # return nil
140             # }
141             # save_file.print "#\n# Commands to restore trepanning environment\n#\n"
142             # @commands.each do |cmd_name, cmd_obj|
143             # cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
144             # next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
145             # cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
146             # save_file.print subcmd_obj.save_command if
147             # subcmd_obj.respond_to?(:save_command)
148             # next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
149             # subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
150             # save_file.print subsubcmd_obj.save_command if
151             # subsubcmd_obj.respond_to?(:save_command)
152             # }
153             # }
154             # }
155             # save_file.print "!FileUtils.rm #{save_filename.inspect}" if
156             # opts[:erase]
157             # save_file.close
158              
159             # return save_filename
160             # }
161              
162             =head2 setup_command
163              
164             setup_command($self, $name)
165              
166             Instantiate a Devel::Trepan::Command and extract info: the NAME, ALIASES
167             and store the command in @commands.
168             =cut
169             sub setup_command($$)
170             {
171 494     494 0 1456 my ($self, $name) = @_;
172 494         957 my $cmd_obj;
173 494         1173 my $cmd_name = lc $name;
174 494         1464 my $new_cmd = "\$cmd_obj=Devel::Trepan::CmdProcessor::Command::${name}" .
175             "->new(\$self, \$cmd_name); 1";
176 494 50       34218 if (eval $new_cmd) {
177             # Add to list of commands and aliases.
178 494 50       3572 if ($cmd_obj->{aliases}) {
179 494         1225 for my $a (@{$cmd_obj->{aliases}}) {
  494         1666  
180 559         2372 $self->{aliases}{$a} = $cmd_name;
181             }
182             }
183 494         2560 $self->{commands}{$cmd_name} = $cmd_obj;
184 494         2897 return '';
185             } else {
186 0           $self->errmsg("Error instantiating $name");
187 0           $self->errmsg($@);
188 0           return $@;
189             }
190             }
191              
192             unless (caller) {
193             require Devel::Trepan::CmdProcessor;
194             my $cmdproc = Devel::Trepan::CmdProcessor->new;
195             require Array::Columnize;
196             my @cmds = sort keys(%{$cmdproc->{commands}});
197             print Array::Columnize::columnize(\@cmds);
198             my $sep = '=' x 20 . "\n";
199             print $sep;
200             my @aliases = sort keys(%{$cmdproc->{aliases}});
201             print Array::Columnize::columnize(\@aliases);
202             print $sep;
203              
204             $cmdproc->run_cmd('foo'); # Invalid - not an Array
205             $cmdproc->run_cmd([]); # Invalid - empty Array
206             $cmdproc->run_cmd(['help', '*']);
207             # $cmdproc->run_cmd(['list', 5]); # Invalid - nonstring arg
208             }
209              
210             1;