Perinci::CmdLine::Base - Base class for Perinci::CmdLine{::Classic,::Lite}
This document describes version 1.75 of Perinci::CmdLine::Base (from Perl distribution Perinci-CmdLine-Lite), released on 2017-06-28.
If you execute run(), this is what will happen, in order:
run()
Detect if we are running under tab completion mode
This is done by checking the existence of special environment varibles like COMP_LINE (bash) or COMMAND_LINE (tcsh). If yes, then jump to "PROGRAM FLOW (TAB COMPLETION)". Otherwise, continue.
COMP_LINE
COMMAND_LINE
Run hook_before_run, if defined
This hook (and every other hook) will be passed a single argument $r, a hash that contains request data (see "REQUEST KEYS").
$r
Some ideas that you can do in this hook: XXX.
Parse command-line arguments (@ARGV) and set action
action
If read_env attribute is set to true, and there is environment variable defined to set default options (see documentation on read_env and env_name attributes) then the environment variable is parsed and prepended first to the command-line, so it can be parsed together. For example, if your program is called foo and environment variable FOO_OPT is set to --opt1 --opt2 val. When you execute:
read_env
env_name
foo
FOO_OPT
--opt1 --opt2 val
% foo --no-opt1 --trace 1 2
then @ARGV will be set to ('--opt1', '--opt2', 'val', '--no-opt1', '--trace', 1, 2). This way, command-line arguments can have a higher precedence and override settings from the environment variable (in this example, --opt1 is negated by --no-opt1).
@ARGV
('--opt1', '--opt2', 'val', '--no-opt1', '--trace', 1, 2)
--opt1
--no-opt1
Currently, parsing is done in two steps. The first step is to extract subcommand name. Because we want to allow e.g. cmd --verbose subcmd in addition to cmd subcmd (that is, user is allowed to specify options before subcommand name) we cannot simply get subcommand name from the first element of @ARGV but must parse command-line options. Also, we want to allow user specifying subcommand name from option cmd --cmd subcmd because we want to support the notion of "default subcommand" (subcommand that takes effect if there is no subcommand specified).
cmd --verbose subcmd
cmd subcmd
cmd --cmd subcmd
In the first step, since we do not know the subcommand yet, we only parse common options and strip them. Unknown options at this time will be passed through.
If user specifies common option like --help or --version, then action will be set to (respectively) help and version and the second step will be skipped. Otherwise we continue the the second step and action by default is set to call.
--help
--version
help
version
call
At the end of the first step, we already know the subcommand name (of course, if subcommand name is unknown, we exit with error) along with subcommand spec: its URL, per-subcommand settings, and so on (see the subcommands attribute). If there are no subcommands, subcommand name is set to '' (empty string) and the subcommand spec is filled from the attributes, e.g. url, summary, <tags>, and so on.
subcommands
''
url
summary
We then perform a meta Riap request to the URL to get the Rinci metadata. After that, hook_after_get_meta is run if provided. From the Rinci metadata we get list of arguments (the args property). From this, we generate a spec of command-line options to feed to Getopt::Long. There are some conversions being done, e.g. an argument called foo_bar will become command-line option --foo-bar. Command-line aliases from metadata are also added to the Getopt::Long spec.
meta
hook_after_get_meta
args
foo_bar
--foo-bar
Getopt::Long
It is also at this step that we read config file (if read_config attribute is true). We run hook_before_read_config_file first. Some ideas to do in this hook: setting default config profile.
read_config
hook_before_read_config_file
We then pass the spec to Getopt::Long::GetOptions, we get function arguments.
Getopt::Long::GetOptions
We then run hook_after_parse_argv. Some ideas to do in this hook: XXX.
hook_after_parse_argv
Function arguments that are still missing can be filled from STDIN or files, if the metadata specifies cmdline_src property (see Rinci::function for more details).
cmdline_src
Delegate to action_$action method
action_$action
Before running the action_$action method, hook_before_action is called e.g. to allow changing/fixing action, last chance to check arguments, etc.
hook_before_action
After we get the action from the previous step, we delegate to separate action_$action method (so there is action_version, action_help, and so on; and also action_call). These methods also receive $r as their argument and must return an enveloped result (see Rinci::function for more details).
action_version
action_help
action_call
Result is put in $r->{res}.
$r->{res}
hook_after_action is then called e.g. to preformat result.
hook_after_action
Run hook_format_result
Hook must set $r->{fres} (formatted result).
$r->{fres}
If skip_format attribute is true, or function metadata has cmdline.skip_format set to true, or result has cmdline.skip_format metadata property set to true, then this step is skipped and $r->{fres} is simply taken from $r->{res}[2].
skip_format
cmdline.skip_format
$r->{res}[2]
Run hook_display_result
This hook is used by XXX.
Run hook_after_run, if defined
Some ideas to do in this hook: XXX.
Exit (or return result)
If exit attribute is true, will exit() with the action's envelope result status. If status is 200, exit code is 0. Otherwise exit code is status minus 300. So, a response [501, "Not implemented"] will result in exit code of 201.
exit
exit()
[501, "Not implemented"]
If exit attribute is false, will simply return the action result ($r->{res}). And will also set exit code in $r->{res}[3]{'x.perinci.cmdline.base.exit_code'}.
$r->{res}[3]{'x.perinci.cmdline.base.exit_code'}
If program is detected running in tab completion mode, there is some differences in the flow. First, @ARGV is set from COMP_LINE (or COMMAND_LINE) environment variable. Afterwards, completion is done by calling Perinci::Sub::Complete's complete_cli_arg.
complete_cli_arg
The result is then output to STDOUT (resume from Run hook_format_result step in the normal program flow).
The various values in the $r hash/stash.
orig_argv => array
Original @ARGV at the beginning of run().
common_opts => hash
Value of common_opts attribute, for convenience.
common_opts
action => str
Selected action to use. Usually set from the common options.
format => str
Selected format to use. Usually set from the common option --format.
--format
read_config => bool
This is set in run() to signify that we have tried to read config file (this is set to true even though config file does not exist). This is never set to true when read_config attribute is set, which means that we never try to read any config file.
read_env => bool
This is set in run() to signify that we will try to read env for default options. This settng can be turned off e.g. in common option no_env. This is never set to true when read_env attribute is set to false, which means that we never try to read environment.
no_env
config => hash
This is set in the routine that reads config file, containing the config hash. It might be an empty hash (if there is on config file to read), or a hash with sections as keys and hashrefs as values (configuration for each section). The data can be merged from several existing config files.
read_config_files => array
This is set in the routine that reads config file, containing the list of config files actually read, in order.
config_paths => array of str
config_profile => str
parse_argv_res => array
Enveloped result of parse_argv().
parse_argv()
ignore_missing_config_profile_section => bool (default 1)
This is checked in the parse_argv(). To aid error checking, when a user specifies a profile (e.g. via --config-profile FOO) and config file exists but the said profile section is not found in the config file, an error is returned. This is to notify user that perhaps she mistypes the profile name.
--config-profile FOO
But this checking can be turned off with this setting. This is sometimes used when e.g. a subclass wants to pick a config profile automatically by setting $r->{config_profile} somewhere before reading config file, but do not want to fail execution when config profile is not found. An example of code that does this is Perinci::CmdLine::depak.
$r->{config_profile}
subcommand_name => str
Also set by parse_argv(). The subcommand name in effect, either set explicitly by user using --cmd or the first command-line argument, or set implicitly with the default_subcommand attribute. Undef if there is no subcommand name in effect.
--cmd
default_subcommand
subcommand_name_from => str
Also set by parse_argv(). Tells how the subcommand_name request key is set. Value is either --cmd (if set through --cmd common option), arg (if set through first command-line argument), default_subcommand (if set to default_subcommand attribute), or undef if there is no subcommand_name set.
subcommand_name
arg
subcommand_data => hash
Also set by parse_argv(). Subcommand data, including its URL, summary (if exists), and so on. Note that if there is no subcommand, this will contain data for the main command, i.e. URL will be set from url attribute, summary from summary attribute, and so on. This is a convenient way to get what URL and summary to use, and so on.
skip_parse_subcommand_argv => bool
Checked by parse_argv(). Can be set to 1, e.g. in common option handler for --help or --version to skip parsing @ARGV for per-subcommand options.
args => hash
Also taken from parse_argv() result.
meta => hash
Result of get_meta().
get_meta()
dry_run => bool
Whether to pass -dry_run special argument to function.
-dry_run
res => array
Enveloped result of action_ACTION().
action_ACTION()
fres => str
Result from hook_format_result().
hook_format_result()
output_handle => handle
Set by select_output_handle() to choose output handle. Normally it's STDOUT but can also be pipe to pager (if paging is turned on).
naked_res => bool
Set to true if user specifies --naked-res.
--naked-res
viewer => str
Program to use as external viewer.
viewer_temp_path => str
Set to temporary filename created to store the result to view to external viewer program.
All hooks will receive the argument $r, a per-request hash/stash. The list below is by order of calling.
Called at the start of run(). Can be used to set some initial values of other $r keys. Or setup the logger.
Only called when read_config attribute is true.
Called after the get_meta method gets function metadata, which normally happens during parsing argument, because parsing function arguments require the metadata (list of arguments, etc).
get_meta
PC:Lite as well as PC:Classic use this hook to insert a common option --dry-run if function metadata expresses that function supports dry-run mode.
--dry-run
PC:Lite also checks the deps property here. PC:Classic doesn't do this because it uses function wrapper (Perinci::Sub::Wrapper) which does this.
deps
Called after run() calls parse_argv() and before it checks the result. $r-{parse_argv_res}> will contain the result of parse_argv(). The hook gets a chance to, e.g. fill missing arguments from other source.
$r-
Note that for sources specified in the cmdline_src property, this base class will do the filling in after running this hook, so no need to do that here.
PC:Lite uses this hook to give default values to function arguments $r->{args} from the Rinci metadata. PC:Classic doesn't do this because it uses function wrapper (Perinci::Sub::Wrapper) which will do this as well as some other stuffs (validate function arguments, etc).
$r->{args}
Called before calling the action_ACTION method. Some ideas to do in this hook: modifying action to run ($r->{action}), last check of arguments ($r->{args}) before passing them to function.
action_ACTION
$r->{action}
PC:Lite uses this hook to validate function arguments. PC:Classic does not do this because it uses function wrapper which already does this.
Called after calling action_ACTION method. Some ideas to do in this hook: preformatting result ($r->{res}).
The hook is supposed to format result in $res-{res}> (an array).
$res-
All direct subclasses of PC:Base do the formatting here.
The hook is supposed to display the formatted result (stored in $r-{fres}>) to STDOUT. But in the case of streaming output, this hook can also set it up.
Called at the end of run(), right before it exits (if exit attribute is true) or returns $r-{res}>. The hook has a chance to modify exit code or result.
Below is list of special arguments that may be passed to your function by the framework. Per Rinci specification, these are prefixed by - (dash).
-
Only when in dry run mode, to notify function that we are in dry run mode.
Only when pass_cmdline_object attribute is set to true. This can be useful for the function to know about various stuffs, by probing the framework object.
pass_cmdline_object
Only when pass_cmdline_object attribute is set to true. Contains the $r per-request hash/stash. This can be useful for the function to know about various stuffs, e.g. parsed configuration data, etc.
This will be set if argument is retrieved from file, stdin, stdin_or_file, stdin_or_files, or stdin_line.
file
stdin
stdin_or_file
stdin_or_files
stdin_line
An extra information if argument value is retrieved from file(s), so the function can know the filename(s).
This module observes the following Rinci metadata property attributes:
Set default output format (if user does not specify via --format command-line option).
If you set it to 1, you specify that function's result never needs formatting (i.e. the function outputs raw text to be outputted directly), so no formatting will be done. See also: skip_format attribute, cmdline.skip_format result metadata attribute.
This module interprets the following result metadata property/attribute:
Instruct to use this exit code, instead of using (function status - 300).
Replace result. Can be useful for example in this case:
sub is_palindrome { my %args = @_; my $str = $args{str}; my $is_palindrome = $str eq reverse($str); [200, "OK", $is_palindrome, {"cmdline.result" => ($is_palindrome ? "Palindrome" : "Not palindrome")}]; }
When called as a normal function we return boolean value. But as a CLI, we display a more user-friendly message.
Default format to use. Can be useful when you want to display the result using a certain format by default, but still allows user to override the default.
If you want to filter the result through pager (currently defaults to $ENV{PAGER} or less -FRSX), you can set cmdline.page_result in result metadata to true.
$ENV{PAGER}
less -FRSX
cmdline.page_result
For example:
$SPEC{doc} = { ... }; sub doc { ... [200, "OK", $doc, {"cmdline.page_result"=>1}]; }
Instruct to use specified pager instead of $ENV{PAGER} or the default less or more.
less
more
Aside from using a pager, you can also use a viewer. The difference is, when we use a pager we pipe the output directly to the pager, but when we use a viewer we write to a temporary file then call the viewer with that temporary filename as argument. Viewer settings override pager settings.
If this attribute is set to true, will view result using external viewer (external viewer program is set either from cmdline.viewer or VIEWER or BROWSER. An error is raised when there is no viewer set.)
cmdline.viewer
VIEWER
BROWSER
Instruct to use specified viewer instead of $ENV{VIEWER} or $ENV{BROWSER}.
$ENV{VIEWER}
$ENV{BROWSER}
When we want the command-line framework to just print the result without any formatting. See also: skip_format attribute, cmdline.skip_format function metadata attribute.
This is added by this module, so exit code can be tested.
Contains a list of known actions and their metadata. Keys should be action names, values should be metadata. Metadata is a hash containing these keys:
A hash of common options, which are command-line options that are not associated with any subcommand. Each option is itself a specification hash containing these keys:
category (str)
Optional, for grouping options in help/usage message, defaults to Common options.
Common options
getopt (str)
Required, for Getopt::Long specification.
handler (code)
Required, for Getopt::Long specification. Note that the handler will receive ($geopt, $val, $r) (an extra $r).
($geopt, $val, $r)
usage (str)
Optional, displayed in usage line in help/usage text.
summary (str)
Optional, displayed in description of the option in help/usage text.
show_in_usage (bool or code, default: 1)
A flag, can be set to 0 if we want to skip showing this option in usage in --help, to save some space. The default is to show all, except --subcommand when we are executing a subcommand (obviously).
show_in_options (bool or code, default: 1)
A flag, can be set to 0 if we want to skip showing this option in options in --help. The default is to 0 for --help and --version in compact help. Or --subcommands, if we are executing a subcommand (obviously).
order (int)
Optional, for ordering. Lower number means higher precedence, defaults to 1.
A partial example from the default set by the framework:
{ help => { category => 'Common options', getopt => 'help|h|?', usage => '--help (or -h, -?)', handler => sub { ... }, order => 0, show_in_options => sub { $ENV{VERBOSE} }, }, format => { category => 'Common options', getopt => 'format=s', summary => 'Choose output format, e.g. json, text', handler => sub { ... }, }, undo => { category => 'Undo options', getopt => 'undo', ... }, ... }
The default contains: help (getopt help|h|?), version (getopt version|v), action (getopt action), format (getopt format=s), format_options (getopt format-options=s), json). If there are more than one subcommands, this will also be added: list (getopt list|l). If dry-run is supported by function, there will also be: dry_run (getopt dry-run). If undo is turned on, there will also be: undo (getopt undo), redo (getopt redo), history (getopt history), clear_history (getopt clear-history).
help|h|?
version|v
format=s
format-options=s
list|l
dry-run
undo
redo
history
clear-history
Sometimes you do not want some options, e.g. to remove format and format_options:
format
format_options
delete $cmd->common_opts->{format}; delete $cmd->common_opts->{format_options}; $cmd->run;
Sometimes you want to rename some command-line options, e.g. to change version to use capital -V instead of -v:
-V
-v
$cmd->common_opts->{version}{getopt} = 'version|V';
Sometimes you want to add subcommands as common options instead. For example:
$cmd->common_opts->{halt} = { category => 'Server options', getopt => 'halt', summary => 'Halt the server', handler => sub { my ($go, $val, $r) = @_; $r->{subcommand_name} = 'shutdown'; }, };
This will make:
% cmd --halt
equivalent to executing the 'shutdown' subcommand:
% cmd shutdown
Will be passed to Perinci::Sub::Complete's complete_cli_arg(). See its documentation for more details.
complete_cli_arg()
Set subcommand to this if user does not specify which to use (either via first command-line argument or --cmd option). See also: get_subcommand_from_arg.
get_subcommand_from_arg
If set to yes, then if a partial subcommand name is given on the command-line and unambiguously completes to an existing subcommand name, it will be assumed to be the complete subcommand name. This is like the auto_abbrev behavior of Getopt::Long. For example:
auto_abbrev
% myapp c
If there are subcommands create, modify, move, delete, then c is assumed to be create. But if:
create
modify
move
delete
c
% myapp mo
then it results in an unknown subcommand error because mo is ambiguous between modify and move.
Note that subcommand name in config section must be specified in full. This option is about convenience at the command-line only.
The default is 1, which is to get subcommand from the first command-line argument except when there is default_subcommand defined. Other valid values are: 0 (not getting from first command-line argument), 2 (get from first command-line argument even though there is default_subcommand defined).
Available output formats.
Default format.
Whether to pass special argument -cmdline containing the cmdline object to function. This can be overriden using the pass_cmdline_object on a per-subcommand basis.
-cmdline
In addition to -cmdline, -cmdline_r will also be passed, containing the $r per-request stash/hash (see "REQUEST KEYS").
-cmdline_r
Passing the cmdline object can be useful, e.g. to call action_help(), to get the settings of the Perinci::CmdLine, etc.
This will be passed to Perinci::Sub::GetArgs::Argv, which has this value default to 1.
Default is from PERINCI_CMDLINE_PROGRAM_NAME environment or from $0.
Specify Riap protocol version to use. Will be passed to Riap client constructor (unless you already provide a Riap client object, see riap_client).
riap_client
Set to Riap client instance, should you want to create one yourself. Otherwise will be set Perinci::Access (in PC:Classic), or Perinci::Access::Lite (in PC:Lite).
Arguments to pass to Riap client constructor. Will be used unless you create your own Riap client object (see riap_client). One of the things this attribute is used is to pass HTTP basic authentication to Riap client (Perinci::Access::HTTP::Client):
riap_client_args => {handler_args => {user=>$USER, password=>$PASS}}
Should be a hash of subcommand specifications or a coderef.
Each subcommand specification is also a hash(ref) and should contain these keys:
url (str, required)
Location of function (accessed via Riap).
summary (str, optional)
Will be retrieved from function metadata at url if unset
description (str, optional)
description
Shown in verbose help message, if description from function metadata is unset.
tags (array of str, optional)
tags
For grouping or categorizing subcommands, e.g. when displaying list of subcommands.
log_any_app (bool, optional)
log_any_app
Whether to load Log::Any::App, default is true. For subcommands that need fast startup you can try turning this off for said subcommands. See "LOGGING" for more details.
use_utf8 (bool, optional)
use_utf8
Whether to issue "binmode(STDOUT, ":utf8")". See "LOGGING" for more details.
undo (bool, optional)
Can be set to 0 to disable transaction for this subcommand; this is only relevant when undo attribute is set to true.
show_in_help (bool, optional, default 1)
show_in_help
If you have lots of subcommands, and want to show only some of them in --help message, set this to 0 for subcommands that you do not want to show.
pass_cmdline_object (bool, optional, default 0)
To override pass_cmdline_object attribute on a per-subcommand basis.
args (hash, optional)
If specified, will send the arguments (as well as arguments specified via the command-line). This can be useful for a function that serves more than one subcommand, e.g.:
subcommands => { sub1 => { summary => 'Subcommand one', url => '/some/func', args => {flag=>'one'}, }, sub2 => { summary => 'Subcommand two', url => '/some/func', args => {flag=>'two'}, }, }
In the example above, both subcommand sub1 and sub2 point to function at /some/func. But the function can differentiate between the two via the flag argument being sent.
sub1
sub2
/some/func
flag
% cmdprog sub1 --foo 1 --bar 2 % cmdprog sub2 --foo 2
In the first invocation, function will receive arguments {foo=>1, bar=>2, flag=>'one'} and for the second: {foo=>2, flag=>'two'}.
{foo=>1, bar=>2, flag=>'one'}
{foo=>2, flag=>'two'}
Subcommands can also be a coderef, for dynamic list of subcommands. The coderef will be called as a method with hash arguments. It can be called in two cases. First, if called without argument name (usually when doing --subcommands) it must return a hashref of subcommand specifications. If called with argument name it must return subcommand specification for subcommand with the requested name only.
name
Required if you only want to run one function. URL should point to a function entity.
Alternatively you can provide multiple functions from which the user can select using the first argument (see subcommands).
Whether to read environment variable for default options.
Environment name to read default options from. Default is from program name, upper-cased, sequences of dashes/nonalphanums replaced with a single underscore, plus a _OPT suffix. So if your program name is called cpandb-cpanmeta the default environment name is CPANDB_CPANMETA_OPT.
_OPT
cpandb-cpanmeta
CPANDB_CPANMETA_OPT
Whether to read configuration files.
Configuration filename(s). The default is program_name . ".conf". For example, if your program is named foo-bar, config_filename will be foo-bar.conf.
program_name . ".conf"
foo-bar
foo-bar.conf
You can specify an array of filename strings, which will be checked in order, e.g.: ["myapp.conf", "myapp.ini"].
["myapp.conf", "myapp.ini"]
You can also specify an array of hashrefs, for more complex scenario. Each hash can contain these keys: filename, section. For example:
filename
section
[ {filename => 'mysuite.conf', section=>'myapp1'}, {filename => 'myapp1.conf'}, # section = GLOBAL (default) ]
This means, configuration will be searched in mysuite.conf under the section myapp1, and then in myapp1.conf in the default/global section.
mysuite.conf
myapp1
myapp1.conf
Which directories to look for configuration file. The default is to look at the user's home and then system location. On Unix, it's [ "$ENV{HOME}/.config", $ENV{HOME}, "/etc"]. If $ENV{HOME} is empty, getpwuid() is used to get home directory entry.
[ "$ENV{HOME}/.config", $ENV{HOME}, "/etc"]
Object to cleanse result for JSON output. By default this is an instance of Data::Clean::JSON and should not be set to other value in most cases.
When a function returns result, and the user wants to display the result as JSON, the result might need to be cleansed first (using Data::Clean::JSON by default) before it can be encoded to JSON, for example it might contain Perl objects or scalar references or other stuffs. If you are sure that your function does not produce those kinds of data, you can set this to false to produce a more lightweight script.
If set to 1, assume that function returns raw text that need not be translated, and so will not offer common command-line options --format, --json, as well as --naked-res.
--json
As an alternative to this, can also be done on a per-function level by setting function metadata property cmdline.skip_format to true. Or, can also be done on a per-function result basis by returning result metadata cmdline.skip_format set to true.
Whether or not to set utf8 flag on output. If undef, will default to UTF8 environment. If that is also undef, will default to 0.
If set to 1, then dry-mode will be turned on by default unless user uses DRY_RUN=0 or --no-dry-run.
--no-dry-run
The main method to run your application. See "PROGRAM FLOW" for more details on what this method does.
Called by run().
Called by parse_argv() or do_dump() or do_completion(). Subclass has to implement this.
Can be set to 1 to force using viewer to view result. Can be set to 0 to explicitly disable using viewer to view result even though cmdline.view_result result metadata attribute is active.
cmdline.view_result
Can be set to select the viewer program to override cmdline.viewer. Can also be set to '' or 0 to explicitly disable using viewer to view result even though cmdline.view_result result metadata attribute is active.
0
Can be set to 1 to force paging of result. Can be set to 0 to explicitly disable paging even though cmd.page_result result metadata attribute is active.
cmd.page_result
Like in other programs, can be set to select the pager program (when cmdline.page_result result metadata is active). Can also be set to '' or 0 to explicitly disable paging even though cmd.page_result result metadata is active.
When VIEWER is not set, then this environment variable will be used to select external viewer program.
Can be used to set CLI program name.
To set default for use_utf8 attribute.
Please visit the project's homepage at https://metacpan.org/release/Perinci-CmdLine-Lite.
Source repository is at https://github.com/perlancar/perl-Perinci-CmdLine-Lite.
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-CmdLine-Lite
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
perlancar <perlancar@cpan.org>
This software is copyright (c) 2017, 2016, 2015, 2014 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Perinci::CmdLine::Lite, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perinci::CmdLine::Lite
CPAN shell
perl -MCPAN -e shell install Perinci::CmdLine::Lite
For more information on module installation, please visit the detailed CPAN module installation guide.