The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Term::CLI::Util - utility functions for Term::CLI(3p)

VERSION

version 0.059000

SYNOPSIS

 use Term::CLI::Util qw( :all );

 use Data::Dumper;

 my %result = get_options_from_array(
    args         => \@ARGV,
    spec         => [ 'verbose|v', 'debug|d' ]
    result       => \(my %options),
    pass_through => 1,
 );

 say "Result: ", Data::Dumper->Dump(
    [ \%result, \%options, \@ARGV ],
    [ 'result', 'options', 'ARGV' ]
 );

 is_prefix_str( 'foo', 'foobar' ); # returns true.
 is_prefix_str( 'bar', 'foobar' ); # returns false.

DESCRIPTION

Provide utility functions for various modules in the Term::CLI(3p) collection.

EXPORTED FUNCTIONS

No functions are exported by default. Functions need be imported explicitly by name, or by specifying the :all tag, which will import all functions.

FUNCTIONS

find_obj_name_matches
    LIST = find_obj_name_matches( TEXT, OBJ_LIST_REF );
    LIST = find_obj_name_matches( TEXT, OBJ_LIST_REF, exact => 1 );

Find objects in OBJ_LIST_REF (an ArrayRef) where TEXT is a prefix for the object's name attribute. The list must be sorted on name field.

If the exact options is specified to be true, an exact name match will result in exactly one item to be returned.

find_text_matches
    LIST = find_string_matches( TEXT, STRING_LIST_REF );
    LIST = find_string_matches( TEXT, STRING_LIST_REF, exact => 1 );

Same as find_obj_name_matches above, except that the second argument refers to a sorted list of scalars (strings), rather than objects.

get_options_from_array
    HASH = get_options_from_array(
        args => ArrayRef,
        spec => ArrayRef,
        [ result => HashRef, ]
        [ pass_through => Bool, ]
    );

Parse the command line options in the args array according to the options specified in the spec array. Recognised options are stored in the result hash.

This is a fancy wrapper around GetOptionsFromArray from Getopt::Long(3p).

This function, however, sets the following configuration flags for Getopt::Long: bundling, require_order and either pass_through or no_pass_through, depending on the pass_through parameter it was given.

Unlike Getopt::Long, this function will remove the option terminating "double dash" (--) argument from the argument list, even if pass_through is true.

The return value is a hash with the following keys:

success

A boolean indicating whether the option parsing was successful or not. If false, the error_msg key will hold a diagnostic message.

error_msg

A string holding the error message from Getopt::Long. If success is true, this will be an empty string.

double_dash

A boolean indicating whether option parsing was stopped due to encountering a -- word in the argument list.

This is only present if pass_through was specified with a true value.

is_prefix_str
    BOOL = is_prefix_str( SUBSTR, STRING );

Returns whether SUBSTR is a prefix of STRING.

EXAMPLES

Consider the following script, called getopt_test.pl:

    use 5.014;
    use warnings;
    use Data::Dumper;
    use Term::CLI::Util qw( get_options_from_array );

    my ($pass_through, @args) = @ARGV;

    my %options;

    my %result = get_options_from_array(
        args         => \@args,
        spec         => [ 'verbose|v+', 'debug|d' ],
        result       => \%options,
        pass_through => $pass_through,
    );

    print Data::Dumper->Dump(
        [ \%result, \%options, \@args ],
        [ '*result', '*options', '*args' ]
    );

With correct input

With pass_through:

    $ perl getopt_test.pl 1 -vv --debug -- foo bar
    %result = (
                'success' => 1,
                'error_msg' => '',
                'double_dash' => 1
              );
    %options = (
                 'debug' => 1,
                 'verbose' => 2
               );
    @args = (
              'foo',
              'bar'
            );

Without pass_through:

    $ perl getopt_test.pl 0 -vv --debug -- foo bar
    %result = (
                'success' => 1,
                'error_msg' => '',
              );
    %options = (
                 'debug' => 1,
                 'verbose' => 2
               );
    @args = (
              'foo',
              'bar'
            );

Note the difference in output: in the case where pass_through is enabled, there is an entry in the result for double_dash (which in this case is true).

With incorrect input

With pass_through:

    $ perl getopt_test.pl 1 -vv --debug --bad -- foo bar
    %result = (
                'success' => 1,
                'error_msg' => '',
                'double_dash' => ''
              );
    %options = (
                 'verbose' => 2
               );
    @args = (
              '--bad',
              '--debug',
              '--',
              'foo',
              'bar'
            );

Without pass_through:

    $ perl getopt_test.pl 0 -vv --debug -- foo bar
        %result = (
                    'success' => '',
                    'error_msg' => 'Unknown option: bad'
                  );
        %options = (
                     'debug' => 1,
                     'verbose' => 2
                   );
        @args = (
                  'foo',
                  'bar'
                );

SEE ALSO

Term::CLI(3p), Getopt::Long(3p).

CAVEATS

When pass_through is enabled, Getopt::Long should leave a -- in the argument list when it encounters it; however, versions before 2.51 do not do so.

This module tries to compensate for that when it detects an older Getopt::Long version by searching for -- in the argument list beforehand. There are still instances where this can go wrong, though:

  • Input is --foo -- --verbose and option foo happens to take an argument.

  • Input is --opt1 arg1 arg2 and arg2 happens to be --.

However, since the double_dash flag is really only used in command completion, this is not a very major issue.

AUTHOR

Steven Bakker <Steven.Bakker@ams-ix.net>, AMS-IX B.V.; 2022.

COPYRIGHT AND LICENSE

Copyright (c) 2022 AMS-IX B.V.; All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See "perldoc perlartistic."

This software 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.