Re: how to deal with 20 commands
by Zaxo (Archbishop) on May 23, 2005 at 02:33 UTC
|
Use a dispatch table, a hash with your commands as keys and code references as values,
my %dispatch = (
start => sub {
my @args = @_;
# . . .
},
# . . .
);
while (<STDIN>) {
my ($cmd, @args) = split;
exists $dispatch{$cmd}
or warn 'Unknown command: ', $cmd and next;
$dispatch{$cmd}(@args);
}
| [reply] [d/l] |
Re: how to deal with 20 commands
by sk (Curate) on May 23, 2005 at 02:33 UTC
|
If it is going to be a simple system commmand like ls, cp etc. you might just be able to get away by having the 20 commands in a Hash... Simple commands first argument is a command itself and you can split on space to get that command and check it in your Hash...
I am sure there might be other ways to do it but creating an interactive mini-shell might be tricky...for example how do you handle pipes? How do you handle built in functions that throw a message to the user? Remove file xyz (y/n)?: Are you going to parse wild cards or let the shell deal with it?etc.
If you just want to restrict the commands a user should type you can consider restricting the file perm for the commands that they shouldn't be using. However that does not mean they will have a restrictive shell...
cheers
SK | [reply] |
Re: how to deal with 20 commands
by davidrw (Prior) on May 23, 2005 at 02:37 UTC
|
I don't know if this is the best way (perhaps there's a module to help maintain this kind of thing?), but you could use something like this with an array of the possible commands.. The array lets you fix the order the cmds are checked for (perhaps putting the common ones first), and if you capture in the regex, the captured values will be pased as parameters to the sub when it's invoked. Below is a working proof of concept:
use strict;
use warnings;
my @CMDS = (
{ regex => qr/^cp\s+(\S+)\s+(\S+)/, code => \&do_cp },
{ regex => qr/^mv\s+(\S+)\s+(\S+)/, code => \&do_mv },
);
my $input_string = <STDIN>;
foreach my $cmd ( @CMDS ){
my @match = ($input_string =~ /$cmd->{regex}/) or next;
$cmd->{code}( @match );
}
sub do_cp {
my $src = shift;
my $dest = shift;
warn "cp $src $dest";
}
sub do_mv {
my $src = shift;
my $dest = shift;
warn "mv $src $dest";
}
| [reply] [d/l] |
|
|
thanks for all the help.
what i am looking for is some thing which works the same way as the module GetOpt::Long or STD works. they parse the command line swtiches and the programmer doesnt habe to worry about if the switches have been types correctly or not
so is there some thing which can do the same for commands too?
| [reply] |
|
|
local @ARGV = @_;
GetOptions( # . . .
) or warn 'Whatever';
| [reply] [d/l] |
|
|
|
|
|
|
|
| [reply] [d/l] |
Re: how to deal with 20 commands
by redhotpenguin (Deacon) on May 23, 2005 at 05:14 UTC
|
| [reply] |
Re: how to deal with 20 commands
by salva (Canon) on May 23, 2005 at 19:37 UTC
|
The worst thing about long if-elsif-else chains is their performance, but you are talking about an interactive aplication, so you don't need to worry about performance and chained if-elsif-else's will not be so bad.
Anyway, let my suggest an alternative OO aproach: define a class for every command you support, i.e.: MyApp::Command::ls, MyApp::Command::cp, etc.
Then, in every command class define the set of methods you need, i.e. parse_args(), run(), print_output(), etc.
And then use the perl OO notation to dispatch commands:
while(read_cmd()} {
eval {
$cmd_name=~/^\w+/ or die "invalid command";
my $cmd_class = "MyApp::Command::$command_name";
my $cmd = eval { require $cmd_class; $cmd_class->new };
if ($@) die "unknow command $cmd_name ($@)\n";
$cmd->parse_args(@args) or die "...";
$cmd->run(@args) or die "...";
etc();
};
print $@ if $@;
}
This way, adding new commands is very easy, just create new classes for them and drop them on the rigth directory. It also allows for simple code reuse via inheritance.
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: how to deal with 20 commands
by dwijew (Initiate) on May 23, 2005 at 02:30 UTC
|
you can use a switch statement i think. in my opinion its better than 20 if statements! | [reply] |
|
|
Never, never recommend Switch.pm. It's a source filter that has serious bugs and is likely to break your code.
| [reply] [d/l] |
|
|
| [reply] [d/l] |