class

Jargon::CLI

Inherits Reference < Object

A command-line parser driven by one or more schemas. A CLI is either flat (a single schema) or in subcommand mode (a map of named subcommands, each its own Schema or nested CLI). Build one with Jargon.cli/Jargon.new, then parse arguments into a Result, json straight to validated data, or run to also handle --help, completion, and error exits.

Constants

STDIN_JSON = "-@"

Alone on a command line, or after the subcommand, it reads options as JSON from stdin (xerp mark -@ < options.json).

Constructors

from_file(path : String, program_name : String = "cli") : CLI

Create a CLI from a JSON or YAML schema file. Auto-detects multi-doc format for subcommands.

Source
from_json(json : String, program_name : String = "cli") : CLI

Create a CLI from a JSON schema string. Auto-detects multi-doc format (relaxed JSONL) for subcommands.

Source
from_yaml(yaml : String, program_name : String = "cli") : CLI

Create a CLI from a YAML schema string. Auto-detects multi-doc format for subcommands.

Source
new(schema : Schema, program_name : String = "cli")
Source
new(program_name : String)
Source

Instance methods

bare_assignment(enabled : Bool)

Control whether a bare key=value token — no leading dashes — may implicitly assign to a named property. On by default. When off, such a token is never read as an assignment: it falls to positional capture if a slot is open, otherwise it is an unexpected argument. Turn it off for deterministic parsing with zero implicit-assignment magic, e.g. when operands legitimately contain = (name=value pairs passed through to another tool) and you never want one silently absorbed as a property. Note that a positional slot already captures =-bearing operands literally regardless of this setting; the switch only governs the implicit-assignment fallback. It does not affect --flag=value, which is standard long-option syntax and always honored. Applies to this CLI and its directly attached Schema subcommands; a nested CLI keeps its own setting. (A colon is never an assignment separator: key:value is always an ordinary token.)

Source
bare_assignment?
Source
bash_completion(command : String = @program_name) : String

Generate a shell completion shim. By default it calls back into this program; pass command: to point completion at a separate (e.g. lighter) binary that answers the hidden __complete verb.

Source
completer(path : String, &block : Completion::Context -> Array(String))

Register a dynamic completer for a field, identified by its dotted path: the field name for a flat CLI, or subcommand.field (a.b.field when nested). The block receives a Completion::Context and returns the candidate strings. Raises if the path does not match a schema field, so typos and renames fail fast.

Source
completers
Source
config_format(*extensions : String, &block : String -> T) : self forall T

Read config files ending in any of extensions with the block, which turns a file's text into anything that can be written as JSON: a TOML library's TOML.parse, say. An added format is looked for ahead of YAML and JSON, and ahead of formats added after it, its extensions in the order given, so where a directory has both app.toml and app.yaml, app.toml takes precedence. Adding yaml, yml, or json replaces that extension's parser, and it keeps its place.

cli.config_format("toml") { |text| TOML.parse(text) }
cli.config_format("yaml", "yml") { |text| YAML.parse(text) } # in place of Jargon's YAML reader
Source
config_paths(*, project : Bool = false) : Array(String)

Returns the list of config paths load_config would search, given the same project: setting.

Source
default_subcommand(name : String)

Set the subcommand used when arguments name none.

Source
default_subcommand
Source
fish_completion(command : String = @program_name) : String

Generate a shell completion shim. By default it calls back into this program; pass command: to point completion at a separate (e.g. lighter) binary that answers the hidden __complete verb.

Source
handle_completion(args : Array(String) = ARGV, *, io : IO = @output, exit_process : Bool = true) : Bool

If this invocation is a completion request (the hidden __complete verb), print candidates and — unless exit_process: false — exit 0. Returns true when it handled completion, false otherwise, so it can be called early in a program (before heavy initialization) or as the whole body of a dedicated completion helper binary. The developer never types the verb itself; the generated shim supplies it.

Source
help(subcommand : String) : String

Render help for a single subcommand. subcommand is space-separated for nested commands (e.g. "remote add"). Raises ArgumentError for a subcommand the CLI doesn't have, as validate does.

Source
help

Render the program's help text: a command listing when subcommands are defined, an option listing for a flat CLI, or a bare usage line otherwise.

Source
json(args : Array(String), input : IO, *, defaults : Defaults | Nil = nil) : JSON::Any
Source
json(args : Array(String) = ARGV, *, defaults : Defaults | Nil = nil) : JSON::Any

Parse and return just the data, raising ParseError on validation errors. Use when you want the values directly and treat invalid input as fatal.

Source
load_config(*, merge : Bool = true, project : Bool = false) : JSON::Any | Nil

Load config from standard locations. Supports YAML (.yaml, .yml) and JSON (.json) files, and any format added with config_format, which is looked for ahead of them.

Paths searched (in order):

  1. ./.config/{program_name}.yaml/.yml/.json (project local, flat; project: true only)
  2. ./.config/{program_name}/config.yaml/.yml/.json (project local, directory; project: true only)
  3. $XDG_CONFIG_HOME/{program_name}.yaml/.yml/.json (user global, flat)
  4. $XDG_CONFIG_HOME/{program_name}/config.yaml/.yml/.json (user global, directory)

Project-local configs are read from the current directory, which may be one someone else controls (a freshly cloned repository), and they would take precedence over the user's own config. So they are off by default; pass project: true to opt in.

With merge: true (default), merges all configs found (project wins over user). With merge: false, returns first config found. Returns nil if no config file found.

Source
output
Source
output=(output : IO)
Source
parse(args : Array(String), input : IO, *, defaults : Defaults | Nil = nil) : Result

:ditto: input supplies the stream read for the -@ (stdin JSON) form.

Source
parse(args : Array(String) = ARGV, *, defaults : Defaults | Nil = nil) : Result

Parse arguments into a Result (parsed data plus any validation errors); never raises on invalid input. defaults seeds values not given on the command line (e.g. from a config file), below CLI args and env vars.

With subcommands, a mapping in defaults under a subcommand's name is that subcommand's section, and any other key is global. A subcommand takes the global keys it has an option for, then its section's keys over them, every one of them. A nested CLI's section holds its own subcommands' sections the same way.

Source
program_name
Source
run(args : Array(String), input : IO, *, defaults : Defaults | Nil = nil) : Result
Source
run(args : Array(String) = ARGV, *, defaults : Defaults | Nil = nil) : Result

Run the CLI with automatic --help, --completions, and error handling. Prints help/completions and exits 0, prints errors and exits 1, otherwise returns/yields result.

Source
run(args : Array(String), input : IO, *, defaults : Defaults | Nil = nil, &) : Nil
Source
run(args : Array(String) = ARGV, *, defaults : Defaults | Nil = nil, &) : Nil
Source
schema
Source
subcommand(name : String, schema : Schema)
Source
subcommand(name : String, cli : CLI)
Source
subcommand(name : String, *, json : String)
Source
subcommand(name : String, *, yaml : String)
Source
subcommand(name : String, *, file : String)

Load subcommand(s) from a file.

  • Single-doc file: requires name, loads as single subcommand
  • Multi-doc file without name: loads each doc as top-level subcommand
  • Multi-doc file with name: loads docs as nested subcommands under name
Source
subcommand(*, file : String)

Load subcommands from a multi-document file (no parent name). Each document must have a "name" field.

Source
subcommand_key(key : String)

Set the JSON key that names the subcommand when parsing full JSON from stdin (the -@ form). Defaults to "subcommand".

Source
subcommand_key
Source
subcommands
Source
validate(data : Hash(String, JSON::Any), subcommand : String | Nil = nil) : Array(String)

Validate data against a schema, returning any errors. If no schema is provided, uses the CLI's root schema. For subcommand validation, pass the subcommand name (space-separated for nested).

Source
validate(result : Result) : Array(String)

:ditto: Validate a previously parsed Result against its subcommand.

Source
zsh_completion(command : String = @program_name) : String

Generate a shell completion shim. By default it calls back into this program; pass command: to point completion at a separate (e.g. lighter) binary that answers the hidden __complete verb.

Source