admiral

Async-first declarative CLI builder for MoonBit, inspired by gunshi

cli
argparse
moonbit
moon add totto2727/admiral@0.6.4
Download zip
Author
Version
0.6.4
License
MIT
Last updated
6 days ago
Downloads
242
README

#admiral

Declarative CLI builder for MoonBit, inspired by gunshi.

This package is a fork of mizchi/admiral. It preserves the upstream MIT license and adds async-first native command execution and help fallback behavior.

A native-first wrapper around moonbitlang/core/argparse that provides:

  • Typed option helpers (string, bool, int, int64, uint, uint64, double, positional)
  • Optional configuration loading through independent config keys
  • Async run callbacks for commands and nested subcommands
  • TTY-gated interactive input callbacks with typed value overrides
  • Structured JSON schema output for AI agent integration
  • Shell completion generation (bash, zsh, fish)
  • Auto-generated --help / --version, including help for incomplete command paths

#Install

Add to moon.mod:

import {
"totto2727/admiral@0.6.1",
"moonbitlang/async@0.20.3",
}

preferred_target = "native"

Add to moon.pkg:

import {
"totto2727/admiral" @admiral,
"moonbitlang/async",
}

#Quick Start

async fn main {
let name = @admiral.string(
"name",
short='n',
description="Name to greet",
env="ADMIRAL_NAME",
config="name",
required=true,
)
let verbose = @admiral.bool("verbose", short='v', description="Verbose output")
let count = @admiral.int("count", short='c', description="Repeat count", default=Some(1))
let app = @admiral.cli(
name="myapp",
version="1.0.0",
description="My CLI tool",
commands=[
@admiral.command(
name="greet",
description="Greet someone",
options=[name, verbose, count],
examples=["myapp greet --name Alice", "myapp greet -n Bob -v -c 3"],
run=Some(async fn(ctx) {
let name_value = try { ctx.get_string_required(name) } catch { _ => return }
let is_verbose = ctx.get_bool(verbose)
let count_value = match ctx.get_int(count) { Some(n) => n; None => 1 }
for i = 0; i < count_value; i = i + 1 {
if is_verbose {
println("Hello, " + name_value + "! (" + (i + 1).to_string() + ")")
} else {
println("Hello, " + name_value + "!")
}
}
}),
),
],
)
app.run()
}

$ myapp greet --name Alice Hello, Alice! $ myapp greet -n Bob -v -c 3 Hello, Bob! (1) Hello, Bob! (2) Hello, Bob! (3) $ myapp --help Usage: myapp [command] My CLI tool Commands: greet Greet someone Options: -h, --help Show help information. -V, --version Show version information.

#Guide

#Defining Options

Options and positions use the same value types and Context getters:

// String option: --name value or -n value
@admiral.string("name", short='n', description="User name", env="MYAPP_NAME", config="name", required=true)

// Bool flag: --verbose or -v
@admiral.bool("verbose", short='v', description="Verbose output", env="MYAPP_VERBOSE", config="verbose")

// Int option: --port 8080 or -p 8080
@admiral.int("port", short='p', description="Port number", env="MYAPP_PORT", config="port", default=Some(3000))

// Scalar position: file
@admiral.position_string("file", description="Input file", config="input", required=true)

// Variadic position: file...
@admiral.position_strings("files", description="Input files")

short, env, and config are optional. Omit short to only allow the long form (--name); set env to read an environment variable and config to read a separately named configuration key.

#Environment Variables

string, bool, and int accept an optional env argument containing the environment variable name:

@admiral.string("name", env="MYAPP_NAME")
@admiral.bool("verbose", env="MYAPP_VERBOSE")
@admiral.int("port", env="MYAPP_PORT")

app.run() reads process arguments and the process environment by default. For tests or embedding, inject either source explicitly:

app.run(
argv=Some(["serve"]),
env={
"MYAPP_PORT": "8080",
"MYAPP_VERBOSE": "true",
},
)

// An empty map prevents ambient process variables from affecting the parse.
app.run(argv=Some(["serve"]), env=Map([]))

Values resolve in the order argv > env > default_values. Environment-backed boolean flags accept 1, 0, true, false, yes, no, on, and off. Precedence is defined by moonbitlang/core/argparse. Boolean literals are handled by its bool environment parser. The default process map comes from moonbitlang/core/env.

The generated schema contains only configured environment-variable names and config keys; it never resolves or embeds runtime values.

Each helper returns a typed, read-only definition such as OptionDef[String], OptionDef[Bool], or OptionDef[Int]. Pass the same definition to command or cli and to the matching Context getter; this makes the option name a single source of truth and causes mismatched getters to fail at compile time.

#Interactive Input

Set interactive=true on each option or position that participates in interactive input, then pass one async interactive callback to the owning command or root cli. Admiral invokes the callback only when at least one registered definition opts in and mizchi/tui reports that an input TTY is available. On native platforms, mizchi/tui treats either TTY-backed standard input or an available controlling terminal (/dev/tty or CONIN$) as interactive. When no input TTY is available, Admiral skips the callback and preserves ordinary parsing and required-value validation.

let project = @admiral.position_string(
"project",
required=true,
interactive=true,
)
let query = @admiral.string(
"query",
env="ADMIRAL_PROJECT_QUERY",
default=Some(""),
interactive=true,
)

let app = @admiral.cli(
name="project-search",
positionals=[project],
options=[query],
interactive=Some(input => {
let initial = input.to_context()
let selected = run_project_search_tui(
initial.get_string(project),
initial.get_string(query).unwrap_or(""),
)
input.set_string(project, selected)
}),
run=Some(ctx => println(ctx.get_string_required(project))),
)

InteractiveContext::to_context() resolves initial values through the same argv > env > config > default rules as the final command callback. The typed set_bool, set_string, set_strings, numeric scalar, and numeric array methods replace selected values before run executes. Required interactive definitions are deferred until the callback only in an interactive environment, so a search selector can supply an otherwise missing required value.

The callback owns the entire interaction rather than a single component. It can perform asynchronous discovery, maintain search state, run multiple screens, or mount a complete mizchi/tui event loop. See src/examples/interactive for a native searchable project selector based on the official mizchi/tui virtual DOM, keyboard input, and terminal APIs.

#Configuration

Pass an optional argument-less load_config callback to cli. The callback can read any configuration format, but must return a Map[String, Json] whose keys match the independent config names declared on options or positions:

fn load_config() -> Map[String, Json] raise @admiral.ConfigLoadFailure {
{
"port": (7000).to_json(),
"verbose": (true).to_json(),
"tags": ["release", "signed"].to_json(),
}
}

let app = @admiral.cli(
name="myapp",
load_config=Some(load_config),
commands=[...],
)

CliApp::run passes only the real environment map to core/argparse and stores the loaded configuration map separately in each command Context. Each Context getter inspects the parser's ValueSource. Each getter first decides whether config should be used. An Argv or Env source skips config and continues with the existing value parsing; a Default or absent source first checks the definition's config key and decodes an available JSON value with FromJson, then falls back to parsing the declared default or missing-value behavior only when that config key is unavailable.

Values resolve in the order argv > env > config > default. Option names, environment-variable names, and config keys are independent. Config values are available to options and positions that declare config. When a loaded config key satisfies a required argument, admiral relaxes the corresponding parser requirement; when it is absent, ordinary core/argparse required validation remains active.

Environment values remain scalar strings and continue to use core/argparse parsing. Config values are decoded by the matching MoonBit FromJson implementation inside each getter. Plural definitions such as strings and ints require a JSON array and preserve its elements. An active config value that cannot be decoded raises JsonDecodeError instead of falling back to a declared default; scalar getters use None for an unavailable value, while plural getters return an empty array. Numeric parsing failures from argv, environment variables, or declared defaults also propagate as errors instead of returning None. Required plural getters return NonEmptyArray[T], exposing first: T, rest: ArrayView[T], and all: ReadOnlyArray[T]; they raise when the resolved array is empty. Return Map([]) when no configuration values are available.

ConfigLoadFailure is the typed error for the callback. For example, a loader can report raise @admiral.ConfigLoadFailure("config file is unreadable").

CliApp is a public record. Direct struct-literal callers must include interactive and load_config in CliApp; direct CommandDef literals must include interactive; and direct Context literals must include sources, config, interactive_flags, and interactive_values. Calls through cli, command, and Context::Context remain source-compatible because the new inputs are optional or initialized internally.

#Reading Values from Context

Inside an async run callback, use Context methods to read parsed values:

let verbose = @admiral.bool("verbose")
let name = @admiral.string("name", required=true)
let port = @admiral.int("port", required=true)
let input = @admiral.position_int("input", required=true)

// Register definitions with command(options=[verbose, name, port], positionals=[input]).
run=Some(async fn(ctx) {
// Bool — returns false if not specified
let is_verbose = ctx.get_bool(verbose)

// String — returns None if not specified
let name_value = ctx.get_string(name) // String?

// String (required) — raises if missing
let name_value = try { ctx.get_string_required(name) } catch { _ => return }

// Int — parses string value to Int, returns None if missing or invalid
let port_value = ctx.get_int(port) // Int?

// Int (required) — raises if missing or not a valid integer
let port_value = try { ctx.get_int_required(port) } catch { _ => return }

// The same getter accepts PositionDef[Int]
let input_value = try { ctx.get_int_required(input) } catch { _ => return }
})

#Nested Subcommands

Commands can nest arbitrarily deep:

let dry_run = @admiral.bool("dry-run", description="Preview without applying")
let up_steps = @admiral.int("steps", short='s', description="Number of steps")
let down_steps = @admiral.int("steps", short='s', description="Steps to rollback", default=Some(1))
let seed_file = @admiral.string("file", short='f', description="Seed file", default=Some("seeds/default.sql"))

let app = @admiral.cli(
name="myapp",
commands=[
@admiral.command(
name="db",
description="Database commands",
subcommands=[
@admiral.command(
name="migrate",
description="Run migrations",
subcommands=[
@admiral.command(
name="up",
description="Apply pending migrations",
options=[dry_run, up_steps],
examples=[
"myapp db migrate up",
"myapp db migrate up --dry-run",
"myapp db migrate up --steps 5",
],
run=Some(async fn(ctx) {
if ctx.get_bool(dry_run) {
println("[DRY RUN] Would apply migrations")
} else {
match ctx.get_int(up_steps) {
Some(n) => println("Applying " + n.to_string() + " migrations...")
None => println("Applying all pending migrations...")
}
}
}),
),
@admiral.command(
name="down",
description="Rollback migrations",
options=[down_steps],
run=Some(async fn(ctx) {
let steps = match ctx.get_int(down_steps) { Some(n) => n; None => 1 }
println("Rolling back " + steps.to_string() + " migration(s)...")
}),
),
],
),
@admiral.command(
name="seed",
description="Seed the database",
options=[seed_file],
run=Some(async fn(ctx) {
let file = match ctx.get_string(seed_file) { Some(f) => f; None => "seeds/default.sql" }
println("Seeding from: " + file)
}),
),
],
),
],
)

$ myapp db migrate up --dry-run [DRY RUN] Would apply migrations $ myapp db migrate down --steps 3 Rolling back 3 migration(s)... $ myapp db seed --file custom.sql Seeding from: custom.sql

#Positional Arguments

let files = @admiral.position_strings("files", description="Files to concatenate")

@admiral.command(
name="cat",
description="Concatenate files",
positionals=[files],
run=Some(async fn(ctx) {
let file_values = ctx.get_strings(files)
for file in file_values {
println("Reading: " + file)
}
}),
)

$ myapp cat a.txt b.txt c.txt Reading: a.txt Reading: b.txt Reading: c.txt

#Testing with Explicit argv

// In async tests, pass argv explicitly:
async test {
app.run(argv=Some(["greet", "--name", "alice"]))
}

// In production, omit argv to use process args:
app.run()

#Structured Schema Output

admiral can output the full CLI definition as JSON — useful for AI agents, documentation generators, and tooling:

println(app.render_schema()) // -> JSON string
let json = ToJson::to_json(app) // -> Json value

Example output:

{ "name": "myapp", "version": "1.0.0", "description": "My CLI tool", "commands": { "greet": { "description": "Greet someone", "options": { "name": { "type": "string", "description": "Name to greet", "required": true, "short": "n", "env": "ADMIRAL_NAME" }, "verbose": { "type": "bool", "description": "Verbose output", "required": false, "short": "v" }, "count": { "type": "int", "description": "Repeat count", "required": false, "short": "c", "default": "1" } }, "examples": ["myapp greet --name Alice", "myapp greet -n Bob -v -c 3"] }, "db": { "description": "Database commands", "commands": { "migrate": { "description": "Run migrations", "commands": { "up": { "description": "Apply pending migrations", "options": { "dry-run": { "type": "bool", "description": "Preview without applying", "required": false }, "steps": { "type": "int", "description": "Number of steps", "required": false, "short": "s" } }, "examples": ["myapp db migrate up", "myapp db migrate up --dry-run"] } } } } } } }

This enables AI agents to understand CLI interfaces without parsing --help text — types, required/optional, defaults, and examples are all machine-readable.

#Shell Completion

Generate completion scripts for bash, zsh, and fish:

// Bash
println(app.render_bash_completion())

// Zsh
println(app.render_zsh_completion())

// Fish
println(app.render_fish_completion())

Typical usage — add a completion subcommand:

let shell = @admiral.string(
"shell",
short='s',
description="Shell type (bash, zsh, fish)",
required=true,
)

@admiral.command(
name="completion",
description="Generate shell completion script",
options=[shell],
run=Some(async fn(ctx) {
match ctx.get_string(shell) {
Some("bash") => println(app.render_bash_completion())
Some("zsh") => println(app.render_zsh_completion())
Some("fish") => println(app.render_fish_completion())
_ => println("Unsupported shell. Use: bash, zsh, fish")
}
}),
)

# Bash: add to ~/.bashrc eval "$(myapp completion --shell bash)" # Zsh: add to ~/.zshrc eval "$(myapp completion --shell zsh)" # Fish: save to completions dir myapp completion --shell fish > ~/.config/fish/completions/myapp.fish

#API Reference

#Option Helpers

FunctionDescription
string(name, short?, description?, env?, config?, required?, default?)String option (--name value)
strings(name, short?, description?, env?, config?, required?)Repeated string option
bool(name, short?, description?, env?, config?)Boolean flag (--verbose)
int(name, short?, description?, env?, config?, required?, default?)Integer option (--port 8080)
ints(name, short?, description?, env?, config?, required?)Repeated integer option
int64(name, short?, description?, env?, config?, required?, default?)64-bit signed integer option
int64s(name, short?, description?, env?, config?, required?)Repeated 64-bit signed integer option
uint(name, short?, description?, env?, config?, required?, default?)Unsigned integer option
uints(name, short?, description?, env?, config?, required?)Repeated unsigned integer option
uint64(name, short?, description?, env?, config?, required?, default?)64-bit unsigned integer option
uint64s(name, short?, description?, env?, config?, required?)Repeated 64-bit unsigned integer option
double(name, short?, description?, env?, config?, required?, default?)Double-precision floating-point option
doubles(name, short?, description?, env?, config?, required?)Repeated double-precision floating-point option

#Position Helpers

FunctionResult type
position_string(name, description?, config?, required?)PositionDef[String]
position_strings(name, description?, config?, required?)PositionDef[Array[String]]
position_int(name, description?, config?, required?)PositionDef[Int]
position_ints(name, description?, config?, required?)PositionDef[Array[Int]]
position_int64 / position_int64sPositionDef[Int64] / PositionDef[Array[Int64]]
position_uint / position_uintsPositionDef[UInt] / PositionDef[Array[UInt]]
position_uint64 / position_uint64sPositionDef[UInt64] / PositionDef[Array[UInt64]]
position_double / position_doublesPositionDef[Double] / PositionDef[Array[Double]]

#Command Definition

FunctionDescription
command(name, description?, options?, positionals?, examples?, subcommands?, run?)Define a command or subcommand with an async run callback
cli(name, version?, description?, options?, commands?, load_config?)Create a CLI app with global options

#Context Methods

MethodReturnDescription
get_bool(OptionDef[Bool])BoolFlag value (default: false)
get_string(ArgDef[String, M])String?First string value from an option or position
get_string_required(ArgDef[String, M])String raiseRequired string value
get_int(ArgDef[Int, M])Int?Parsed integer value from an option or position
get_int_required(ArgDef[Int, M])Int raiseRequired parsed integer value
get_int64 / get_int64_requiredInt64? / Int64 raise64-bit signed integer value
get_uint / get_uint_requiredUInt? / UInt raiseUnsigned integer value
get_uint64 / get_uint64_requiredUInt64? / UInt64 raise64-bit unsigned integer value
get_double / get_double_requiredDouble? / Double raiseDouble-precision floating-point value
get_strings(ArgDef[Array[String], M])Array[String]Repeated string values, empty when unavailable
get_ints(ArgDef[Array[Int], M])Array[Int] raiseRepeated parsed integer values
get_int64s / get_uints / get_uint64s / get_doublescorresponding Array[T] raiseRepeated parsed numeric values
plural getter with _required suffixNonEmptyArray[T] raiseRequired non-empty repeated values
get_subcommand()(String, Context)?Selected subcommand name and context

#Schema & Completion

MethodReturnDescription
render_schema()StringFull CLI definition as JSON string
ToJson::to_json(app)JsonFull CLI definition as Json value
render_bash_completion()StringBash completion script
render_zsh_completion()StringZsh completion script
render_fish_completion()StringFish completion script

#Running

app.run() // use process args
app.run(argv=Some(["greet", "--name", "x"])) // explicit args (for testing)
app.run(env={ "ADMIRAL_NAME": "Env" }) // explicit environment map
app.run(
argv=Some(["greet"]),
env={ "ADMIRAL_NAME": "Env" },
)

CliApp::run(argv?, env?) is async. Omitted argv uses process arguments, and omitted env uses the process environment. Call it from async fn main or async test; no task-group wrapper is required. --help and --version are automatically handled by argparse. Invoking the app without a runnable command, or a command group without its required subcommand, displays the corresponding help. Unknown commands, invalid options, and errors raised by command callbacks remain errors.

#Targets

Admiral supports the native target. This follows the current support level of the official moonbitlang/async runtime.

#License

MIT. See LICENSE.

The upstream project declares its original license as MIT in mizchi/admiral's module manifest.

#
OptionDef

type OptionDef[T] = ArgDef[T, OptionMetadata]

#
PositionDef

type PositionDef[T] = ArgDef[T, PositionMetadata]

#
ToStoredOption

trait ToStoredOption

#
ToStoredPosition

trait ToStoredPosition

#
ConfigLoadFailure

pub(all) suberror ConfigLoadFailure {
ConfigLoadFailure(String)
} derive(Eq,
Debug
)

#
ArgDef

pub struct ArgDef[_, Metadata] {
name : String
config : String?
metadata : Metadata
} derive(
Debug
)

#
CliApp

pub(all) struct CliApp {
name : String
version : String
description : String
root_options : Array[ArgDef[Unit, OptionMetadata]]
root_positionals : Array[ArgDef[Unit, PositionMetadata]]
commands : Array[CommandDef]
interactive : async (InteractiveContext) -> Unit?
run : async (Context) -> Unit?
load_config : () -> Map[String, Json] raise ConfigLoadFailure?
}

impl ToJson for CliApp

#
CliApp::render_bash_completion

fn CliApp::render_bash_completion(self : CliApp) -> String

#
CliApp::render_fish_completion

fn CliApp::render_fish_completion(self : CliApp) -> String

#
CliApp::render_schema

fn CliApp::render_schema(self : CliApp) -> String

#
CliApp::render_zsh_completion

fn CliApp::render_zsh_completion(self : CliApp) -> String

#
CliApp::run

async fn CliApp::run(self : CliApp, argv? : Array[String]?, env? : Map[String, String]) -> Unit

Parses inputs and runs the selected callback, invoking interactive input only when at least one selected definition opts in and an input TTY is available.

#
CommandDef

pub(all) struct CommandDef {
name : String
description : String
options : Array[ArgDef[Unit, OptionMetadata]]
positionals : Array[ArgDef[Unit, PositionMetadata]]
examples : Array[String]
subcommands : Array[CommandDef]
interactive : async (InteractiveContext) -> Unit?
run : async (Context) -> Unit?
}

#
Context

pub(all) struct Context {
flags :
HashMap
[String, Bool]
values :
HashMap
[String, ReadOnlyArray[String]]
sources :
HashMap
[String,
ValueSource
]
config :
HashMap
[String, Json]
interactive_flags :
HashMap
[String, Bool]
interactive_values :
HashMap
[String, ReadOnlyArray[String]]
subcommand : (String, Context)?
}

#
Context::Context

fn Context::Context(flags? : Map[String, Bool], values? : Map[String, Array[String]], sources? : Map[String,
ValueSource
], config? : Map[String, Json], subcommand? : (String, Context)?) -> Context

#
Context::get_bool

Boolean options are flags stored separately from positional values. Their absence means false, so this getter intentionally accepts only OptionDef.

#
Context::get_double

fn[Metadata] Context::get_double(self : Context, argument : ArgDef[Double, Metadata]) -> Double? raise

#
Context::get_double_required

fn[Metadata] Context::get_double_required(self : Context, argument : ArgDef[Double, Metadata]) -> Double raise

#
Context::get_doubles

fn[Metadata] Context::get_doubles(self : Context, argument : ArgDef[Array[Double], Metadata]) -> ReadOnlyArray[Double] raise

#
Context::get_doubles_required

fn[Metadata] Context::get_doubles_required(self : Context, argument : ArgDef[Array[Double], Metadata]) -> NonEmptyArray[Double] raise

#
Context::get_int

fn[Metadata] Context::get_int(self : Context, argument : ArgDef[Int, Metadata]) -> Int? raise

#
Context::get_int64

fn[Metadata] Context::get_int64(self : Context, argument : ArgDef[Int64, Metadata]) -> Int64? raise

#
Context::get_int64_required

fn[Metadata] Context::get_int64_required(self : Context, argument : ArgDef[Int64, Metadata]) -> Int64 raise

#
Context::get_int64s

fn[Metadata] Context::get_int64s(self : Context, argument : ArgDef[Array[Int64], Metadata]) -> ReadOnlyArray[Int64] raise

#
Context::get_int64s_required

fn[Metadata] Context::get_int64s_required(self : Context, argument : ArgDef[Array[Int64], Metadata]) -> NonEmptyArray[Int64] raise

#
Context::get_int_required

fn[Metadata] Context::get_int_required(self : Context, argument : ArgDef[Int, Metadata]) -> Int raise

#
Context::get_ints

fn[Metadata] Context::get_ints(self : Context, argument : ArgDef[Array[Int], Metadata]) -> ReadOnlyArray[Int] raise

#
Context::get_ints_required

fn[Metadata] Context::get_ints_required(self : Context, argument : ArgDef[Array[Int], Metadata]) -> NonEmptyArray[Int] raise

#
Context::get_string

fn[Metadata] Context::get_string(self : Context, argument : ArgDef[String, Metadata]) -> String? raise
JsonDecodeError

#
Context::get_string_required

fn[Metadata] Context::get_string_required(self : Context, argument : ArgDef[String, Metadata]) -> String raise

#
Context::get_strings

fn[Metadata] Context::get_strings(self : Context, argument : ArgDef[Array[String], Metadata]) -> ReadOnlyArray[String] raise
JsonDecodeError

#
Context::get_strings_required

fn[Metadata] Context::get_strings_required(self : Context, argument : ArgDef[Array[String], Metadata]) -> NonEmptyArray[String] raise

#
Context::get_subcommand

fn Context::get_subcommand(self : Context) -> (String, Context)?

#
Context::get_uint

fn[Metadata] Context::get_uint(self : Context, argument : ArgDef[UInt, Metadata]) -> UInt? raise

#
Context::get_uint64

fn[Metadata] Context::get_uint64(self : Context, argument : ArgDef[UInt64, Metadata]) -> UInt64? raise

#
Context::get_uint64_required

fn[Metadata] Context::get_uint64_required(self : Context, argument : ArgDef[UInt64, Metadata]) -> UInt64 raise

#
Context::get_uint64s

fn[Metadata] Context::get_uint64s(self : Context, argument : ArgDef[Array[UInt64], Metadata]) -> ReadOnlyArray[UInt64] raise

#
Context::get_uint64s_required

fn[Metadata] Context::get_uint64s_required(self : Context, argument : ArgDef[Array[UInt64], Metadata]) -> NonEmptyArray[UInt64] raise

#
Context::get_uint_required

fn[Metadata] Context::get_uint_required(self : Context, argument : ArgDef[UInt, Metadata]) -> UInt raise

#
Context::get_uints

fn[Metadata] Context::get_uints(self : Context, argument : ArgDef[Array[UInt], Metadata]) -> ReadOnlyArray[UInt] raise

#
Context::get_uints_required

fn[Metadata] Context::get_uints_required(self : Context, argument : ArgDef[Array[UInt], Metadata]) -> NonEmptyArray[UInt] raise

#
InteractiveContext

pub struct InteractiveContext {
initial : Context
flags : Map[String, Bool]
values : Map[String, Array[String]]
}

Accumulates values selected by a command's interactive input callback. Read to_context() before setting values to obtain the resolved argv, environment, configuration, positional, and default values as initial input.

#
InteractiveContext::set_bool

fn InteractiveContext::set_bool(self : InteractiveContext, option : ArgDef[Bool, OptionMetadata], value : Bool) -> Unit

Replaces a boolean option with a value selected interactively.

#
InteractiveContext::set_double

fn[Metadata] InteractiveContext::set_double(self : InteractiveContext, argument : ArgDef[Double, Metadata], value : Double) -> Unit

Replaces a floating-point input with a value selected interactively.

#
InteractiveContext::set_doubles

fn[Metadata] InteractiveContext::set_doubles(self : InteractiveContext, argument : ArgDef[Array[Double], Metadata], values : Array[Double]) -> Unit

Replaces repeated floating-point input with values selected interactively.

#
InteractiveContext::set_int

fn[Metadata] InteractiveContext::set_int(self : InteractiveContext, argument : ArgDef[Int, Metadata], value : Int) -> Unit

Replaces an integer option or positional with a value selected interactively.

#
InteractiveContext::set_int64

fn[Metadata] InteractiveContext::set_int64(self : InteractiveContext, argument : ArgDef[Int64, Metadata], value : Int64) -> Unit

Replaces a 64-bit integer input with a value selected interactively.

#
InteractiveContext::set_int64s

fn[Metadata] InteractiveContext::set_int64s(self : InteractiveContext, argument : ArgDef[Array[Int64], Metadata], values : Array[Int64]) -> Unit

Replaces repeated 64-bit integer input with values selected interactively.

#
InteractiveContext::set_ints

fn[Metadata] InteractiveContext::set_ints(self : InteractiveContext, argument : ArgDef[Array[Int], Metadata], values : Array[Int]) -> Unit

Replaces repeated integer input with values selected interactively.

#
InteractiveContext::set_string

fn[Metadata] InteractiveContext::set_string(self : InteractiveContext, argument : ArgDef[String, Metadata], value : String) -> Unit

Replaces a string option or positional with a value selected interactively.

#
InteractiveContext::set_strings

fn[Metadata] InteractiveContext::set_strings(self : InteractiveContext, argument : ArgDef[Array[String], Metadata], values : Array[String]) -> Unit

Replaces a repeated string option or positional with values selected interactively.

#
InteractiveContext::set_uint

fn[Metadata] InteractiveContext::set_uint(self : InteractiveContext, argument : ArgDef[UInt, Metadata], value : UInt) -> Unit

Replaces an unsigned integer input with a value selected interactively.

#
InteractiveContext::set_uint64

fn[Metadata] InteractiveContext::set_uint64(self : InteractiveContext, argument : ArgDef[UInt64, Metadata], value : UInt64) -> Unit

Replaces a 64-bit unsigned integer input with a value selected interactively.

#
InteractiveContext::set_uint64s

fn[Metadata] InteractiveContext::set_uint64s(self : InteractiveContext, argument : ArgDef[Array[UInt64], Metadata], values : Array[UInt64]) -> Unit

Replaces repeated 64-bit unsigned integer input with values selected interactively.

#
InteractiveContext::set_uints

fn[Metadata] InteractiveContext::set_uints(self : InteractiveContext, argument : ArgDef[Array[UInt], Metadata], values : Array[UInt]) -> Unit

Replaces repeated unsigned integer input with values selected interactively.

#
InteractiveContext::to_context

Returns the current context, including values already selected by this callback.

#
NonEmptyArray

pub struct NonEmptyArray[T] {
first : T
rest : ArrayView[T]
all : ReadOnlyArray[T]
} derive(
Debug
)

#
OptionMetadata

pub struct OptionMetadata {
type_ : OptionType
short : Char
description : String
env : String?
required : Bool
default_value : String?
multiple : Bool
interactive : Bool
} derive(
Debug
)

#
OptionType

pub(all) enum OptionType {
StringOpt
BoolOpt
IntOpt
Int64Opt
UIntOpt
UInt64Opt
DoubleOpt
} derive(Eq,
Debug
)

impl Show for OptionType

#
PositionMetadata

pub struct PositionMetadata {
type_ : OptionType
description : String
required : Bool
multiple : Bool
interactive : Bool
} derive(
Debug
)

#
bool

fn bool(name : String, short? : Char, description? : String, env? : String, config? : String, interactive? : Bool) -> ArgDef[Bool, OptionMetadata]

#
build_command

#
cli

fn cli(name~ : String, version? : String, description? : String, options? : Array[&ToStoredOption], positionals? : Array[&ToStoredPosition], commands? : Array[CommandDef], interactive? : async (InteractiveContext) -> Unit?, run? : async (Context) -> Unit?, load_config? : () -> Map[String, Json] raise ConfigLoadFailure?) -> CliApp

#
command

fn command(name~ : String, description? : String, options? : Array[&ToStoredOption], positionals? : Array[&ToStoredPosition], examples? : Array[String], subcommands? : Array[CommandDef], interactive? : async (InteractiveContext) -> Unit?, run? : async (Context) -> Unit?) -> CommandDef

#
double

fn double(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Double?, interactive? : Bool) -> ArgDef[Double, OptionMetadata]

#
doubles

fn doubles(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Double], OptionMetadata]

#
int

fn int(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Int?, interactive? : Bool) -> ArgDef[Int, OptionMetadata]

#
int64

fn int64(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Int64?, interactive? : Bool) -> ArgDef[Int64, OptionMetadata]

#
int64s

fn int64s(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int64], OptionMetadata]

#
ints

fn ints(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int], OptionMetadata]

#
position_double

fn position_double(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Double, PositionMetadata]

#
position_doubles

fn position_doubles(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Double], PositionMetadata]

#
position_int

fn position_int(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Int, PositionMetadata]

#
position_int64

fn position_int64(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Int64, PositionMetadata]

#
position_int64s

fn position_int64s(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int64], PositionMetadata]

#
position_ints

fn position_ints(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int], PositionMetadata]

#
position_string

fn position_string(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[String, PositionMetadata]

#
position_strings

fn position_strings(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[String], PositionMetadata]

#
position_uint

fn position_uint(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[UInt, PositionMetadata]

#
position_uint64

fn position_uint64(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[UInt64, PositionMetadata]

#
position_uint64s

fn position_uint64s(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt64], PositionMetadata]

#
position_uints

fn position_uints(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt], PositionMetadata]

#
string

fn string(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : String?, interactive? : Bool) -> ArgDef[String, OptionMetadata]

#
strings

fn strings(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[String], OptionMetadata]

#
uint

fn uint(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : UInt?, interactive? : Bool) -> ArgDef[UInt, OptionMetadata]

#
uint64

fn uint64(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : UInt64?, interactive? : Bool) -> ArgDef[UInt64, OptionMetadata]

#
uint64s

fn uint64s(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt64], OptionMetadata]

#
uints

fn uints(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt], OptionMetadata]