A tiny operator‑typed CLI language for structured data.
TypedArgs is not an option parser.
It is a mini‑language for expressing structured data on the command line — scalars, arrays, hashes, and arrays of hashes — using a small set of explicit, shell‑safe operators.
It runs anywhere MRuby runs: embedded systems, containers, CI runners, Windows, macOS, Linux, BusyBox, Alpine, and fully sandboxed MRuby VMs. No dependencies. No shell tricks. No heuristics. No guessing.
TypedArgs behaves the same everywhere.
Most CLI parsers try to guess what the user meant. TypedArgs refuses.
Shells are inconsistent. Quoting rules differ. JSON on the command line is painful.
Suffix‑typed flags collide with shells. YAML is too heavy.
Users deserve a grammar that is:
- Explicit — the operator defines the shape
- Portable — works in every shell without quoting
- Deterministic — same input, same output, always
- Minimal — four operators, one mental model
- Structured — arrays and hashes are first‑class citizens
TypedArgs is the answer: a tiny algebra of flags.
TypedArgs is built on four operators.
They define the shape of the value — nothing else is needed.
| Operator | Meaning |
|---|---|
= |
scalar assignment |
+= |
append scalar to array |
:fields:= |
assign hash tuple |
+:fields:= |
append hash tuple to array |
This is the entire language.
No suffixes.
No brackets.
No type inference.
No shell‑sensitive characters.
Just operators.
TypedArgs is pure Ruby and MRuby‑core‑friendly.
Drop the Ruby files into your MRuby build or load them into your VM.
args = TypedArgs.opts("--mode=fast", "--debug=true")
args["mode"] # => "fast"
args["debug"] # => trueIf no arguments are passed, TypedArgs.opts defaults to ARGV.
You must supply that array yourself in MRuby; see tools/typedargs_test/test.c for an example.
TypedArgs defines a small, explicit grammar for keys and values.
Everything is driven by operators.
--mode=fast
--count=5
--debug=true
--foo=nil
Values may be:
- strings
- integers
- floats
- booleans (
true/false) nil
--db.user=root
--cache.redis.host=localhost
Keys may contain:
- letters
- digits
- underscore
- dash
- dot
Keys may not start with a digit or dash.
Dotted keys are treated as flat strings, not nested hashes.
--item+=a
--item+=b
Result:
{ "item" => ["a", "b"] }+= always appends.
If the key didn’t exist, an array is created.
--range:min,max:=5,10
Result:
{ "range" => { "min" => 5, "max" => 10 } }Arity is enforced:
If you declare two fields, you must supply two values.
--servers+:name,port:=alpha,80
--servers+:name,port:=beta,443
Result:
{
"servers" => [
{ "name" => "alpha", "port" => 80 },
{ "name" => "beta", "port" => 443 }
]
}+: always appends a hash to an array.
TypedArgs.alias("-v", "--verbose")
TypedArgs.opts("-v")
# => { "verbose" => true }Aliases expand before parsing.
They can target dotted keys and any operator form.
TypedArgs provides compiler‑style diagnostics with caret indicators.
Example:
--range:min,max:=5
^
Syntax error: Arity mismatch: expected 2, got 1
Every error includes:
- the original argument
- a caret pointing to the exact byte
- a clear error class
TypedArgs is self‑teaching.
TypedArgs applies flags in order.
Later flags overwrite earlier ones unless using accumulation operators.
| Syntax | Meaning |
|---|---|
--key=value |
assign scalar |
Overwrites previous value.
| Syntax | Meaning |
|---|---|
--key+=value |
append scalar to array |
Creates array if missing.
Overwrites previous non‑array values.
| Syntax | Meaning |
|---|---|
--key:field1,field2:=v1,v2 |
assign hash |
Overwrites previous value.
| Syntax | Meaning |
|---|---|
--key+:field1,field2:=v1,v2 |
append hash to array |
Creates array if missing.
| Sequence | Result |
|---|---|
--foo=1 → --foo+=2 |
[2] |
--foo+=1 → --foo+=2 |
[1,2] |
--foo:min,max:=1,2 → --foo:min,max:=3,4 |
{ "min"=>3,"max"=>4 } |
--foo+:min,max:=1,2 → --foo+:min,max:=3,4 |
[{"min"=>1,"max"=>2},{"min"=>3,"max"=>4}] |
--foo=1 → --foo+=2 → --foo:name:=alpha → --foo=bar |
"bar" |
TypedArgs is explicit:
the operator determines the shape.
TypedArgs ships with a full conformance suite covering:
- scalars
- arrays
- hashes
- arrays of hashes
- dotted keys
- alias expansion
- invalid characters
- invalid suffix placement
- invalid field lists
- tuple arity
- invalid numbers
- unterminated strings
- invalid short flags
- invalid dotted paths
- empty keys
- alias expansion to invalid keys
The suite is the specification.
If an implementation passes the suite, it is TypedArgs.
TypedArgs is intentionally:
- Explicit — no guessing
- Portable — no shell dependencies
- Minimal — four operators, one grammar
- Deterministic — predictable and stable
- Structured — arrays and hashes are first‑class
TypedArgs does not depend on:
- shell brace expansion
- shell quoting rules
- environment‑specific behavior
- Bash‑only features
The shell’s only job is to pass raw strings.
TypedArgs does everything else.
Apache‑2