Frage

I have a module misc which is used by a few scripts. Each script accept two standard options (-help and -verbose) as well as a bunch of its own ones.

So, every scripts now has

my ($verbose,$quiet) = (1,0);
my $help = undef;
...
GetOptions("verbose|v+" => \$verbose, "quiet|q+" => \$quiet, "help|h" => \$help,
           ....)
  or die "GetOptions: error (see above)\n";
if (defined $help) { usage(); exit; }
$verbose -= $quiet;

which is already boring.

Now, I want the misc functions to be aware of the value of $verbose too, so I have to move $verbose et al to misc and use $misc::verbose in scripts:

misc:

our $verbose = 1;
my $quiet = 0;
our $help = undef;
our %common_options = ("verbose|v+" => \$verbose, "quiet|q+" => \$quiet, "help|h" => \$help);
sub set_verbose () { $verbose -= $quiet; }

script:

GetOptions(\%misc::common_options,"verbose|v","quiet|q","help|h",
           "count=i" => \$count, "start=i" => \$start, "mincoverage=i" => \$mincoverage,
           "output=s" => \$output, "input=s" => \$input, "targets=s" => \$targets)
  or die "GetOptions: error (see above)\n";
if (defined $misc::help) { usage(); exit; }
misc::set_verbose();

which does not look much better (and appears to not work anyway, at least -help is ignored).

So, what do people use for command line options shared between modules and scripts?

War es hilfreich?

Lösung

Personally, I do it simpler:

  • use a hash to store command line options

      GetOptions(\%args, "xxx1","xxx2");
    
  • Pass that hash - as is - to ANY classes' constructrs, or module setters

      my $object = Class1->new(%args, %constructor_args);
      Module2::set_args(\%args); # 
    
  • Argument setter in the module would be:

      # Module2
      our %args;
      sub set_args { %args = %{ shift }; }
    

This ensures that:

  • I NEVER have to worry about moving parameters from scope to scope and having to modify some calls. They are ALL passed around 100% of needed places

  • Neat and non-messy code. Since we are broadcasting, we don't need to worry about subscribers' individual needs.

  • Pattern easily replicated to ALL classes you own.

As a matter of fact, if you want to be extra crafty, you can even replace Module2::set_args(\%args); calls for several classes with a smart code that:

  1. Reads in a list of loaded modules

  2. Checks which of those modules implements set_args() call via UNIVERSAL::can()

  3. Calls the supporting modules' set_args() call

The latter makes the code even cleaner, in that N calls to set_args() one for each non-class module is are all replaced by one set_all_modules_args() call.

Andere Tipps

Have a module that's responsible for getting standard options.

Use this module, and everyone will be able to access the verbose() call.

package StandardOptions;


use base qw(Exporter);
our @EXPORT = qw(verbose);

use Getopt::Long;

Getopt::Long::Configure(qw(pass_through));


my $helpNeeded;
my $verbose
GetOptions ("help" => \$helpNeeded, "verbose" => $verbose);


if ($helpNeeded) {
    #provide help
    exit(0);
}

sub verbose {
   return $verbose;
}

1;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top