in reply to simpliest way to add "language" to my app

Something that's relatively simple is to have a hash, with the keys being the command, and the values being anonymous subroutines.

my %command= ( shutdown => sub { print "Shutting down...\n"; exit 0; }, lock_user => sub { my ($user) = @_; # Insert code to lock $user here. }, unlock_user => sub { my ($user) = @_; # Insert code here to unlock $user }, show => sub { # Insert show code here }, lock => sub { $_ = shift; if ($command{lock_$_}) { $command{lock_$_}->(@_); } else { die "Don't know how to lock $_\n"; } }, unlock => sub { $_ = shift; if ($command{unlock_$_}) { $command{unlock_$_}->(@_); } else { die "Don't know how to unlock $_\n"; } }, help => sub {# update per L~R's suggestion: print "Current commands: "; print join "\n", sort { $a cmp $b } keys %command; }, ); my ($cmd, @args) = @ARGV; # Or however you get them. $cmd = lc $cmd; # Force lowercase per L~R's suggestion. my $sub = $command{$cmd}; $sub = $command{help} if not defined $sub; $sub->(@args);

$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/

Replies are listed 'Best First'.
Re: Re: simpliest way to add "language" to my app
by Limbic~Region (Chancellor) on Oct 05, 2003 at 04:03 UTC
    jonadab,
    Depending on how forgiving and user friendly smackdab wants to be, your solution can be improved:
  • Pass raw data to parsing sub
  • If match found, execute accordingly
  • If match not found, give user a list of currently supported commands

    The parsing sub may do things like:

  • Force lower case
  • Change (un)?lock user (un)?lock_user
  • Allow synonyms such as halt for shutdown
  • Regular expressions to handle common typos
  • Append non matches to a log for further analysis to help improve parsing routine

    The only other thing that I would suggest is changing the key assignment from anonymous subs to named subs.

    shutdown => sub { print "Shutting down...\n"; exit 0; } becomes shutdown => \&shutdown
    Cheers - L~R
      Pass raw data to parsing sub

      Well, he said the simplest way...

      If match not found, give user a list of currently supported commands

      Now, that would certainly be a worthwhile enhancement. And easy enough to do, too.

      Force lower case

      I almost included that... but for some reason I didn't. Perhaps I should have.

      Allow synonyms such as halt for shutdown

      That may be the best argument for the named subs you mention, actually.


      $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
        Thanks these are helpful to look at.

        I am currently using one big switch in a ParseCmd() fn, which is easier for me as each "response" is short.

        What is a mess is validating that each command has the correct number of parameters before I call it. Come to think about it I guess each command fn could exit with an "invalid command" error if there are missing params...I see that your approach handles this much better that what I am doing...just pass an array for the "rest" of the params (if any)

        Still a little wordy if I add 50 commands in the future...but simple!

        thanks