Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Minimum command length matcher

by jcwren (Prior)
on Aug 29, 2000 at 18:44 UTC ( #30139=sourcecode: print w/ replies, xml ) Need Help??

Category: Miscellaneous
Author/Contact Info jcwren
jcwren@jcwren.com
Description: I write a fair number of programs that use interactive commands. I intensely dislike programs that require me to type more than the minimum number of characters to distinguish one command from another. I also dislike have to have special parameters that instruct the command interpeter what portion of the command is unique.

To that end, this snippet takes a hash of commands, keyed by the command name, and the user input, and finds the minimum match. Errors are no matches, or ambiguous matches, in which case an error message with the list of commands is returned. If no error, the full name of the hash is returned.
#!/usr/local/bin/perl -w

use strict;
use Carp;

my %Commands = ('who'      => \&do_who,
                'what'     => \&do_what,
                'why'      => \&do_why,
                'never'    => \&do_never,
                'again'    => \&do_again,
                'answer'   => \&do_answer);

{
   my $userinput = $ARGV[0];

   my ($errmsg, $command) = check_commands (\%Commands, $userinput);

   if ($errmsg)
   {
      print "$errmsg\n";
      exit;
   }

   &{$Commands {$command}};
}

sub check_commands
{
   @_ == 2 or croak "Incorrect number of parameters";
   
   my ($cmdhash, $command) = @_;
   
   my @matches = grep /^$command/i, sort keys %$cmdhash;
   
   if (scalar @matches == 0)
   {
      return ("I don't know what '$command' means", undef);
   }
   elsif (scalar @matches > 1)
   {
      my $lastcmd = pop @matches;

      return ("'$command' is ambigous.  It could mean " . join (', ', 
+@matches) . " or $lastcmd", undef);
   }
   
   return (undef, $matches [0]);
}

sub do_who     {print "Who\n"};
sub do_what    {print "What\n"};
sub do_why     {print "Why\n"};
sub do_never   {print "Never\n"};
sub do_again   {print "Again\n"};
sub do_answer  {print "Answer\n"};

Comment on Minimum command length matcher
Download Code
RE: Minimum command length matcher
by KM (Priest) on Aug 29, 2000 at 18:53 UTC
    You could easily take this one step further and give it the ability to then accept which command the user meant (like some shells do). By changing the 'ambiguous match' (you have it 'ambigous', BTW) part to create a hash. Actually, if you make @matched into %matched with the structure of:

    %matches = (1 => 'match1', 2 => 'match2', etc... );

    You could then make the 'ambiguous match' section as which was meant.. ie..

    'monkey' is ambiguous. It could mean monkeylover [1] or monkeyman [2]:

    The user would then enter 1 or 2, you read it on STDIN, and run the correct sub. Just an idea :)

    Cheers,
    KM

Back to Code Catacombs

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://30139]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (7)
As of 2014-12-19 00:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (69 votes), past polls