The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Config::Param - all you want to do with parameters for your program (or someone else's)

SYNOPSIS

Just use the module,

        use Config::Param;

define your parameters in the simplest form of a flat array, possibly directly in the call to the parser,

        # the definitions in flat array
        # predefined by default: help / h and config / I
        my $parm_ref = Config::Param::get
        (
           'parm1', $default1,  'a', 'help text for scalar 1'
          ,'parm2', $default2,  'b', 'help text for scalar 2'
          ,'parmA', \@defaultA, 'A', 'help text for array A'
          ,'parmH', \%defaultH, 'H', 'help text for hash H'
          ,'parmX', $defaultX,  '', 'help text for last one (scalar)'
        );

or go about this in a more structured way with extra tweaks.

        my $flags = $Config::Param:arg|$Config::Param:count;
        my @pardef =
        (
          [ 'parm1', $default1,  'a', 'some scalar parameter' ]
        , [ 'parm2', $default2,  'b', 'a counted switch', $flags ]
        , { long=>'parmA', value=>[], short=>'A'
          , help=>'help text for array A,', arg=>'element', flags=>$flags }
        , [ 'parmH', \@defaultH, 'H', 'help text for hash H', 'prop=val', $flags ]
        , [ 'parmX', $defaultX,  '', 'help text for last one (scalar)' ]
        );
        $parm_ref = Config::Param::get(\@pardef);

The result is a hash reference with the long parameter names as keys and containing the values after processing the command line.

        print "Value of parameter 'parm1': $parm_ref->{parm1}\n";
        print "Contents of array 'parmA': ".( defined $parm_ref->{parmA}
        ? join(",", @{$parm_ref->{parmA}})
        : "<undefined>" )."\n";

There could be some extra configuration.

        my %config =
        (
          'info' => 'program info text'
        ,  'version' => '1.2.3'
        ,  'flags' => $Config::Param:count # default flags for all parameters
           # possibly more
        );
        $parm_ref = Config::Param::get(\%config, \@pardef);

The command-line arguments to use instead of @ARGV can also be provided.

        $parm_ref = Config::Param::get(\%config,\@pardef,\@cmdline_args);

The most complicated call is this, making only sense when disabling final exit:

        $config{noexit} = 1; # or nofinals
        $parm_ref = Config::Param::get(\%config,\@pardef,\@cmdline_args, $errors);

This will return a count of errors encountered (bad setup, bad command line args). With default configuration, the routine would not return on error, but end the program. Errors will be mentioned to STDERR in any case.

Finally, you can use a Config::Param object to do what Config::Param::get does:

        # equivalent to
        # $parm_ref = Config::Param::get(\%config,\@pardef);
        my $pars = Config::Param->new(\%config, \@pardef);
        my $bad = not (
                    $pars->good()
                and $pars->parse_args(\@ARGV)
                and $pars->use_config_files()
                and $pars->apply_args()
        );
        $pars->final_action($bad);
        $parm_ref = $pars->{param};

DESCRIPTION

The basic task is to take some description of offered parameters and return a hash ref with values for these parameters, influenced by the command line and/or configuration files. The simple loop from many years ago now is about the most comprehensive solution for a program's param space that I am aware of, while still supporting the one-shot usage via a single function call and a flat description of parameters.

The module handles command line options to set program parameters, defining and handling standard options for generating helpful usage messages, and parses as well as generates configuration files. Furthermore, it can generate program documentation in POD form, the other way round from other approaches that use your written POD to generate parameter help.

The syntax for single-letter options follows the recommendations of IEEE Std 1003.1-2017 (12. Utility Conventions), with

command [options] [--] [operands]

indicating a generic command line. All parameters are required to have a long name, which is used for GNU-style long options. A short name (classic POSIX-style) is optional.

Option processing overview

This is a brief overview of ways to provide parameter values via command-line options. See further below for details.

The letter p stands for the short name of the parameter param. When providing values, a prefix of + or ++ works just as - or --.

--param, -p

Identical to --param=1 unless counting for the scalar parameter is enabled, when it is identical to --param+=1 instead.

++param, +p

Identical to --param=0.

--param=value, -p=value

Set parameter value. If the parameter is an array or hash and accumulation is enabled, this is identical to --param.=value.

--param value, -p value, -pvalue

Alternative syntax equivalent to --param=value without equal sign or even whitespace to set the parameter value where a value is mandatory. The last form only works if the value does not conflict with operator syntax (beginning with ., +, -, *, or /) and does not start with an equal sign itself.

-abc, -abc=value, -abc value

Equivalent to -a -b -c, -a -b -c=value, and -a -b -c value, respectively. The last one only works if -c (and only c) requires an argument.

--param.=value, -p.[=]value

Append the given value to the current content of the parameter. For arrays, this appends another entry. For hashes, the value shall be a name-value pair to update the hash.

--param<+|-|*|/>=value, -p<+|-|*|/>[=]value

Perform arithmetic operations on the current scalar parameter value. Examples that all add 3 to the current value:

        --param+=3 -p+=3 -p+3

Arithmetic is not supported for array and hash parameters. The operators are + for addition, - for subtraction, * for multiplication, / for division.

--param/,/=a,b,c, --param/,/ a,b,c, -p/,/[=]a,b,c, -p/,/ a,b,c

Set array parameter to comma-separated list (any single-character separator may be chosen). An argument has to follow, so an equal sign or, for the short option, even any separation is optional.

--param/,/=a=1,b=2, --param/,/ a=1,b=2, -p/,/[=]a=1,b=2, -p/,/ a=1,b=2,

Set hash parameter to comma-separated name-value pairs (any single-character separator besides the equal sign may be chosen). An argument has to follow, so an equal sign or, for the short option, even any separation is optional.

--param//, -p//

Set the array or hash parameter to the empty list/hash. This is different from assigning an empty string, which would create one entry defined by that empty string instead.

Some of the above variants are not supported with the lazy configuration option for reducing the amount of hyphens to type.

Basic option syntax and scalar parameters

This module processes command line options to set program parameters, be it short or long style, supporting clustering of short options. Every parameter has to be given a long option name, while a short (single-letter) one is optional. By default, the form --param=value or -p=value sets an explicit value. Omitting the =value part causes the value 1 (true) being assigned -- or added if the flag $Config::Param::count is in effect.

A parameter can be marked to require an explicit argument using the flag $Config::Param::arg. Then, the forms --param value and -p value as well as -pvalue also are valid syntax, but the forms --param and -p without following value are invalid. If there is no separation to the value, the value itself must not begin with any of =, ., +, -, *, and /.

Also, though somewhat counterintuitive but existing practice and logically following the idea that "-" is true, ++param / +p will set the value to 0 (false). If you specify a value, it does not matter if "-" or "+" is used in front of the name.

The values are stored from the strings of the argument list and interpreted by Perl when you access them. There is no distinction bettwen strings and numbers; those are just scalar values. If you enable switch accumulation, integer arithmetic takes place for counting the number of times the parameter (switch, short or long form) was given: -p -parm -p will be equivalent to --param=3 if the value was previously unset or zero. The form +p will always reset the value to zero.

There is the fundamental problem of deciding if we have a parameter value or some other command-line data like a file name to process. Since this problem still persists with the "=" used in assignment when one considers a file with a name like "--i_look_like_an_option", Config::Param also looks out for -- as a final delimiter for the named parameter part, which is also quite common behaviour.

The command line arguments after "--" stay in the input array (usually @ARGV) and can be used by the calling program. The parsed parameters as well as the optional "--" are removed; so, if you want to retain your @ARGV, just provide a copy.

There is a configuration option that reduces the amount of "-" you need to type, see "lazy" below. It may make sense if your program exclusively takes named parameters with values and does not expect anything else, but it complicates usage by enlarging the variations of syntax.

Arrays and hashes

You can also have hashes or arrays as values for your parameters. The hash/array type is chosen when you provide an (anonymous) hash/array reference as value in the definition.

You can set a whole array by specifying a separator character between forward slashes:

        --array/,/=a,b

This results in the strings "a" and "b" being stored as elements. You can choose any character as separator, even the forward slash itself.

You can also use the concatenation operator .= to append elements, the form

        --array=a --array.=b

being equivalent to the above. Furthermore, if accumulation is enabled ($Config::Param::append), the concatenation operator is implicit, so another way would be

        --array=a --array=b

and finally, if the flag ($Config::Param::arg is active, the equal sign can be omitted, to have

        --array a --array b

result in the same, also for the short names. Without that flag, --array would instead set or append the value 1.

In any setting, you can empty an array or hash using --array// or -a//.

Hash values are set via prefixing a key with following "=" before the actual value:

        --hash=name=value

This sets the whole hash to the single name-value set, or appends such a set if $Config::Param::append is active. To set multiple values in one go, the same logic as for arrays applies:

        --hash/,/=foo=a,bar=b
        --hash=foo=a --hash.=bar=b

If the equal sign is omitted, only a key specified, a hash entry with an undefined value is created. This is the only direct way to actally pass the value undef via the commandline. This is different from --hash=key=, which adds the empty string as value.

A change for fringe cases arised in version 4 of the library: In the past, omitting any argument (just --hash or ++hash) would result in the value 1 or 0 being stored for the key 'truth'. Now, the behaviour is consistent so that --hash does create a hash entry with key 1 and undefined value, like --hash=1 does.

The same logic as for arrays applies regarding $Config::Param::arg and $Config::Param::append. Likewise, hash is also cleared usign --hash// or -H//.

Operators

Apart from simple assignment, the parser offers some basic operators to work on command-line arguments or configuration file entries in succession.

Instead of --param=value you can do do --param.=value to append something to the existing value. When -p is the short form of --param, the same happens through -p.=value or, saving one character, -p.value. The long form needs the full operator, as the dot could be part of a parameter name. So

        --param=a --param.=b -p.c

results in the value of parm being 'abc'.

This is especially important for sanely working with hashes and arrays without $Config::Param::append, where the append operator adds new entries instead of re-setting the whole data structure to the given value. The append operator is also the only operator defined for arrays and hashes. It can be combined with the element splitting,

        --array/:/=a:b --array/-/.=c-d -a/,/.=e,f

resulting in a, b, c, d, e, and f being stored in the array.

There is no advanced parsing with quoting of separator characters --- that's why you can choose an appropriate one so that simple splitting at occurences does the right thing.

The full non-assignment operator consists of an operator character and the equal sign, but the latter can be dropped for the short option form. Apart from concatenation, there are basic arithmetic operators. These plain operators are available:

=value

Direct assignment.

.=value or short .value

String concatenation for scalar parameters, pushing values for array and hash parameters.

+=value or short +value

Addition to scalar value.

-=value or short -value

Substraction from scalar value.

*=value or short *value

Multiplication of scalar value.

/=value or short /value

Division of scalar value.

You can omit the = for the short-form (one-letter) of parameters on the command line when using the extra operators, but not in the configuration file. There it is needed for parser safety. The operators extend to the multiline value parsing in config files, though (see the section on config file syntax).

See the lazy configuration switch for a modified command line syntax, saving you some typing of "-" chars.

Automatic usage/version message creation

Based on the parameter definition Config::Param automatically prints the expected usage/help message when the (predefined!) --help / -h was given, with the info string in advance when defined, and exits the program. You can turn this behaviour off, of course. An example for the generated part of the help message:

        simple v0.0.1 - just a quick hack to demonstrate Config::Paramm
        
        usage:
                examples/simple [parameters] whatever
        
        We have this long info string just to show that Config::Param picks
        the tagline and usage info from it. This is not mandatory.
        
        Generic parameter example (list of real parameters follows):
                simple -s -xyz -s=value --long --long=value [--] [files/stuff]
        
        Just mentioning -s equals -s=1 (true), while +s equals -s=0 (false).
        The separator "--" stops option parsing.
        
        Recognized parameters:
        
        NAME, SHORT VALUE [# DESCRIPTION]
        config, I   [] # Which configfile(s) to use (overriding automatic
                    search in likely paths);
                    special: just -I or --config causes printing a current
                    config file to STDOUT
        help, h ... 1 # Show the help message. Value 1..9: help level, par:
                    help for paramter par (long name) only.
        meter ..... 'I got value but no help text, neither short name.'
        para, p ... 0 # A parameter.
        version ... 0 # print out the program version

Note: When printing to a terminal, Config::Param tries to determine the screen width and does a bit of formatting to help readability of the parameter table.

With the posixhelp option, it looks more traditional:

        simple v0.0.1 - just a quick hack to demonstrate Config::Param
        
        usage:
                examples/simple [parameters] whatever
        
        We have this long info string just to show that Config::Param picks
        the tagline and usage info from it. This is not mandatory.
        
        Short options can be grouped and non-optional arguments can follow
        without equal sign. Force options end with '--'. Switches on with -,
        off with +. See --help=par for details on possible advanced syntax
        with option --par.
        
        -I, --config[=val] Which configfile(s) to use (overriding automatic
                           search in likely paths);
                           special: just -I or --config causes printing a
                           current config file to STDOUT
        -h, --help[=val]   Show the help message. Value 1..9: help level, par:
                           help for paramter par (long name) only.
            --meter[=val]  
        -p, --para[=val]   A parameter.
            --version      print out the program version

This mode makes most sense when you also use parameter flags to augment the definitions, forcing mandatory arguments, marking parameters as switches and counters. If you start to really polish the usage of your program, you might want to consider going down that route for feel more like a good old program with hand-crafted option parsing.

help parameter values

The help parameter interprets given values is specific ways, to squeeze out more functionality of that precious predefined name.

1

Standard compact help, option overview.

name

Print out verbose help for the parameter with the given long option name.

2

More elaborate help including some extra lines about parameter syntax.

3 to 9

Higher levels to allow selections of parameters of increasing obscurity (see the level property in a parameter definition).

-1

List parameter names, comma-separated in a possibly wrapped line.

-2

List parameter names, one on each line.

-3

List parametter names without the built-ins, one on each line.

-10[,]name[,name ...]

Dump values of the provided parameters in a way suitable for evaluation in Perl, as a comma-separated list.

-11[,]name[,name ...]

Dump values in a line-oriented format.

-100

Print the usage documentation as POD, perhaps to pass to pod2man for creating a man page.

Configuration file parsing

The module also introduces a simple but flexible configuration file facility. Configuration means simply setting the same parameters that are available to the command line.

The second and last predefined parameter called "config" (short: I) is for giving a file (or several ones, see below!) to process before the command line options are applied (what the user typed is always the last word). If none is given, some guessing may take place to find an appropriate file (see below). When just -I or --config is given (no =!), then a file with the current configuration ist written to STDOUT and the program exits (unless ignorefinals is set). When you give the lonely -I or --config once, you'll get a explained config file with comments and meta info, when you give the option twice, you get a condensed file with only the raw settings and a small header telling for which program it is.

Config files are parsed before applying command line arguments, so that the latter can override settings.

Configuration file creation

Well, of course the module will also create the configuration files it consumes. Specifying --conf or -I (or your different chosen names) without option argument trigers writing of a configuration file to standard output and exit of the program. This is a trick available only to this special parameter

Configuration file syntax

The syntax of the configuration files is based on simple name and value pairs, similar to INI files (no sections, though you can use dots in parameter names to mimick them). In a configuration file, only the long name of a parameter is used:

        mode = "something"

sets the parameter mode to the value something. Actually,

        mode = something

would do the same. The whitespace around the operator (here: =) and before the line break is ignored. You want to use (double) quotes when defining a value that begins or ends with whitespace:

        mode = " something spacy "

Consequently, you have to use quotes around the value if it starts with a quote character:

        mode = ""something with a quote"

The stuff between the first " and the last " will be used as value (you do not need to quote your quotes individually). If you want your strings to contain multiple lines (or just a single actual newline character), you can use this, which should look familiar from Perl:

        mode <<EOT
        a line
        another line
        bla
        EOT

You can replace the EOT with anything you like... even nothing - then, the next empty line marks the end. Only rule is that the end marker should not appear in the multiline value itself (alone on a line). Please note that this not being actual Perl syntax, there are no semicolons here.

Also, the last line end before the end marker is stripped, so if you want it included, add an empty line:

        mode <<EOT
        a line

        EOT

You can also use the funny operators introduced for command line parameters by replacing the = with .=, +=, -=, /=, *= as you like. That works for the <<EOT multiline construct, too, just make it .<<EOT for appending and likewise +<<EOT, -<<EOT , /<<EOT, *<<EOT for the other operations.

Also, just mentioning the parameter name sets it to a true value, like simple mentioning on command line. And that is actually one reason for not just using another markup or serialization format for configuration files: The specification in the file follows the same concepts you have on the command line (esp. regarding operator use). It is the same language, although with some slight deviation, like the here document and string quoting, which is matter of the shell in the case of command lines.

Comments in the config file start with "#" and are supposed to be on lines on their own (otherwise, they will get parsed as part of a parameter value). Special tokens for the parser (see see parse_file method, with the optional parameter) start with "=", the important one is inclusion of other config files:

        =include anotherconfigfile[.conf]

This will locate anotherconfigfile either via absolute path or relative to the currently parsed file. Search paths are not used (this was documented erroneously before). Its settings are loaded in-place and parsing continues with the current file. The file name starts with the first non-whitespace after =include and continues until the end of line. No quoting. If the given name does not exist, the ending .conf is added and that one tried instead. The parsing aborts and raises an error if an inclusion loop is detected.

There are more tokens in a fully annotated output of config files. Example:

        # I skipped  block of comments explaining the config file syntax.
        =param file for par_acceptor
        =version 1.0.0

        =info Param test program that accepts any parameter given

        =long ballaballa type scalar
        =help a parameter with meta data

        ballaballa = "0"

Only the last line in this example is relevant to the program itself (named "par_acceptor" here). The rest is auxilliary information for outsiders.

One last note: If a parameter value is undefined, no assignment is written to the config file. So a config file can never intentionally set a value to undefined state. You can start out with undef values, but as soon as the parameter got set one time to something else, it won't go back undef.

The config keys

Note that the hash ref you give to the constructor is taken over by the object; if you want to preserver the original hash, you have to make a copy yourself. It is the same with parameter definitions as array ref; consumed by initialization.

info (some text)

A text to print out before the parameter info when giving help, also used for the DESCRIPTION section in POD output if infopod is not defined.

infopod (some POD-formatted text)

Same as info, but used verbatim in POD output, and used to format help message printout if the former is not present. Be careful with fancy encodings. It is assumed that the terminal can handle whatever is given here, which should be UTF-8 nowadays, but you might want to stick to ASCII. This applies to any texts handled by this module, though.

program

name of the program/package, used in search for config file and for output of config files/messages; default is basename($0)

version

Version string for your program; this activates the definition of a --version switch to print it.

verbose (0 / 1)

When not 0, be verbose about the work being done. There may be different verbosity levels in the future, but for now value 4 is no different from 1. You can set $Config::Param::verbose to the same effect, globally.

multi (0 / 1)

If activated, potentially parses all located default config files in a row instead of choosing one (currently this is about generic and host config file; might get extended to system global vs. $HOME).

confdir (directory path)

Define a directory for searching of config files, overriding the internal defaults of looking at various likely places (in order), with "bin" being the directory the program resides in, "~" the user home directory:

~/.programname
bin/../etc/programname
bin/../etc
bin/etc
bin
~/.config/programname
~/.config

The contents and ordering of that list carry over behaviour in earlier versions of Config::Param, where the first existing directory in that list got used as single source for config files. During addition of the .config/ variants for version 3.001, this got changed to search the whole list (plus current working directory) for each requested file. This should provide reasonable compatibility to existing setups and a flexible way forward to enhance the ability to find config files. Note that you can always skip all that automatic fuss by specifying full paths to the desired config files. This just offers some convenience at the expense of predictability in case of conflicting config files of the same name at different locations. TODO: A future release may offer to override this list and tell Config::Param to locate multiple occurences of one config file name and load them in order. In that case, you probably want to change the order to look in global directories first, then in the users's home for specific settings overriding global defaults.

Explicitly given files without absolute path are always searched in the current working directory first.

file (single file name/path or array ref of those)

Define the default config file (s), overriding the internal default of confdir/programname.conf or (being more powerful if existing) confdir/programname.hostname.conf . The .conf suffix will be added if needed. A word on the hostname: This is a possibility to use one configuration directory for several hosts (p.ex. mounted over NFS).

BEWARE: Every smartness has its catch - when you do a `myprogram -I=my -I > my.conf` the newly created (and empty) file my.conf in the currect directoy is found and used as config file for reading, resulting in the program defaults being written regardless of what another existing my.conf would say!

nofile (0 / 1)

Prevent automatic parsing of configuration files.

gimme (0 / 1)

Give help end exit if no command line arguments are there.

lazy (0 / 1)

Switch to the "lazy" syntax that allows omitting the "-" and "--" in -p and --parameter (same with "+" and "++") most of the times but absolutely requires the separation of other stuff with /-+/ (read this as PERL regex;-).

nofinals (0 / 1)

Do not take final action on certain switches (help, version, config file printing). Normally (with nofinals == 0), Param would exit your program on processing these.

noexit (0 / 1)

Do final actions, but do not exit on those. Also prevents dying in constructor (and by extension, the get routine). You are supposed to check the error list.

notinfile (listref)

list with parameters (long names) not to include in config file printing, help and config are always left out as they make no sense in files (config might make sense, but there is =include to handle that).

nanny (0 / 1)

give parameter help and exit() when encountering unknown parameters in config files; otherwise just complain - this is disabled by nofinals.

fuzzy (0 / 1)

handle --non-existing-parameter by simply stopping parsing there (treat it as first file or such to be handled by your program), otherwise complain and dump help info + exit.

nocomplain (0 / 1)

do not complain about missing config file or the like

hidenonshort

Hide parameters that don't have a short name in the overview (p.ex. multiline stuff that one doesn't want to see outside of config files)

ordered

Print out parameters in definition order; otherwise sorted. This is implied once you define sections.

binmode (undef / :utf8 / :latin1 / ...)

Set the binmode (text encoding) for parsed files.

ignore_unkown

Do not complain on unknown parameters, just swallow silently. The actual value is important: 1 == only ignore unknowns in config files, 2 == also ignore unknowns on command line (overridden by the fuzzy operation).

accept_unkown

Silently add parameters (long names only) to the party as scalars when encountering corresponding settings. Similar to ignore_unknown, the value 1 means adding from config files only, value 2 also adds from command line (overruled by the fuzzy operation).

This also activates partial usage of parameter meta data in the config file if it appears before the actual assignment. In that case, you can even add non-scalar parameters externally.

output

Specify a handle to print help messages and config files to instead of STDOUT.

linewidth

Set a line width for paragraph formatting (otherwise terminal is queried).

silenterr

Integer for preventing printout of errors. You can prevent other printery by not enabling verbose mode and preventing finals or setting output to some sink.

author

Set some text to print when information about the author is expected.

Copyright and license info.

tagline

The one-line reason for your program thttp://thomas.orgis.org/scripterei/download/Config-Param-3.002000.tar.gzo exist. The motto, whatever. If not given, the first line of the info string is used. Please give either none or both of tagline and usage.

usage

Usage string summing up basic calling of the program. If not present, the info string might get harvested for that, if it contains such:

        usage: program [parameters] some.conf [parameters] [param names]

or

        usage:
          program [parameters] some.conf [parameters] [param names]

(with arbitrary number of empty lines in between). Please give either none or both of tagline and usage.

posixhelp

Generate usage text more like those of classic POSIX tools, not using a table of parameters, rather options and option arguments. This is incompatible with the lazy parameter parsing, as the usage hints would be too confusing or just inaccurate regarding actual syntax.

shortdefaults

Define this to a false value to prevent -h and -I being predefined as short names for --help and --config. Available since version 4. This frees some namespace, but still enforces the long names being available for help output and config file parsing. Users should be able to rely on that.

flags

Default flags for parameter definitions in the implicit default section. See "PARAMETER DEFINITON" for possible values.

regex

Default regex for parameter definitions in the implicit default section. See "PARAMETER DEFINITON".

call

Default callback for parameter definitions in the implicit default section. See "PARAMETER DEFINITON". This can be useful for tracing command line usage with a generic function. This call will also be applied to the default parameters defined by the library.

PARAMETER DEFINITION

Parameter definitions are provided as plain array or an array of hashes/arrays:

        # plain flat list of long name, default value, short name, help text
        @pardef = (  'long1',0,'l','some parameter'
                    ,'long2',1,'L','another parameter' );
        # list of lists
        @pardef = (  ['long1',0,'l','some parameter']
                    ,['long2',1] ); # omitted stuff empty/undef by default
        # list of hashes and/or lists
        @pardef =
        (
                {
                         long=>'long1'
                        ,value=>0,
                        ,short=>'l'
                        ,help=>'some parameter'
                }
                , ['long2',1,'L','another parameter']
        );

If the first element is no reference, Config::Param checks if the total count is a multiple of 4 to catch sloppyness on your side. These are possible keys for the hash definition:

long

The long paramter name. This is required. It must not contain '=', commas or any whitespace and begin and end with a non-operator character. Also, it needs to be at least two characters long.

value

The default value. The parameter starts with this value and and operations from the command line or config files apply on top, most notably simple replacement with another value. This can be a scalar (including undef) or a (anonymous) reference to an array or hash, which also defines the type of the parameter. No other type of reference, please.

Note that the contents the array/hash reference points to are deep-copied to avoid modifying the parameter definition and have consistent results on re-runs of the parser.

short

The short name, the classic POSIX option. This needs to be a single character that is not part of an operator.

help

The help text that describes this parameter and its usage.

arg

Name of argument to use in help output. The default would be 'value'. If this is the empty string, no argument is mentioned in the help output. This fits classic switches that only know on and off, or possibly a count. An alternative for that is to add the flag $Config::Param::switch.

flags

A set of flags specific to this parameter. See below. A section definition can provide a default.

addflags

Flags to set on top (only in hash definition).

level

A help level for this parameter to appear in the generated usage text. You can hide an excessive amount of options from simple --help output by specifying a level above 1. They are only listed at/above --help=level.

regex

A regex a value needs to match. This has to be a parsed regex object, not a plain string, so use something like

        regex=>qr/^\d+$/

to enforce unsigned integers. The check is applied per-element for arrays and hashes (values only, not keys) at the end, after applying operators. If the check fails, it is treated like a parameter parsing error, normally ending your program.

A section definition can provide a default.

call

A subroutine reference to call for validation or any processing you would like after parsing a parameter from the command line, but before settling operations. This means you get see --foo and decide if this should be translated to --foo.=42 instead of treating it as --foo=1. Any fancy operation may apply. You could just count things.

This is intended for interactive gimmics and not triggered during parsing of configuration files. A forced argument gives you an implicit = operator, even if that might be translated to the append operator after the call due to the parameter flags.

A prototype would be

        sub param_call # (name, sign, op, value)
        {
                print STDERR "Operation on $_[0].\n".
                print STDERR "You want to apply operation $_[2] to parameter $_[0].\n"
                        if defined $_[2];
                print STDERR "The fresh value for $_[0]: $_[3]\n"
                        if defined $_[3];
                return 0
                        unless $_[0] =~ /^num/;
                $_[3] += 0; # force numeric nature
                return 1
                        if $_[3] % 2; # Only even numbers!
                return 0; # all good
        }

The sign is either - or + relating to --foo or ++foo usage. You can modify this as well as operator and value. The operation and value could be undefined if not provided by the user, but you can set them. Once the operator is defined, a value must be set, too, and the sign does not matter anymore. You can actually decide to set the value to undefined, a state that normally cannot be restored after a parameter has been set in the usual way.

If the call returns non-zero, this is treated as an error in parameter handling and the program ends unless you disabled that in your call to the library. If you modify the name, or just undefine it, the setting will be dropped as if the user did not specify anything.

A section definition can provide a default callback.

An array definition contains four or more of the values for the above hash keys in the documented order.

So, an elaborate definition may look like

        {
                         long     => 'friend'
                        ,value    => 'myself'
                        ,short    => 'f'
                        ,help     => 'name of a friend'
                        ,arg      => 'name'
                        ,flags    => $Config::Param::arg
                        ,addflags => 0
                        ,level    => 3
                        ,regex    => qr/[a-zA-Z]/
                        ,call     => sub { ... }
        }

or

        ['friend', 'myself', 'f', 'name of a friend', 'name', $Config::Param::arg
        ,       0, 3, qr/[a-zA-Z]/, sub { ... } ]

for brevity.

A set of flags modifies the parsing behaviour. They can be set globally as a default, with each parameter definition possibly overriding those. The parameter flags value is built by binary OR of these, so

        $Config::Param::arg|$Config::Param::append

means this parameter requires and argument and that is implicitly appended to the current contents of the hash or array.

These are the possible flags:

$Config::Param::count

Turn -p without option argument into -p+=1, to effectively count the number of times a switch was specified. This only has effect for scalar parameters.

$Config::Param::arg

Require an explicit argument. This allows the user to drop the equal sign between option and value in favour of providing the value as following word on the command line. For the short name, this even allows dropping any separator, like in

        -Wl,-R/foo/bar

to assign (or append, for an array) the value 'l,-R/foo/bar' to the parameter with the short name 'W'.

$Config::param::switch

Mark this scalar parameter as a switch that knows on and off, maybe counted. This is the same as specifying an empty argument name. The option will still accept an optional argument, but it will not be advertised.

$Config::Param::append

Turn an assignment into appending to the array or hash. This even enables the extreme case of storing a sequence of ones and zeros using

        -a +aa -a +a -aaa

to encode the binary sequence 10010111. More traditionally, the combination with $Config::Param::arg enables storing multple option arguments from

        -a hello -a world

into the array ('hello', 'world') without funky operator syntax. This has no effect for scalar parameters.

$Config::Param::nonempty

Triggers a error if the parameter does not contain some non-empty value after parsing. This means something different than the empty string or just undefined for scalars and at least one element being present for arrays and hashes. The array or hash element itself can still be empty.

If you also want to ensure some non-whitespace or actually non-empty array or hash elements, use a regex check in addition.

Sections

To structure the help output, you can also include hashes that do not define a parameter, but a section of them instead. This structures the printout for many parameters and gives you the chance to add some more prose like that. Examples of section definitions:

        { section=>'input' }

        { section=>'some knobs', help=>'Tune -u -u --up!'
        , level=>2, flags=$Config::Param::count }

The help text is formatted to fit on the screen, so no fancy formatting besides paragraphs is supposed to be present from your side.

The presence of section definitions also triggers printout of parameters in the order you defined them. The optional level makes the section printout only apppear at and above the given help level.

MEMBERS

The simple procedural interface consists of mainly one function, but also some:

get
        $parm_ref = Config::Param::get(\%config,\@pardef,\@cmdline_args, $errors);
        $parm_ref = Config::Param::get(@pardef);

This basically returns a hashref with parsed parameter values, from different variants of input (see SYNOPSIS). You can also fetch a reference to the error string array, which only makes sense when disabling final actions, which would happen normally (the function not returning at all).

valid_name
        be_happy() if Config::Param::valid_name($long, $short);

Purely syntactical check for valid parameter names (letters, not (too many) funky symbols).

valid_type
        be_happy() if Config::Param::valid_type($value);

This does not mean that Config::Param will do the correct thing with your complex cross-blessed data structure; just that it thinks that it can, and will work with it as parameter intialization.

valid_def
        be_happy() if Config::Param::valid_def(\%single_pardef);

Checks if a single parameter definition given as hash is formally correct (name and type). If you hand in a second argument, the type code is stored there.

hashdef
        $parhash = Config::Param::hashdef(@def_array);
builtins
        $builtin_names = Config::Param::builtins(\%config);
        print "$name is used as long or short" if $builtin_names->{$name};

As it is an error to try and define a parmameter that conflicts with predfined long/short names, this returns a hash for easy checking if something is used already (depending on %config).

sane_pardef
        $problem = Config::Param::sane_pardef(\%config,\@pardef);
        die "bad parameter specification: $problem\n" if $problem;

This checks the parameter definition for issues (noted in $problem string) and brings it into the preferred form for internal consumption. Returns empty string if no problem encountered. The provided config is supposed to be identical to the one used later.

Using this function, you can prevent Config::Param::get() or Config::Param->new() from blowing up (using die()) on bad parameter specifications. If you do not take that extra care, it is assumed that blowing up is what you want on errors.

escape_pod

Little function that takes a string and returns it with potential POD directives neutralized.

The module also offers a class to work with. Most class members return 1 (true) on success, 0 on failure, also incrementing the error counter. That class has the following interesting members:

new

The constructor that normally wants this usage:

        $param = Config::Param->new(\%config, \@pardef);

It is possible to omit config hash and parameter definition and this can make sense if you intend to create the param space later on (p.ex. from a config file with meta data).

        $param = Config::Param->new(\%config);
or
        $param = Config::Param->new();
        # then do something to define parameters
define

A method to define one single parameter:

        $param->define({long=>$longname, value=>$value, short=>$short, help=>$desc});

Here, the help can be a string or a reference to a string (a reference is stored, anyway).

good

Return true if no errors are recorded (from bad definitions or command line arguments, for example). If using instances of the class explicitly, you should make sure you check this method before actually working with any resulting parmeter values. Library versions before 4 aborted the program using die() or croak() on setup issues, but now such errors are recorded for you to act on. Just dying deep in some library is not polite.

find_config_files

Use confdir and program to find possible config files (setting the the config parameter, it it is not set already).

        $param->find_config_files();
parse_args

Parse given command line argument list, storing its settings in internal operator queue (step 1 of usual work).

        $param->parse_args(\@ARGV);

Returns true if no error occured during this or an earlier call to parse_args() or apply_agrgs().

use_config_files

Apply possible operations on config parameter and parse files indicated by that (step 2 of usual work).

        $param->use_config_files();

Returns true if no new error occured.

apply_args

Apply the operations defined by the parsed argument list to the parameters (step 3 of usual work).

        $param->apply_args();

Returns true if no command line parsing error occured, meaning no error during this or earlier calls to apply_args() or parse_args(). This changed subtly in version 4. Before that, it returned if no errors occured at all, also from config files. As it is and was no good idea to call this when errors occured before, this change should not matter much, but makes the return value more consistent.

final_action

Possibly execute final action as determined by parameter values or encountered errors, like printing help or a configuration file and exit (step 4 or usual work). Without something special to do, it just returns nothing. It also does nothing if nofinals is set and only exists the program if noexit is unset.

        $param->final_action();

If called with a true value as argument,

        $para->final_action(1);

it only checks the internal error count, producing a final error message if that is non-zero, and exists unless noexit is set. Other final actions are not taking place. Since version 4, the non-zero exit values are 64 (EX_USAGE) to indicate errros in command-line syntax or parameter semantics, 78 (EX_CONFIG) to indicate specific config-file syntax issues, or 70 (EX_SOFTWARE) for errors in my or your code (usage of the library). This follows the conventions of sysexits.h.

parse_file

Parse given configuration file. Optional parameter (when true) triggers full usage of meta data to complete/override setup. If the given file specification is no full absolute path, it is searched in usual places or in specified configuration directory (see confdir). Note that versions before 3.001 replaced a "~" at the beginning with the home directory. While that may be convenient in certain moments where the shell does not do that itself, such is still is the shell's task and possibly causes confusion.

        $param->parse_file($file, $construct);

This returns true if no new error occured.

Print config file to given handle. Optional parameter gives a level of bareness, stripping meta info.

        $param->print_file(\*STDOUT, $bare);
current_setup

Return configuration hash and parameter definition array that corresponds to the current state (copies that can be destroyed at will).

        ($config, $pardef) = $param->current_setup();
        $param_copy = Config::Param->new($config, $pardef);
par_content
        # dump in perl-parseable format, with some pretty indent
        $string = $param->par_content($name, 'dump', 2);
        # lines without other quoting
        $string = $param->par_content($name, 'lines');

Return a string representing the content to given parameter key, with optional choice of format. Default is 'dump' with indent 0. Other choice is 'lines' for putting the value on a line or multiple lines, in case of arrays/hashes (newlines in values just happen, too, undef values result in empty lines, empty arrays/hashes in nothing at all). The third parameter chooses the indent style (see Data::Dumper).

Print POD to configured output. This utilizes the parameter space plus the meta data you provided in the config hash, including the possible extra sections. Writing the documentation by hand would suck, wouldn't it? Never forget a parameter in the man page again!

There are some member variables that are of interest (messing with those can have consequences, of course):

param

This is the internal parameter hash. If using the object interface, that is how you can actually access your configuration.

help
        $par_description = ${$param->{help}{$name}};
short
        $par_short = $param->{short}{$name}
long
        $par_short = $param->{long}{$shortname}
files

An array of files that have been parsed. You are free to reset that to be empty before loading a configuration file explicitly. After parsing, you have the list of all files that have been included (the intially given one plus files that have been included from there on).

errors

An array of collected error messages. You are free to empty it to indicate a fresh start, but make sure not to ignore errors created during parameter definition. Before version 4, the library aborted the process when something went wrong in this stage. This was changed to only end your program in an expected way during a call to final_action().

Members not documented here can not be relied upon for future releases.

SEE ALSO

This module evolved from a simple loop for command line argument processing, that I thought was quicker written than to search for an already existing module for that. While just using some Getopt may have been a bit quicker, this wouldn't fully do what I want and what numerous scripts I have written rely on. It may fully do what you want, though - so better check this before blaming me for wasting your time with installing Config::Param.

This being yet another entry in the Config/Getopt category, there are lots of alternative packages doing similar things (see http://search.cpan.org/modlist/Option_Parameter_Config_Processing). But when you limit your search to packages that do command line processing, parsing of config files and do handle standard behaviour like generating usage messages, the crowd is well reduced. You might want to check out App::Options, which has the same basic functionality, but of course different enough in the details as well as basic philosophy to let me justify the existence of this module, at least to myself.

There is also Getopt::Euclid, which somewhat works like the inverse, generating your parameter space from verbose description (POD) instead of generating the latter from the Perl data structure you provide. In any case, it is not concerned with config files.

AUTHOR

Thomas Orgis <thomas@orgis.org>

COPYRIGHT AND LICENSE

Copyright (C) 2004-2022, Thomas Orgis.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.