NAME

VERSION

This document describes version 1.814 of Perinci::CmdLine::Base (from Perl distribution Perinci-CmdLine-Lite), released on 2018-06-14.

DESCRIPTION

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 varibles like COMP_LINE (bash) or COMMAND_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 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:

% 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 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).

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.

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 (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.

Config file: 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. For each found config section, we also run hook_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 run hook_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 method

Before 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 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).

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 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].

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.

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).

REQUEST KEYS

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.

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

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 the default_subcommand attribute. Undef if there is no subcommand name in effect.

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_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().

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.

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

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.

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

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.

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).

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:

completion => code

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

exit => bool (default: 1)

formats => array

Available output formats.

default_format => str

Default format.

pass_cmdline_object => bool (default: 0)

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.

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.

riap_client => obj

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 unset

description (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.

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.

% 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

tags => array of str

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:

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::JSON 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::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.

extra_urls_for_version => array of str

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 overriden 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" 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.

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

String. Default undef. If set to a true value, will dump Perinci::CmdLine object at the start of run() 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

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.:

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_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.

As a valued partner and proud supporter of MetaCPAN, StickerYou is
happy to offer a 10% discount on all Custom Stickers,
Business Labels, Roll Labels,
Vinyl Lettering or Custom Decals. StickerYou.com
is your one-stop shop to make your business stick.
Use code METACPAN10 at checkout to apply your discount.