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 ownedStringvalues viaProcess::args().parse(&args)clones only the values it needs to store inMatches.Matches::value()andMatches::positional()return ownedStringclones 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 CliCLI parsing and help-generation utilities.
The namespace exposes a bounded public surface centered on:
Commandfor spec definition and parsingMatchesfor query accessCliErrorfor stable failures
Records
record CliErrorA 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.
message: StringStable error text suitable for user-facing CLI messages.
clone(&self): CliErrorReturns an owned copy of the error.
Example
let duplicate: Cli::CliError = error.clone();
record CommandBuilder for bounded command-line parsers.
Command owns a declared option specification and can parse either an
explicit argv vector or the current process argv.
name: StringCanonical command name used for help rendering and argv fallback.
about: StringOptional one-line about text shown in help output.
specs: Vector<OptionSpec>Declared flag and option specifications in stable insertion order.
static new(name: str): CommandCreates 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): voidSets the one-line about text used by renderHelp().
Example
command.aboutText("Build project artifacts.");
appendSpecHelp(&self, help: &mut String, spec: &OptionSpec): voidAppends 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): voidDeclares 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): voidDeclares 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 index0is 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 occurrencesname: canonicalized token text without-/--token: original raw token for stable error reportingargs: full argv vectorindex: current token index withinargs
Returns
Result::OK(nextIndex)when parsing succeedsResult::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>): StringResolves the program name from argv or falls back to the command name.
Example
let program: String = command.programName(&args);
renderHelp(&self): StringRenders deterministic help text from the command specification.
Output order
- usage line
- blank line + about text when present
- blank line + options section when at least one spec exists
- options in declaration order
Example
let help: String = command.renderHelp();
record MatchesParsed command-line matches.
Matches stores owned data so callers can inspect results without
borrowing from the original argv vector.
program: StringProgram 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): booleanReturns 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): StringReturns 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 valueOption::NONEwhen the option is absent or is a boolean flag
Example
let output: Option<String> = matches.value("output");
record OptionSpecOption definition used by Command.
This record describes one accepted long/short option pair.
longName: StringCanonical long option name without the -- prefix.
shortName: StringOptional short alias without the - prefix.
help: StringHelp text rendered in renderHelp().
takesValue: booleanWhether the option consumes the next argv item as a value.
record OptionValueOne 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.
name: StringCanonical long option name, even when parsed through a short alias.
value: StringOwned option payload when one was consumed.
hasValue: booleanWhether this occurrence carries a value.
Functions
function cliStringAfterPrefix(value: &String, prefixLength: u64): StringReturns 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): booleanReturns 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): booleanReturns whether value begins with prefix.
Notes
- This check is byte-oriented.
- It allocates a temporary owned
Stringfor the prefix comparison.
Example
let isLong: boolean = cliStringStartsWith(&String::create("--verbose"), "--");