Module

std::cli

CLI Module

Bounded clap-like command-line parsing helpers.

Purpose

This module provides a small, reviewable command builder and argv parser for common Ignis CLI entrypoints.

It is inspired by clap-style APIs, but it is intentionally narrower: callers declare a command, register supported flags/options, and then parse a Vector<String> or the current process arguments into owned Matches.

Supported grammar

Form Supported Notes
--flag Yes Declared boolean flag
-f Yes Declared short flag
--output file Yes Declared valued option consumes next argv item
-o file Yes Declared short valued option consumes next argv item
positional args Yes Preserved in order
-- terminator Yes All later tokens become positionals
--opt=value No Intentionally out of scope
grouped short flags (-abc) No Intentionally out of scope
defaults / env injection No Intentionally out of scope
subcommands No Intentionally out of scope

Parsing lifecycle

  Command spec
  ┌───────────────────────────────────────────┐
  │ new(name)                                 │
  │ aboutText(...)                            │
  │ flag(...) / option(...)                   │
  └────────────────────┬──────────────────────┘
                       │
                       ▼
  argv scan
  ┌───────────────────────────────────────────┐
  │ parse(&args) or parseProcess()            │
  │ - detect `--`                             │
  │ - match long/short specs                  │
  │ - collect owned option values             │
  │ - preserve ordered positionals            │
  └────────────────────┬──────────────────────┘
                       │
                       ▼
  Result
  ┌───────────────────────────────────────────┐
  │ Result::OK(Matches)                       │
  │ Result::ERROR(CliError)                   │
  └───────────────────────────────────────────┘

Ownership model

  • parseProcess() copies host argv into owned String values via Process::args().
  • parse(&args) clones only the values it needs to store in Matches.
  • Matches::value() and Matches::positional() return owned String clones so callers do not borrow from internal parser storage.

Error model

Parsing failures are explicit Result::ERROR(CliError) values. The current bounded error surface is:

  • unknown option
  • missing value for a declared valued option

Help rendering

renderHelp() is deterministic:

  • usage line first
  • about text next when present
  • option listing in declaration order

Example

import Cli from "std::cli";

function main(): i32 {
  let mut command: Cli::Command = Cli::Command::new("tool");
  command.aboutText("Build project artifacts.");
  command.flag("verbose", "v", "Enable verbose output.");
  command.option("output", "o", "Write output file.");

  match (command.parseProcess()) {
    Result::OK(matches) -> {
      if (matches.has("verbose")) {
        // verbose branch
      }
      return 0;
    },
    Result::ERROR(error) -> {
      // print error.message or renderHelp()
      return 1;
    },
  };
}
namespace Cli

CLI parsing and help-generation utilities.

The namespace exposes a bounded public surface centered on:

  • Command for spec definition and parsing
  • Matches for query access
  • CliError for stable failures

Records

record CliError

A parsing or validation error.

The current bounded parser uses a single message field so callers can show stable human-readable output without depending on backend diagnostics.

Members
message: String

Stable error text suitable for user-facing CLI messages.

clone(&self): CliError

Returns an owned copy of the error.

Example

let duplicate: Cli::CliError = error.clone();
record Command

Builder for bounded command-line parsers.

Command owns a declared option specification and can parse either an explicit argv vector or the current process argv.

Members
name: String

Canonical command name used for help rendering and argv fallback.

about: String

Optional one-line about text shown in help output.

specs: Vector<OptionSpec>

Declared flag and option specifications in stable insertion order.

static new(name: str): Command

Creates a new empty command specification.

Arguments

  • name: command/program name to display in help output.

Example

let command: Cli::Command = Cli::Command::new("tool");
aboutText(&mut self, about: str): void

Sets the one-line about text used by renderHelp().

Example

command.aboutText("Build project artifacts.");
appendSpecHelp(&self, help: &mut String, spec: &OptionSpec): void

Appends one formatted help line for a declared option spec.

The output format is intentionally compact and deterministic so tests and CLI callers can rely on stable rendering.

Example

command.appendSpecHelp(&mut help, spec);
findSpec(&self, name: &String): Option<&OptionSpec>

Finds the declared spec matching a long name or short alias.

Example

let spec: Option<&Cli::OptionSpec> = command.findSpec(&String::create("verbose"));
flag(&mut self, longName: str, shortName: str, help: str): void

Declares a boolean flag.

Arguments

  • longName: canonical long name without --
  • shortName: optional short alias without -
  • help: help text shown in deterministic help output

Example

command.flag("verbose", "v", "Enable verbose output.");
option(&mut self, longName: str, shortName: str, help: str): void

Declares an option that consumes the next argv item as its value.

Example

command.option("output", "o", "Write output file.");
parse(&self, args: &Vector<String>): Result<Matches, CliError>

Parses an explicit argv vector.

Arguments

  • args: argv-style vector where index 0 is the program name.

Supported behavior

  • long flags and valued options
  • short flags and valued options
  • ordered positionals
  • -- terminator

Unsupported behavior

  • grouped short flags
  • --opt=value
  • repeated-value aggregation helpers
  • default values and env fallbacks

Example

let mut args: Vector<String> = Vector::new<String>();
args.push(String::create("tool"));
args.push(String::create("--verbose"));
let result: Result<Cli::Matches, Cli::CliError> = command.parse(&args);
parseOption(&self, options: &mut Vector<OptionValue>, name: &String, token: &String, args: &Vector<String>, index: u64): Result<u64, CliError>

Parses one long or short option token and advances the argv index.

Arguments

  • options: output vector that accumulates parsed option occurrences
  • name: canonicalized token text without -/--
  • token: original raw token for stable error reporting
  • args: full argv vector
  • index: current token index within args

Returns

  • Result::OK(nextIndex) when parsing succeeds
  • Result::ERROR(CliError) when the option is undeclared or missing a required value

Example

let nextIndex: Result<u64, Cli::CliError> = command.parseOption(&mut options, &name, token, &args, 1);
parseProcess(&self): Result<Matches, CliError>

Parses the current process argv.

Returns

The same result shape as parse(&args), but using owned argv copies from Process::args().

Example

let result: Result<Cli::Matches, Cli::CliError> = command.parseProcess();
programName(&self, args: &Vector<String>): String

Resolves the program name from argv or falls back to the command name.

Example

let program: String = command.programName(&args);
renderHelp(&self): String

Renders deterministic help text from the command specification.

Output order

  1. usage line
  2. blank line + about text when present
  3. blank line + options section when at least one spec exists
  4. options in declaration order

Example

let help: String = command.renderHelp();
record Matches

Parsed command-line matches.

Matches stores owned data so callers can inspect results without borrowing from the original argv vector.

Members
program: String

Program name taken from argv[0] or the command name fallback.

options: Vector<OptionValue>

Parsed flag/option occurrences in arrival order.

positionals: Vector<String>

Parsed positional arguments after option handling.

find(&self, name: str): Option<&OptionValue>

Finds the first stored option occurrence by canonical long name.

This helper is private because the public API should expose semantic queries such as has() and value() instead of raw storage traversal.

Example

let entry: Option<&Cli::OptionValue> = matches.find("output");
has(&self, name: str): boolean

Returns true when the named flag or option was present.

Arguments

  • name: canonical long option name.

Example

let verboseEnabled: boolean = matches.has("verbose");
positional(&self, index: u64): Option<String>

Returns the positional argument at index.

Positionals remain ordered exactly as parsed, including tokens that appeared after --.

Example

let firstArg: Option<String> = matches.positional(0);
programName(&self): String

Returns an owned copy of the resolved program name.

Example

let name: String = matches.programName();
value(&self, name: str): Option<String>

Returns the first stored value for a named option.

Returns

  • Option::SOME(String) when the named option was present with a value
  • Option::NONE when the option is absent or is a boolean flag

Example

let output: Option<String> = matches.value("output");
record OptionSpec

Option definition used by Command.

This record describes one accepted long/short option pair.

Members
longName: String

Canonical long option name without the -- prefix.

shortName: String

Optional short alias without the - prefix.

help: String

Help text rendered in renderHelp().

takesValue: boolean

Whether the option consumes the next argv item as a value.

record OptionValue

One parsed option or flag occurrence.

OptionValue is an internal storage shape used by Matches. Boolean flags set hasValue = false and store an empty value string.

Members
name: String

Canonical long option name, even when parsed through a short alias.

value: String

Owned option payload when one was consumed.

hasValue: boolean

Whether this occurrence carries a value.

Functions

function cliStringAfterPrefix(value: &String, prefixLength: u64): String

Returns the substring after a known prefix length.

Arguments

  • value: source token.
  • prefixLength: number of leading bytes to skip.

Returns

A new owned String containing the suffix.

Example

let suffix: String = cliStringAfterPrefix(&String::create("--output"), 2);
// suffix == "output"
function cliStringEquals(value: &String, expected: str): boolean

Returns whether an owned string equals a str literal.

This is a private parser helper that keeps equality checks readable in the argv scan loop.

Example

let same: boolean = cliStringEquals(&String::create("--help"), "--help");
function cliStringStartsWith(value: &String, prefix: str): boolean

Returns whether value begins with prefix.

Notes

  • This check is byte-oriented.
  • It allocates a temporary owned String for the prefix comparison.

Example

let isLong: boolean = cliStringStartsWith(&String::create("--verbose"), "--");