File Coverage

blib/lib/Cmd/Interpreter.pm
Criterion Covered Total %
statement 20 89 22.4
branch 0 32 0.0
condition n/a
subroutine 7 22 31.8
pod 8 15 53.3
total 35 158 22.1


line stmt bran cond sub pod time code
1             package Cmd::Interpreter;
2 1     1   826 use 5.008001;
  1         4  
3 1     1   6 use strict;
  1         2  
  1         41  
4 1     1   21 use warnings;
  1         2  
  1         45  
5              
6 1     1   768 use Term::ReadLine;
  1         3366  
  1         117  
7              
8             our $VERSION = "0.3.3";
9              
10 1     1   7 use constant IDENT_CHARS => join '', 'a'..'z', 'A'..'Z', '0' .. '9', '_';
  1         2  
  1         103  
11 1     1   5 use constant PROG_NAME => 'Simple command interpreter';
  1         2  
  1         61  
12 1     1   5 use constant PROMPT => 'cmd> ';
  1         2  
  1         1054  
13              
14              
15             sub new {
16 0     0 0   my $class = shift;
17 0           my %args = @_;
18              
19 0           my $self = {
20             prog_name => PROG_NAME,
21             prompt => PROMPT,
22             last_cmd => '',
23             %args
24             };
25              
26 0           return bless $self, $class;
27             }
28              
29              
30             sub run {
31 0     0 0   my $self = shift;
32              
33 0           $self->pre_loop();
34 0           $self->loop(@_);
35 0           $self->post_loop();
36             }
37              
38              
39             sub loop {
40 0     0 0   my $self = shift;
41 0           my $intro = shift;
42              
43 0 0         print "$intro\n" if $intro;
44              
45 0           my $term = Term::ReadLine->new($self->{prog_name});
46 0           my $stop = '';
47              
48 0           while (1) {
49 0           my $line = $term->readline($self->{prompt});
50              
51 0           $line = $self->pre_cmd($line);
52 0           $stop = $self->do_cmd($line);
53 0           $stop = $self->post_cmd($stop, $line);
54              
55 0 0         last if $stop;
56             }
57             }
58              
59              
60       0 1   sub pre_loop {
61             }
62              
63              
64       0 1   sub post_loop {
65             }
66              
67              
68             sub pre_cmd {
69 0     0 1   my $self = shift;
70              
71 0           return shift;
72             }
73              
74              
75             sub post_cmd {
76 0     0 1   my $self = shift;
77              
78 0           return shift;
79             }
80              
81              
82       0 1   sub default_action {
83             }
84              
85              
86             sub empty_line {
87 0     0 1   my $self = shift;
88              
89 0 0         return $self->do_cmd($self->{last_cmd}) if $self->{last_cmd};
90 0           return '';
91             }
92              
93              
94             sub no_input {
95 0     0 1   my $self = shift;
96              
97 0           print "\n";
98              
99 0           return "no_input";
100             }
101              
102              
103             sub do_help {
104 0     0 0   my $self = shift;
105 0           my $topic = shift;
106              
107 0 0         if ($topic) {
108 0           my $sub = "help_$topic";
109              
110 0 0         if ($self->check_sub($sub)) {
111 0           return $self->$sub();
112             }
113              
114 0           print "There is no help for '$topic'\n";
115             } else {
116 0           my $sub = "help";
117              
118 0 0         if ($self->check_sub($sub)) {
119 0           return $self->$sub();
120             }
121              
122 0           print "Please try: '?command' or 'help command'\n";
123             }
124              
125 0           return '';
126             }
127              
128              
129             sub do_shell {
130 0     0 1   my $self = shift;
131 0           my $cmd = shift;
132              
133 0 0         if ($cmd) {
134 0           print `$cmd`;
135             } else {
136 0           print "Please use: '!command [args]' or 'shell command [args]'\n";
137             }
138              
139 0           return '';
140             }
141              
142              
143             sub do_cmd {
144 0     0 0   my $self = shift;
145              
146 0 0         return $self->no_input() unless defined $_[0];
147              
148 0           my ($cmd, $args, $line) = $self->parse_line(shift);
149              
150 0 0         return $self->empty_line() unless $line;
151 0 0         return $self->default_action() unless $cmd;
152              
153 0           my $sub = $self->check_sub("do_$cmd");
154              
155 0 0         return $self->default_action($cmd, $args) unless $sub;
156              
157 0           $self->{last_cmd} = $line;
158              
159 0           return $self->$sub($args);
160             }
161              
162              
163             sub check_sub {
164 0     0 0   my $self = shift;
165 0           my $sub = shift;
166              
167 0 0         return $self->can($sub) ? $sub : '';
168             }
169              
170              
171             sub parse_line {
172 0     0 0   my $self = shift;
173 0           my $line = shift;
174              
175 0           chomp $line;
176              
177 0 0         return ('', '', $line) unless $line;
178              
179 0 0         if ($line =~ /\?(.*)/) {
    0          
180 0           $line = "help $1";
181             } elsif ($line =~ /!(.*)/) {
182 0           $line = "shell $1";
183             }
184              
185 0 0         return ($1, $2, $line) if $line =~ /^([@{[IDENT_CHARS]}]+)\s*(.*)\s*$/;
  0            
186 0           return ('', '', $line);
187             }
188              
189              
190             1;
191             __END__