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

NAME

Getopt::LongUsage - Describe the usage of Getopt::Long options in human readable format

SYNOPSIS

Provide the description for Getopt::Long options in order to generate a descriptive usage for the user.

Example code:

    use Getopt::Long;
    use Getopt::LongUsage;

    my ($width,$length,$verbose,$help);
    my @getoptconf = (  'width=i'   => \$width,
                        'length=i'  => \$length,
                        'verbose|v' => \$verbose,
                        'help|h'    => \$help
                        );
    my $usage = sub {
        my @getopt_long_configuration = @_;
        GetLongUsage (
            'cli_use'       => ($0 ." [options]"),
            'descriptions'  =>
                [   'width'         => "The width",
                    'length'        => "The length",
                    'verbose'       => "verbose",
                    'help'          => "this help message"
                    ],
            'Getopt_Long'   => \@getopt_long_configuration,
        );
    };
    GetOptions( @getoptconf ) || die ($usage->( @getoptconf ),"\n");
    ...etc...

Example output:

    linux$ ./test_it.pl --not-an-option
    Unknown option: not-an-option
    ./test_it.pl [options]
      --width        The width
      --length       The length
      -v, --verbose  verbose
      -h, --help     this help message

DESCRIPTION

This is a pure perl module which generates a user help message for a perl script that implements the Getopt::Long module. Simply describe each option configured for Getopt::Long, and a useful formatted help message is generated.

REQUIREMENTS

The following perl modules are depended on by this module:

  • Getopt::Long

IMPORTED METHODS

When the calling application invokes this module in a use clause, the following method will be imported into its space.

  • GetLongUsage

METHODS

new

Create a new object instances of this module. It is not necessary to create an object for this module, as the methods can be called outside of OO style programming.

  • returns

    An object instance of this module.

    my $glu = new Getopt::LongUsage();

ParseGetoptLongConfig

Parse option configuration for Getopt::Long.

This method reproduces just enough code as found in Getopt::Long::GetOptionsFromArray(), while also calling functions in that module, so to parse the same exact Getopt::Long configuration input.

    my $configmap = ParseGetoptLongConfig (
                        \%options,
                        'isAvailable',
                        'color=s',
                        'type=s',
                        'cityGrown=s@',
                        'secretAttr=i',
                        'verbose|v',
                        'help|h'
                    );

    my @getoptconf = (
                        'isAvailable'  => \$isAvailable,
                        'color=s'      => \$color,
                        'type=s'       => \$type,
                        'cityGrown=s@' => \@cityGrown,
                        'secretAttr:i' => \$secretAttr,
                        'verbose|v'    => \$verbose,
                        'help|h'       => \$help
                        );
    my $configmap = ParseGetoptLongConfig ( @getoptconf );

GetLongUsage

Generate a usage message from Getopt::Long options.

  • header

    This is a text string to be used as a header of the usage output. It will appear at the top of the usage output.

  • footer

    This is a text string to be used as a footer of the usage output. It will appear at the bottom of the usage output.

  • cli_use

    This is a string representing the format for executing your application.

  • descriptions

    This is an array reference of options with descriptions. The order of the options provided to the descriptions parameter dictates the presentation order. The format is as follows:

        my $descriptions = [ 'opt1' => 'desc1', 'opt2' => 'desc2', etc... ]

    The options should be one that is found in the Getopt::Long configuration passed to the Getopt_Long parameter. If the configuration consists of both long and short options, you should only provide one of them. The description is associated with all related options as configured for Getopt::Long.

    So for example, if the following is your Getopt::Long configuration:

        GetOptions( %options, 'help|h', 'opt1|o')

    Then the following two descriptions configurations would be valid:

        $descriptions = [   'h' => "This help message",
                            'o' => "The first option"   ]
    
        $descriptions = [   'help' => "This help message",
                            'opt1' => "The first option"   ]

    It does not matter if you use either the long or short form of the options, as it is only used in this parameter for the purpose of associating the given description with a relation of options in the Getopt::Long configuration.

  • format

    Formatting options are set in subparameters within this parameter.

    • tab

      The number of spaces that comprise a tab in the formatted output. The default is 2 spaces for each tab.

    • indent

      The number of spaces to indent the formatted output. The default is 0 spaces.

    • longprefix

      The prefix that defines long options. The default is --, as in --help.

    • shortprefix

      The prefix that defines short options. The default is -, as in -h.

  • hidden_opts

    This is an array reference list of Getopt::Long options that will be hidden from the formatted usage message intended for human reading.

  • Getopt_Long

    The array reference list of a Getopt::Long configuration which is a definition of the expected Getopt::Long::GetOptions() input option.

    GetLongUsage (  header          => "This is my header text",
                    footer          => "This is my footer text"
                    cli_use         => "myprog [options] arg1 arg2",
                    descriptions    => \@descriptions,
                    format          => \@format_options,
                    hidden_opts     => \@hidden_options,
                    Getopt_Long     => \@getopt_long_options
                    );

EXAMPLES

Actually, the descriptions are not needed either

Example code:

    use Getopt::Long;
    use Getopt::LongUsage;
    
    my %options;
    my @getoptconf = (  \%options,
                        'isAvailable',
                        'color=s',
                        'type=s',
                        'cityGrown=s@',
                        'verbose|v',
                        'help|h'
                        );
    my $usage = sub {
        my @getopt_long_configuration = @_;
        GetLongUsage (
            'Getopt_Long'   => \@getopt_long_configuration,
        );
    };
    GetOptions( @getoptconf ) || die ($usage->( @getoptconf ),"\n");
    ...etc...

Example output:

    linux$ perl test.pl --notanoption
    Unknown option: notanoption
      -v, --verbose  
      --isAvailable  
      --color        
      -h, --help     
      --type         
      --cityGrown

Using more formatting options

Example code:

    use Getopt::Long;
    use Getopt::LongUsage;
    
    my $VERSION = "2.1.5";
    my %options;
    my @getoptconf = (  \%options,
                        'isAvailable',
                        'color=s',
                        'type=s',
                        'cityGrown=s@',
                        'secretAttr:i',
                        'verbose|v',
                        'help|h'
                        );
    my $usage = sub {
        my @getopt_long_configuration = @_;
        GetLongUsage (
            'header'        => ("MyApple Program version ".$VERSION."\n".'Author Smith <author@example.com>'."\n"),
            'cli_use'       => ($0 ."[options] <args>"),
            'descriptions'  =>
                [   'isAvailable'   => "The apple type is available",
                    'color'         => "The color of this apple type",
                    'type'          => "The type of apple, i.e. \"Gala\"",
                    'cityGrown'     => "The city(s) in which this apple is grown",
                    'secretAttr'    => "You should not see this option",
                    'verbose'       => "verbose",
                    'help'          => "help"
                    ],
            'hidden_opts    => [qw(secretAttr)]
            'footer'        => undef,
            'format'        =>
                [   'tab'       => 4,
                    'indent'    => 0
                    ],
            'Getopt_Long'   => \@getopt_long_configuration,
        );
    };
    GetOptions( @getoptconf ) || die ($usage->( @getoptconf ),"\n");
    ...etc...

Example output:

    MyApple Program version 2.1.5
    Author Smith <author@example.com>
    
    script.pl [options] <args>
        --isAvailable    The apple type is available
        --color          The color of this apple type
        --type           The type of apple, i.e. "Gala"
        --cityGrown      The city(s) in which this apple is grown
        -v, --verbose    verbose
        -h, --help       help

Combining Getopt::XML with Getopt::LongUsage

Considering the following XML File '/path/to/xml_file.xml' and content:

    <apple>
        <color>red</color>
        <type>red delicious</type>
        <isAvailable/>
        <cityGrown>Macomb</cityGrown>
        <cityGrown>Peoria</cityGrown>
        <cityGrown>Galesburg</cityGrown>
    </apple>

Using that XML file as input for default values:

    use Getopt::Long;
    use Getopt::LongUsage;
    use Getopt::XML qw(GetXMLOptionsFromFile);
    use Data::Dump qw(pp);
    #
    # Set the Getopt::Long Configuration
    my @GetoptLongConfig = (
                                \%options,
                                'isAvailable',
                                'color=s',
                                'type=s',
                                'cityGrown=s@'
                            );
    #
    # Read the XML data in as arguments to Getopt::Long
    my %options;
    GetXMLOptionsFromFile (
            xmlfile     => '/path/to/xml_file.xml',
            xmlpath     => '/apple',
            Getopt_Long => \@GetoptLongConfig
    );
    print "==My Default Values==\n";
    pp(\%options);
    #
    # Setup the user's help message for Getopt::Long
    my $usage = sub {
        my @getopt_long_configuration = @_;
        GetLongUsage (
            'header'        => ("MyApple Program version ".$VERSION."\n".'Author Smith <author@example.com>'."\n"),
            'cli_use'       => ($0 ." [options] <args>"),
            'descriptions'  =>
                [   'isAvailable'   => "The apple type is available",
                    'color'         => "The color of this apple type",
                    'type'          => "The type of apple, i.e. \"Gala\"",
                    'cityGrown'     => "The city(s) in which this apple is grown"
                    ],
            'footer'        => "\n",
            'format'        =>
                [   'tab'       => 2,
                    'indent'    => 2
                    ],
            'Getopt_Long'   => \@getopt_long_configuration,
        );
    };
    #
    # Finally retrieve and absorb the user provided input via Getopt::Long
    GetOptions( @GetoptLongConfig ) || die ($usage->( @GetoptLongConfig ));
    print "==My Runtime Values==\n";
    pp(\%options);

Example output when providing an invalid option

    linux$ perl test.pl --notanoption
    ==My Default Values==
    {
      cityGrown => ["Macomb", "Peoria", "Galesburg"],
      color => "red",
      isAvailable => 1,
      type => "red delicious",
    }
    Unknown option: notanoption
      MyApple Program version 
      Author Smith <author@example.com>
      
      test.pl [options] <args>
        --isAvailable  The apple type is available
        --color        The color of this apple type
        --type         The type of apple, i.e. "Gala"
        --cityGrown    The city(s) in which this apple is grown

Example output when providing a valid option

    linux$ perl test.pl --color="blue" --type="blue delicious"
    ==My Default Values==
    {
      cityGrown => ["Macomb", "Peoria", "Galesburg"],
      color => "red",
      isAvailable => 1,
      type => "red delicious",
    }
    ==My Runtime Values==
    {
      cityGrown => ["Macomb", "Peoria", "Galesburg"],
      color => "blue",
      isAvailable => 1,
      type => "blue delicious",
    }

TODO

1 Support the definition of the column width in the usage message output

By defining a format subparameter called cols in GetLongUsage(), one can define how wide (how many columns) the usage message output should be constrained within. In conforming to a maximum column size, the options sub-column and option description sub-column will be adjusted to fit that width in the following ways:

1. The options sub-column may be formatted such that particularly long rows of this sub-column will be on a line of its own, and its associated description will begin on the next line - though in the description sub-column

2. The option description sub-column may be formatted such that descriptions which span beyond the sub-column width will be wrapped to the next line.

    --thisisaverylongoption
                        The descriotion has to start on the next line because the
                        option is too long. Also this description wraps around
                        because it is also too long.
    -a, --another, --param2
                        This is also true for options like this one.
    -h, --help, -?      This option and description fits.
1 Display the input type for each option in the usage message output

Currently the usage message only displays the options and relation option aliases for each option. The required input format is not provided. So by only looking at the options in the usage message output, a user does not know if the option is a boolean flag, requires a string text as input, or requires a number as input.

The ParseGetopLongConfig() method already returns a map of the option configuration which describes the expected input (as boolean flag, string, or integer). The GetLongUsage() method need only utilize that available data when formatting the usage message.

A flag may be provided to allow the caller to turn this off or on, and maybe even possibly format what it looks like. I am considering something like the following as default, which just mimics the Getopt::Long configuration style:

    --booleanflag
    --number=i
    --yourname=s
1 Support for optionally displaying aliases on their own line

Currently the aliases and their main parameters are displayed on the same line. However, it may be desired to have them on a separated line, and reference the main parameter.

So instead of:

    -h, -?, --help        This help message
    -v, --verbose, --ver  Turn on verbose messaging

It would be:

    -h, -?, --help  This help message
    -v, --verbose   Turn on verbose messaging
    --ver           Alias for --verbose

AUTHOR

Russell E Glaue, http://russ.glaue.org

SEE ALSO

Getopt::Long

Getopt::XML

Getopt::LongUsage on Codepin: http://www.codepin.org/project/perlmod/Getopt-LongUsage

COPYRIGHT AND LICENSE

Copyright (c) 2010-2013 Center for the Application of Information Technologies. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.