http://www.perlmonks.org?node_id=882180

samwyse has asked for the wisdom of the Perl Monks concerning the following question:

Let's say that 'bheerdb' is an interface to an external data store. It has a bunch of options that are typically used in a few standard patterns. I'd like to save a bunch of typing by aliasing 'bheerdb' to various names and using $0 to set appropriate defaults for getopt. For example, 'create-tap duff' should set defaults '--action create' and '--type domestic', while 'update-tap --class premium duff' should only set a default of '--action update'.

The aliases I'm using are all 'verb-objtype' and some defaults depend on the verb, some on objtype, and a few actually depend on both. I guess I need some sort of decision table, but Re^3: Burned by precedence rules is the only Perlmonks discussion that even mentions the subject. I don't want to write a bunch of wrapper scripts, because I occasionally need to change the default values, and I don't want to have to change a bunch of scripts. So if anyone has any ideas, I'd appreciate hearing them.

BTW, as I was writing my question, I realized that what I need is similar to something usually found in text adventure games, where there's a generic response to some commands, which can be overridden by both the object and the room you're in. I guess I'll look into that as well.

Replies are listed 'Best First'.
Re: Set getopt defaults based on $0
by tilly (Archbishop) on Jan 13, 2011 at 18:04 UTC
    Using Getopt::Long you can do this by having a section where you declare all of your variables, a second one where you initialize them with default values, then call GetOptions, then have your main script.

    So you can do something like this.

    my ($action, $type, $foo, (other variables)); my $name = $0; $name =~ s~.*/~~; my ($verb, $object) = split /-/, $name; $action = $verb; # Case statement for defaults for verb. # Case statement for defaults for object. # Case statement for defaults for name (combines verb + object) GetOptions( "action=s" => \$action, "type=s" => \$type, "foo=i" => \$foo, ... ); and more program
    If you're using Perl 5.10 or better you can use feature "switch"; at the beginning and then:
    given($object) { when ("tap") {$type = "domestic"} .... }
Re: Set getopt defaults based on $0
by ikegami (Patriarch) on Jan 13, 2011 at 17:56 UTC
    use File::Basename qw( basename ); my $opt_action; my $opt_type; my %rules = ( "create-tap" => sub { $opt_action = 'create'; $opt_type = 'domestic +'; }, ... "*" => sub { $opt_action = $_[0]; }, ); my ($verb, $object) = split(/-/, basename($0)); my $handler = $rules{"$verb-$object"} || $rules{"$verb-"} || $rules{"-$object"} || $rules{"*-}; $handler->($verb, $object) if $handler; ...process the options...
Re: Set getopt defaults based on $0
by hsinclai (Deacon) on Jan 13, 2011 at 17:45 UTC
    Maybe this (dispatch tables) can help ?


Re: Set getopt defaults based on $0
by Anonyrnous Monk (Hermit) on Jan 13, 2011 at 18:58 UTC

    Another variation with Getopt::Long and hash tables to declare the defaults:

    #!/usr/bin/perl -w use strict; use Getopt::Long; my ($verb, $obj) = $0 =~ m|([^/]+)-([^/]+)$|; my %defaults_verbs = ( 'create' => { foo => "foo", bar => "", }, 'update' => { foo => "", bar => "bar", }, #... ); my %defaults_objs = ( 'tap' => { baz => 42, }, 'fap' => { baz => 99, }, #... ); my %defaults_combined = ( 'create-tap' => { foo => "boo", baz => 13, }, #... ); # merge individual defaults hashrefs (order matters), e.g.: my $opts = { %{ $defaults_verbs{$verb} //{} }, %{ $defaults_objs{$obj} //{} }, %{ $defaults_combined{"$verb-$obj"} //{} }, }; GetOptions($opts, 'foo=s', 'bar=s', 'baz=i'); for my $opt (sort keys %$opts) { print "$opt=$opts->{$opt}\n"; }
    $ for name in create-tap update-tap ; do ln -s 882180.pl $name ; done $ ./create-tap bar= baz=13 foo=boo $ ./create-tap --foo=FOO bar= baz=13 foo=FOO $ ./update-tap bar=bar baz=42 foo= $ ./update-tap --baz=55 bar=bar baz=55 foo=