NAME
Perinci::CmdLine::Base - Base class for Perinci::CmdLine{::Classic,::Lite}
VERSION
This document describes version 1.914 of Perinci::CmdLine::Base (from Perl distribution Perinci-CmdLine-Lite), released on 2021-12-10.
DESCRIPTION
Perinci::CmdLine is a command-line application framework. It allows you to create full-featured CLI applications easily and quickly.
See Perinci::CmdLine::Manual for more details.
There is also a blog post series on Perinci::CmdLine tutorial: https://perlancar.wordpress.com/category/pericmd-tut/
PROGRAM FLOW (NORMAL)
If you execute run()
, this is what will happen, in order:
Detect if we are running under tab completion mode
This is done by checking the existence of special environment variables like
COMP_LINE
(bash) orCOMMAND_LINE
(tcsh). If yes, then jump to "PROGRAM FLOW (TAB COMPLETION)". Otherwise, continue.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").Some ideas that you can do in this hook: XXX.
Parse command-line arguments (@ARGV) and set
action
If
read_env
attribute is set to true, and there is environment variable defined to set default options (see documentation onread_env
andenv_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 calledfoo
and environment variableFOO_OPT
is set to--opt1 --opt2 val
. When you execute:% 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
).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 tocmd 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 optioncmd --cmd subcmd
because we want to support the notion of "default subcommand" (subcommand that takes effect if there is no subcommand specified).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
andversion
and the second step will be skipped. Otherwise we continue the second step and action by default is set tocall
.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.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 (theargs
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 calledfoo_bar
will become command-line option--foo-bar
. Command-line aliases from metadata are also added to theGetopt::Long
spec.Config file: It is also at this step that we read config file (if
read_config
attribute is true). We runhook_before_read_config_file
first. Some ideas to do in this hook: setting default config profile. For each found config section, we also runhook_config_file_section
first. The hook will be fed($r, $section_name, $section_content)
and should return 200 status or 204 (no content) to skip this config section or 4xx/5xx to terminate config reading with an error message. After config files are read, we runhook_after_read_config_file
.We then pass the spec to
Getopt::Long::GetOptions
, we get function arguments.We then run
hook_after_parse_argv
. Some ideas to do in this hook: XXX.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).Delegate to
action_$action
methodBefore running the
action_$action
method,hook_before_action
is called e.g. to allow changing/fixing action, last chance to check arguments, etc.After we get the action from the previous step, we delegate to separate
action_$action
method (so there isaction_version
,action_help
, and so on; and alsoaction_call
). These methods also receive$r
as their argument and must return an enveloped result (see Rinci::function for more details).Result is put in
$r->{res}
.hook_after_action
is then called e.g. to preformat result.Run hook_format_result
Hook must set
$r->{fres}
(formatted result).If
skip_format
attribute is true, or function metadata hascmdline.skip_format
set to true, or result hascmdline.skip_format
metadata property set to true, then this step is skipped and$r->{fres}
is simply taken from$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, willexit()
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.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'}
.
PROGRAM FLOW (TAB COMPLETION)
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
.
The result is then output to STDOUT (resume from Run hook_format_result step in the normal program flow).
PLUGINS
My long-term goal is to have ScriptX (which is a plugin-oriented framework) as a replacement for Perinci::CmdLine. Since ScriptX is still in early development, I am adding plugin support to Perinci::CmdLine too (as of 1.900). Plugin support is similar to how ScriptX does plugins. Documentation is currently sparse; please see existing plugins in Perinci::CmdLine::Plugin::*, the ScriptX documentation, as well as the source code directly to get an idea of how plugin works. These are the characteristics of the plugin system: you can customize at which event any plugin runs (flexibility), you can customize the priority of each plugin for an event (flexibility), a "before-event-foo" plugin can cancel the "foo" event, an "after-event-foo" plugin can repeat the "foo" event.
With plugin support, the hook_*()
methods will be phased out eventually. Some features will be moved to plugins in subsequent releases. More plugins will be added, either in this distribution, or in separate distributions. More events will be added to add more "hooks".
Plugin events
Currently only a few events have been added, as not all hook_*()
methods have been converted to plugin events yet. More events will be added in the future. Also note that for all events there are the two additional before_$event
and after_$event
(included below for ease of search).
activate_plugin
This event can be used to disable other plugins (see Perinci::CmdLine::Plugin::DisablePlugin) or do things when a plugin is loaded.
before_activate_plugin
after_activate_plugin
validate_args
Before this event,
$r->{args}
is already set to the input arguments, but they are not validated yet.After this event,
$r->{args}
should have already been validated.before_validate_args
after_validate_args
action
After this event,
$r->{res}
should have already been set to the result.before_action
after_action
Activating plugins
From the source code
(Currently no public API, but you can see the source code, particularly the
_plugin_activate_plugins()
method).From configuration file (special parameter
-plugins
)Special parameters
-plugins
will activate plugins, e.g.:-plugins = -DumpArgs
another example:
-plugins = ["-DumpArgs", "-DumpRes"]
From configuration file ([plugin=...] sections)
For example:
[plugin=DumpArgs] [plugin=DumpArgs] -event=before_validate_args [plugin=DisablePlugins] plugins = DumpArgs,DumpConfig
From environment variable
See "PERINCI_CMDLINE_PLUGINS" and "PERINCI_CMDLINE_PLUGINS_JSON" under "ENVIRONMENT".
REQUEST KEYS
The various values in the $r
hash/stash.
orig_argv => array
Original
@ARGV
at the beginning ofrun()
.common_opts => hash
Value of
common_opts
attribute, for convenience.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
.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 setting can be turned off e.g. in common option
no_env
. This is never set to true whenread_env
attribute is set to false, which means that we never try to read environment.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()
.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.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.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 thedefault_subcommand
attribute. Undef if there is no subcommand name in effect.subcommand_name_from => str
Also set by
parse_argv()
. Tells how thesubcommand_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 todefault_subcommand
attribute), or undef if there is no subcommand_name set.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 fromurl
attribute, summary fromsummary
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()
.dry_run => bool
Whether to pass
-dry_run
special argument to function.res => array
Enveloped result of
action_ACTION()
.fres => str
Result from
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
.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.
page_result => bool
pager => str
HOOKS
All hooks will receive the argument $r
, a per-request hash/stash. The list below is by order of calling.
$cmd->hook_before_run($r)
Called at the start of run()
. Can be used to set some initial values of other $r
keys. Or setup the logger.
$cmd->hook_before_read_config_file($r)
Only called when read_config
attribute is true.
$cmd->hook_after_read_config_file($r)
Only called when read_config
attribute is true.
$cmd->hook_after_get_meta($r)
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).
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.
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.
$cmd->hook_after_parse_argv($r)
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.
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).
$cmd->hook_before_action($r)
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.
PC:Lite uses this hook to validate function arguments. PC:Classic does not do this because it uses function wrapper which already does this.
$cmd->hook_after_action($r)
Called after calling action_ACTION
method. Some ideas to do in this hook: preformatting result ($r->{res}
).
$cmd->hook_format_result($r)
The hook is supposed to format result in $res-
{res}> (an array).
All direct subclasses of PC:Base do the formatting here.
$cmd->hook_display_result($r)
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.
All direct subclasses of PC:Base do the formatting here.
$cmd->hook_after_run($r)
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.
SPECIAL ARGUMENTS
Below is list of special arguments that may be passed to your function by the framework. Per Rinci specification, these are prefixed by -
(dash).
-dry_run => bool
Only when in dry run mode, to notify function that we are in dry run mode.
-cmdline => obj
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.
-cmdline_r => hash
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.
-cmdline_src_ARGNAME => str
This will be set if argument is retrieved from file
, stdin
, stdin_or_file
, stdin_or_files
, or stdin_line
.
-cmdline_srcfilenames_ARGNAME => array
An extra information if argument value is retrieved from file(s), so the function can know the filename(s).
METADATA PROPERTY ATTRIBUTE
This module observes the following Rinci metadata property attributes:
cmdline.default_format => STR
Set default output format (if user does not specify via --format command-line option).
cmdline.skip_format => bool
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.
METADATA'S ARGUMENT SPECIFICATION ATTRIBUTE
RESULT METADATA
This module interprets the following result metadata property/attribute:
attribute: cmdline.exit_code => int
Instruct to use this exit code, instead of using (function status - 300).
attribute: cmdline.result => any
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.
attribute: cmdline.result.interactive => any
Like cmdline.result
but when script is run interactively.
attribute: cmdline.result.noninteractive => any
Like cmdline.result
but when script is run non-interactively (in a pipeline).
attribute: cmdline.default_format => str
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.
attribute: cmdline.page_result => bool
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.
For example:
$SPEC{doc} = { ... };
sub doc {
...
[200, "OK", $doc, {"cmdline.page_result"=>1}];
}
attribute: cmdline.pager => STR
Instruct to use specified pager instead of $ENV{PAGER}
or the default less
or more
.
attribute: cmdline.view_result => bool
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.)
attribute: cmdline.viewer => STR
Instruct to use specified viewer instead of $ENV{VIEWER}
or $ENV{BROWSER}
.
attribute: cmdline.skip_format => bool (default: 0)
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.
attribute: x.perinci.cmdline.base.exit_code => int
This is added by this module, so exit code can be tested.
CONFIGURATION FILE SUPPORT
TBD.
ATTRIBUTES
actions => array
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:
common_opts => hash
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
.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
).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
).
Sometimes you do not want some options, e.g. to remove format
and 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
:
$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
completion => code
Will be passed to Perinci::Sub::Complete's complete_cli_arg()
. See its documentation for more details.
default_subcommand => str
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
.
auto_abbrev_subcommand => bool (default: 1)
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:
% myapp c
If there are subcommands create
, modify
, move
, delete
, then c
is assumed to be create
. But if:
% 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.
get_subcommand_from_arg => int (default: 1)
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).
description => str
A short description of the application.
exit => bool (default: 1)
Define the application exit behaviour. A false value here allows hook code normally run directly before the application exits to be skipped.
formats => array
Available output formats.
default_format => str
Default format.
allow_unknown_opts => bool (default: 0)
Whether to allow unknown options.
pass_cmdline_object => bool (default: 0)
Whether to pass special argument -cmdline
containing the cmdline object to function. This can be overridden using the pass_cmdline_object
on a per-subcommand basis.
In addition to -cmdline
, -cmdline_r
will also be passed, containing the $r
per-request stash/hash (see "REQUEST KEYS").
Passing the cmdline object can be useful, e.g. to call action_help(), to get the settings of the Perinci::CmdLine, etc.
per_arg_json => bool (default: 1 in ::Lite)
This will be passed to Perinci::Sub::GetArgs::Argv.
per_arg_yaml => bool (default: 0 in ::Lite)
This will be passed to Perinci::Sub::GetArgs::Argv.
program_name => str
Default is from PERINCI_CMDLINE_PROGRAM_NAME environment or from $0.
riap_version => float (default: 1.1)
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 => obj
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).
riap_client_args => hash
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}}
subcommands => hash | code
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 unsetdescription
(str, optional)Shown in verbose help message, if description from function metadata is unset.
tags
(array of str, optional)For grouping or categorizing subcommands, e.g. when displaying list of subcommands.
use_utf8
(bool, optional)Whether to issue
use open, ":utf8"
. Alternative:use_locale
. Takes precedence overuse_locale
.use_locale
(bool, optional)Whether to issue
use open, ":locale"
. Alternative:use_utf8
.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)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
andsub2
point to function at/some/func
. But the function can differentiate between the two via theflag
argument being sent.% 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'}
.
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.
summary => str
Optional, displayed in description of the option in help/usage text.
tags => array of str
For grouping or categorizing subcommands, e.g. when displaying list of subcommands.
url => str
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).
read_env => bool (default: 1)
Whether to read environment variable for default options.
env_name => str
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
.
read_config => bool (default: 1)
Whether to read configuration files.
config_filename => str|array[str]|array[hash]
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
.
You can specify an array of filename strings, which will be checked in order, e.g.: ["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 => '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.
config_dirs => array of str
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.
cleanser => obj
Object to cleanse result for JSON output. By default this is an instance of Data::Clean::ForJSON and should not be set to other value in most cases.
use_cleanser => bool (default: 1)
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::ForJSON 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.
extra_urls_for_version => array of str
An array of extra URLs for which version information is to be displayed for the action being performed.
skip_format => bool
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
.
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.
use_utf8 => bool (default: from env UTF8, or 0)
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.
default_dry_run => bool (default: 0)
If set to 1, then dry-mode will be turned on by default unless user uses DRY_RUN=0 or --no-dry-run
.
log => bool
Whether to enable logging. Default is off. If true, will load Log::ger::App.
log_level => str
Set default log level. Will be overridden by $r->{log_level}
which is set from command-line options like --log-level
, --trace
, etc.
METHODS
$cmd->run() => ENVRES
The main method to run your application. See "PROGRAM FLOW (NORMAL)" for more details on what this method does.
$cmd->do_dump() => ENVRES
Called by run().
$cmd->do_completion() => ENVRES
Called by run().
$cmd->parse_argv() => ENVRES
Called by run().
$cmd->get_meta($r, $url) => ENVRES
Called by parse_argv() or do_dump() or do_completion(). Subclass has to implement this.
ENVIRONMENT
BROWSER
String. When "VIEWER" is not set, then this environment variable will be used to select external viewer program.
LOG_DUMP_CONFIG
Boolean. If set to true, will dump parsed configuration at the trace level.
PAGE_RESULT
Boolean. 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.
See also: "PAGER".
PAGER
String. 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.
PERINCI_CMDLINE_DUMP_ARGS
Boolean. If set to true, instead of running normal action, will instead dump arguments that will be passed to function, (after merge with values from environment/config files, and validation/coercion), in Perl format (using Data::Dump) and exit.
Useful for debugging or information extraction.
PERINCI_CMDLINE_DUMP_CONFIG
Boolean. If set to true, instead of running normal action, will dump configuration that is using read_config()
, in Perl format (using Data::Dump) and exit.
Useful for debugging or information extraction.
PERINCI_CMDLINE_DUMP_OBJECT
String. Default undef. If set to a true value, instead of running normal action, will dump Perinci::CmdLine object at the start of run() in Perl format (using Data::Dump) and exit. Useful to get object's attributes and reconstruct the object later. Used in, e.g. App::shcompgen to generate an appropriate completion script for the CLI, or Pod::Weaver::Plugin::Rinci to generate POD documentation about the script. See also Perinci::CmdLine::Dump.
The value of the this variable will be used as the label in the dump delimiter, .e.g:
# BEGIN DUMP foo
...
# END DUMP foo
Useful for debugging or information extraction.
PERINCI_CMDLINE_OUTPUT_DIR
String. If set, then aside from displaying output as usual, the unformatted result (enveloped result) will also be saved as JSON to an output directory. The filename will be UTC timestamp in ISO8601 format.out
, e.g.:
2017-12-11T123456.000000000Z.out
2017-12-11T123456.000000000Z.out.1 (if the same filename already exists)
or each output (.out
) file there will also be a corresponding .meta
file that contains information like: command-line arguments, PID, etc. Some notes:
Output directory must already exist, or Perinci::CmdLine will display a warning and then skip saving output.
Data that is not representable as JSON will be cleansed using Data::Clean::ForJSON.
Streaming output will not be saved appropriately, because streaming output contains coderef that will be called repeatedly during the normal displaying of result.
PERINCI_CMDLINE_PLUGINS
String. A list of plugins to load at the start of program. Format:
-PluginName1,arg1name,arg1val,arg2name,arg2val,...,-PluginName2,...
Plugin name is module name without the Perinci::CmdLine::Plugin::
prefix. The argument list can be skipped if you don't want to pass arguments to a plugin.
PERINCI_CMDLINE_PLUGINS_JSON
String. Like "PERINCI_CMDLINE_PLUGINS" but assumed to be in JSON encoding, to be able to encode data structure (for complex arguments). Syntax:
["PluginName1",{"arg1name":"arg1val","arg2name":"arg2val",...},"PluginName2", ...]
Plugin name is module name without the Perinci::CmdLine::Plugin::
prefix. The hash can be skipped if you don't want to pass arguments to a plugin.
PERINCI_CMDLINE_PROGRAM_NAME
String. Can be used to set CLI program name.
UTF8
Boolean. To set default for use_utf8
attribute.
VIEW_RESULT
Boolean. 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.
VIEWER
String. 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.
See also "BROWSER".
HOMEPAGE
Please visit the project's homepage at https://metacpan.org/release/Perinci-CmdLine-Lite.
SOURCE
Source repository is at https://github.com/perlancar/perl-Perinci-CmdLine-Lite.
AUTHOR
perlancar <perlancar@cpan.org>
CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on GitHub.
Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:
% prove -l
If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla plugin and/or Pod::Weaver::Plugin. Any additional steps required beyond that are considered a bug and can be reported to me.
COPYRIGHT AND LICENSE
This software is copyright (c) 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014 by perlancar <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.
BUGS
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.