I am not aware of of any modules to automate user configuration files that can be over-ridden on the command line. (I would be interested to know of any). A few years ago I wrote some code to do it myself, which I am pasting here.
The basic code to read command a config file, and allow that config to be overridden from the command line uses Getopt::Long, with a bit of extra code to first read the config from a file, and then allow the config hash to be over-ridden on the command line:
sub getArgs
{
# 1. Declare internal defaults to use for any atributes not on the
+ command line or in the user's preferences.
# Format is: name (hash key), default value, comment (for the stor
+ed config file).
my $user_prefs_file = $HOME.'/.application_name.prefs';
my @system_defaults =
(
[ 'verbose', 1, "The Verbosenes. The script should
+ be silent if verbose=0" ],
[ 'parse_schedule_file', 1, "If true, parse the schedule file"
+ ],
# ... etc.
);
# Setup the raw options from the system defaults.
my $raw_opts;
my $user_prefs = readDataFile( $user_prefs_file ); # Load user
+preferences, & over write defaults.
foreach my $ent ( @$system_defaults )
{
my($key, $value, $comment) = @$ent; # The comment is no
+t used at this stage.
if( defined $user_prefs->{$key} )
{
$raw_opts->{$key} = $user_prefs->{$key};
}
else
{
$raw_opts->{$key} = $value;
}
}
# 3. Parse the command line, overiting options from the user prefs
+ & internal defaults.
my $store_prefs;
$raw_opts->{'store_prefs'} = \$store_prefs;
$raw_opts->{'help'} = sub{ pod2usage(-verbose=>0) };
$raw_opts->{'man'} = sub{ pod2usage(-verbose=>2, -exitstat
+us => 0 ) };
# Use the store in hash form op GetOptions, with references to exc
+eptions setup above.
GetOptions( $raw_opts,
'help|h','man','verbose!','store_prefs','flush_cache', 'parse_
+schedule_file!',
# ... etc.
) or pod2usage(-verbose=>0, -message => "incorect options");
# Store the updated user preferences if required.
if( $store_prefs )
{
store_user_prefs( $raw_opts, $user_prefs_file, $system_default
+s );
}
# Delete special references
delete $raw_opts->{'store_prefs'};
delete $raw_opts->{'help'};
delete $raw_opts->{'man'};
# All done, return
return $raw_opts;
}
sub readDataFile
{
# Reads a perl data structure from a file.
my( $fileName ) = @_;
return undef unless -r $fileName; # Quick check the file exits.
open INFILE, "<", $fileName or die "Error, unable to read $fileNam
+e $!";
my $fileText = join('', <INFILE> );
close INFILE;
return eval( $fileText );
}
In my case, I also needed to allow users to save their prefereces back to the configuration file, so there is an extra bit of code to save preferences in a human readable file format with comments on each field:
sub store_user_prefs
{
my ( $raw_opts, # Options hash, amalgamanted from syst
+em defaults, prevously stored preferences, and the command line.
$user_prefs_file, # File to store the option in.
$system_defaults, # System defaults. Used to provide an
+ordered list of options to store with comments to store against them.
) = @_;
open OPTS, '>', $user_prefs_file or die "Error saving preferences
+in $user_prefs_file, $!";
print OPTS "#!/bin/perl\n";
print OPTS "#\n";
print OPTS "# user preferences file. Edit with care.\n";
print OPTS "\n{\n";
foreach my $ent ( @$system_defaults )
{
my($key, $value, $comment) = @$ent;
print OPTS " # $comment\n";
if( 'ARRAY' eq ref $raw_opts->{$key} )
{
my $list = '\''.join('\', \'', @{$raw_opts->{$key}} ).'\''
+;
printf OPTS " '%s' => [%s],\n\n", $key, $list;
}
elsif( 'HASH' eq ref $raw_opts->{$key} )
{
printf OPTS " '%s' => {\n", $key;
printf OPTS " '%s' => '%s',\n", $_, $raw_opts->{$ke
+y}{$_} foreach keys %{$raw_opts->{$key}};
print OPTS " },\n\n";
}
elsif( ref $raw_opts->{$key} )
{
# Something else, probably the cookie jar. Use data dumper
+.
my $dumpedInfo = Dumper( $raw_opts->{$key} );
$dumpedInfo =~ s/\$VAR1 = //;
$dumpedInfo =~ s/;$/,/;
printf OPTS " '%s' => %s\n", $key, $dumpedInfo,
}
else
{
# plain string, number etc.
if( defined $raw_opts->{$key} )
{
printf OPTS " '%s' => '%s',\n\n", $key, $raw_opts->
+{$key};
}
else
{
printf OPTS " '%s' => undef,\n\n", $key;
}
}
}
print OPTS "};\n\n";
close OPTS;
return;
}
In the code above I have stripped out some of the error checking for compactness. I hope it is clear and useful to you. |