# `Cheer.Command.DSL`
[🔗](https://github.com/joshrotenberg/cheer/blob/v0.2.1/lib/cheer/command/dsl.ex#L1)

Macros for declaring commands, arguments, options, subcommands,
lifecycle hooks, param groups, and validation.

# `about`
*macro* 

Set the command's description text, shown in help output.

# `after_help`
*macro* 

Set text displayed after the auto-generated help.

# `after_run`
*macro* 

Run a function on the result after `run/2`. Receives and returns result.

# `aliases`
*macro* 

Set subcommand aliases (e.g. `aliases ["co", "ck"]` for `checkout`).

# `args_conflicts_with_subcommands`
*macro* 

Make subcommands optional so an unknown first token falls through to this
command's own positional arguments.

Without this, a command that declares both `argument`s and `subcommand`s
treats an unrecognized first token as an unknown command and errors. With it,
a token that does not match a declared subcommand is parsed as a positional
argument and option parsing continues across it, so the parent command runs.
Declared subcommands still take precedence: an exact (or, with
`infer_subcommands`, an unambiguous prefix) match dispatches to the
subcommand.

    command "roba" do
      args_conflicts_with_subcommands(true)

      argument :prompt, type: :string, required: false
      subcommand Roba.Commands.History
    end

`roba history` dispatches to the subcommand, while `roba "summarize this"
--model haiku` runs the parent with `prompt: "summarize this"` and
`model: "haiku"`.

# `argument`
*macro* 

Declare a positional argument.

Arguments are matched in declaration order. Options:

  * `:type` - `:string` (default), `:integer`, `:float`, or `:boolean`
  * `:required` - `true` or `false` (default)
  * `:num_args` - collect several positional tokens into a list: an integer for
    an exact count or a range (`1..3`) for a variable count. Consumption is
    greedy (up to the max), so a variadic argument should be declared last. Too
    few values is a usage error.
  * `:choices` - list of allowed values
  * `:help` - help text shown in `--help`
  * `:long_help` - extended help text shown by `--help` (long form)
  * `:value_name` - placeholder name in help (e.g. `"FILE"`)
  * `:hide` - `true` to hide from help output
  * `:deprecated` - `true` for a bare marker, or a string reason; shown in help
  * `:display_order` - integer controlling position in help (lower first)
  * `:validate` - `fn value -> :ok | {:error, msg} end`
  * `:parse` - `fn value -> {:ok, parsed} | {:error, msg} end` to transform the
    value into a domain type (runs after coercion, before `:validate`)

# `before_help`
*macro* 

Set text displayed before the auto-generated help.

# `before_run`
*macro* 

Run a function on args before `run/2`. Receives and returns args map.

# `command`
*macro* 

Define a command block with the given `name`.

All DSL calls (`about`, `argument`, `option`, `subcommand`, etc.) go inside the block.

    command "deploy" do
      about "Deploy the app"
      option :env, type: :string, required: true
    end

# `deprecated`
*macro* 

Mark this command as deprecated. Shows a `(deprecated)` marker in the parent's
help and prints a warning to stderr when the command is used. Pass a string to
include a reason (and a migration hint).

    command "old-name" do
      deprecated "use `new-name` instead"
    end

# `display_order`
*macro* 

Set this command's display order as a subcommand in its parent's help output.

Lower numbers appear first. Commands without an explicit order fall back to
declaration order in the parent.

# `external_subcommands`
*macro* 

Allow this command to accept unknown subcommands (e.g. plugins on `$PATH`).

When enabled, any argv token that does not match a declared subcommand and is
not an option is captured and surfaced to `run/2` via
`args[:external_subcommand]` as `{name, rest_argv}`. Declared subcommands
still take precedence. Commands that opt in should generally not also declare
positional arguments -- leftover positionals are routed to the external-sub
capture, not to arguments.

Example: a `git`-style plugin dispatcher that execs `git-<name>` from `$PATH`.

    command "git-like" do
      external_subcommands(true)

      # ... declared subs, options ...
    end

    def run(args, _raw) do
      case args[:external_subcommand] do
        {name, rest} -> System.cmd("git-#{name}", rest)
        nil -> :ok
      end
    end

# `group`
*macro* 

Define a named group of options with a constraint.

Supports:
  * `mutually_exclusive: true` -- at most one option in the group can be set
  * `co_occurring: true` -- all or none of the options must be set
  * `required: true` -- at least one option in the group must be set

Constraints combine: `mutually_exclusive: true, required: true` means exactly
one member must be set.

# `hide`
*macro* 

Hide this command from its parent's help, shell completion, and unknown-command
listings. The command stays fully dispatchable; only its visibility is affected.

Useful for internal, experimental, or legacy commands.

    command "debug" do
      hide true
    end

# `infer_subcommands`
*macro* 

Allow matching subcommands from unambiguous name prefixes.

When enabled, `che` will resolve to `checkout` if no other subcommand starts
with `che`. Ambiguous prefixes produce an error listing the candidates.
Exact matches always take precedence over prefix inference. Matching is
done against canonical names only -- aliases are not prefix-matched.

# `long_about`
*macro* 

Set the command's extended description, shown by `--help` (long form).

# `option`
*macro* 

Declare a named option (flag).

Options:

  * `:type` - `:string` (default), `:integer`, `:float`, `:boolean`, or `:count`
  * `:short` - single-character alias atom (e.g. `:p` for `-p`)
  * `:required` - `true` or `false` (default)
  * `:default` - default value when not provided (`:count` defaults to `0`, `:multi` defaults to `[]`)
  * `:default_missing_value` - value used when the flag is present with no value
    (`--color` alone). Distinct from `:default` (flag absent). An explicit value
    must use the `--flag=value` form; `--flag value` leaves `value` as a positional.
  * `:multi` - `true` to allow repeated flags collected into a list (e.g. `--tag a --tag b`)
  * `:num_args` - collect several values from a single flag invocation into a list:
    an integer for an exact count (`num_args: 2` accepts `--point 1 2`) or a range
    for a variable count (`num_args: 1..3`). Collection stops at the next flag or
    `--`. Distinct from `:multi`, which repeats the flag. An out-of-range count is a
    usage error. Negative numbers are always accepted as values (`--range -5 5`).
  * `:allow_hyphen_values` - `true` to accept a value that starts with `-`, such
    as `--pattern -v` or `--range -a -b` (with `num_args`). Without it, only
    negative numbers are accepted as hyphen-leading values.
  * `:value_delimiter` - split a single value on this string into a list, e.g.
    `value_delimiter: ","` makes `--tags a,b,c` yield `["a", "b", "c"]`. Each
    element is coerced to `:type` and checked against `:choices`. Combines with
    `:multi` (each occurrence is split and the results flattened).
  * `:parse` - `fn value -> {:ok, parsed} | {:error, msg} end` to transform the
    value into a domain type (an atom, a `Date`, a struct). Runs after `:type`
    coercion and `:value_delimiter` splitting, before `:choices` and `:validate`.
    For a list value (`:multi`, `:num_args`, `:value_delimiter`) it is applied to
    each element.
  * `:env` - environment variable name to read as fallback
  * `:choices` - list of allowed values
  * `:help` - help text shown in `--help`
  * `:long_help` - extended help text shown by `--help` (long form)
  * `:value_name` - placeholder name in help (e.g. `"FILE"`)
  * `:hide` - `true` to hide from help output
  * `:deprecated` - `true` for a bare marker, or a string reason; shown in help
    and warned to stderr when the option is used
  * `:global` - `true` to propagate to all subcommands
  * `:aliases` - list of alternative long names (e.g. `[:colour]` for `:color`)
  * `:display_order` - integer controlling position within its help section (lower first)
  * `:help_heading` - string; options sharing a heading are grouped under it in help
  * `:conflicts_with` - atom or list of atoms; this option cannot be used with the named option(s)
  * `:requires` - atom or list of atoms; the named option(s) must also be present
  * `:required_if` - keyword list `[other_opt: value]`; this option is required when
    any pair matches (i.e. `args[other_opt] == value`)
  * `:required_if_all` - keyword list `[other_opt: value]`; required only when
    every pair matches
  * `:required_unless` - atom or list of atoms; this option is required unless any
    of the named options are present
  * `:required_unless_all` - list of atoms; required unless all of the named
    options are present
  * `:validate` - `fn value -> :ok | {:error, msg} end`

Boolean options automatically support `--no-<name>` negation (e.g. `--no-color`).

Extra positional arguments after `--` are collected into `args[:rest]`.

# `parse_only`
*macro* 

Declare that this command is resolved with `Cheer.parse/3` and has no `run/2`.

A leaf command normally has to implement `run/2`, and the compiler warns when
it does not, because dispatch would reach a dead end. A tree consumed through
`Cheer.parse/3` never dispatches: argv is resolved and validated, and the
caller decides what to do with the args. This declares that intent, so the
leaf check stays out of the way.

    command "myapp" do
      parse_only()

      about "A server configured from argv"
      option :transport, type: :string, choices: ["stdio", "http"]
    end

`Cheer.run/3` on a command declared this way raises, pointing at `parse/3`,
rather than failing on the missing callback.

It is a per-command declaration, not inherited: the leaf without a handler is
the one that declares it. Declaring it on a command that implements `run/2`
anyway changes nothing, and that command still dispatches.

# `persistent_before_run`
*macro* 

Like `before_run`, but inherited by all child subcommands.

# `propagate_version`
*macro* 

Propagate this command's version to all subcommands.

# `subcommand`
*macro* 

Register a child subcommand module.

# `subcommand_required`
*macro* 

Require that a subcommand is provided (error instead of showing help).

# `trailing_var_arg`
*macro* 

Declare a named trailing variable argument.

Everything after the last declared positional (or after `--`) is collected
and available as `args[name]` instead of the default `:rest` key. The name
and help text are shown in the usage and help output.

Options:
  * `:help` - help text shown in `--help`
  * `:required` - `true` if at least one trailing arg must be provided

# `usage`
*macro* 

Override the auto-generated usage line in help output.

# `validate`
*macro* 

Cross-parameter validation function. Receives args map, returns `:ok` or `{:error, msg}`.

# `version`
*macro* 

Set the command's version string, printed by `--version` / `-V`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
