CliMate.CLI.Command behaviour (CLI Mate v0.11.0)

Copy Markdown View Source

A behaviour to define module-based commands.

A command is a keyword list (or a module implementing this behaviour) and accepts these top-level entries:

  • :options — option schema (see CliMate.CLI.Option).
  • :arguments — positional argument schema.
  • :subcommands — a keyword list of nested commands. A command cannot declare both :arguments and :subcommands; the first positional slot is consumed as the sub-command name. A sub-command value can be an inline keyword list, or a module implementing this behaviour.
  • :execute — a 1-arity function called with the parsed result. Also provided via the execute/1 callback on module-based commands. When a command with :execute is selected, CliMate.CLI.parse/2 returns the parsed map with an :execute key holding a zero-arity closure; calling it runs the function with the parsed map (minus the :execute key). Returns nil when no execute is defined or when --help was requested.
  • :name, :version, :doc — metadata used by format_usage/2.

Option inheritance across sub-commands

Options declared on a parent command are inherited by sub-commands and can be passed on any level where the command is being parsed. Arguments given before a sub-command name are parsed with the options known at that level, and arguments given after it with the options of the sub-command, including the inherited ones.

  • Redefining an option at a child level replaces the parent entry entirely, including :short, :default, :cast and :deprecated. The child definition must keep the same :type and :keep settings, otherwise an ArgumentError is raised. Use :cast to change the final value.
  • When a child option uses the same :short as an inherited option, the short refers to the child option after the sub-command name. The inherited option is still available with its long name.
  • Values given on several levels are combined as if they were given on a single level: the last value wins, :keep lists are concatenated and :count occurrences are summed.
  • The default value, the cast function and the deprecation warning are taken from the definition of the selected sub-command, whatever the level the value was given on.

Summary

Callbacks

Returns a command definition to be used with the parser, or invoked as a sub command.

Functions

Builds a command struct from a keyword definition, or from a module implementing this behaviour.

Resolves a sub-command name given on the command line into its definition from the parent command.

Types

argument()

@type argument() :: [argument_opt()]

argument_opt()

@type argument_opt() ::
  {:required, boolean()}
  | {:type, CliMate.CLI.Argument.vtype()}
  | {:doc, binary() | nil}
  | {:cast, nil | CliMate.CLI.Argument.caster()}
  | {:repeat, boolean()}

command()

@type command() :: [command_opt()]

command_opt()

@type command_opt() ::
  {:name, String.t()}
  | {:version, String.t()}
  | {:module, module()}
  | {:doc, String.t()}
  | {:options, [{atom(), option()}]}
  | {:arguments, [{atom(), argument()}]}
  | {:subcommands, [{atom(), command() | module() | t()}]}
  | {:execute, (map() -> term())}

option()

@type option() :: [option_opt()]

option_opt()

@type option_opt() ::
  {:doc, String.t()}
  | {:type, CliMate.CLI.Option.vtype()}
  | {:short, atom()}
  | {:default, term()}
  | {:keep, boolean()}
  | {:doc_arg, String.t()}
  | {:default_doc, String.t()}
  | {:cast, nil | CliMate.CLI.Option.caster()}
  | {:deprecated, nil | boolean() | String.t()}

t()

@type t() :: %CliMate.CLI.Command{
  arguments: [CliMate.CLI.Argument.t()],
  doc: binary() | nil,
  execute: (-> term()) | nil,
  module: module() | nil,
  name: binary() | nil,
  options: [{atom(), CliMate.CLI.Option.t()}],
  subcommands: [{atom(), command() | module() | t()}],
  version: binary() | nil
}

Callbacks

command()

@callback command() :: command()

Returns a command definition to be used with the parser, or invoked as a sub command.

execute(parsed)

(optional)
@callback execute(CliMate.CLI.parsed()) :: term()

Functions

new(command)

Builds a command struct from a keyword definition, or from a module implementing this behaviour.

The accepted entries are listed in the module documentation. Raises an ArgumentError for invalid definitions, for instance when a command declares both :arguments and :subcommands.

Examples

The returned struct holds the normalized options, including the automatic :help option:

iex> command = CliMate.CLI.Command.new(name: "hello", options: [upcase: [type: :boolean]])
iex> command.name
"hello"
iex> Keyword.keys(command.options)
[:upcase, :help]

resolve_subcommand(command, bin_key)

Resolves a sub-command name given on the command line into its definition from the parent command.

Returns {:ok, key, sub_command} where key is the atom form of bin_key and sub_command is the resolved definition built with new/1. Returns {:error, {:unknown_subcommand, bin_key}} when the name matches no declared sub-command.