diff --git a/design/mvp/CLIEmbedding.md b/design/mvp/CLIEmbedding.md new file mode 100644 index 00000000..0f55c831 --- /dev/null +++ b/design/mvp/CLIEmbedding.md @@ -0,0 +1,115 @@ +# Typed Main + +A high-level goal of the component model is the ability to run a single component portably on various hosts. One such embedding is a classic Unix-style Command-Line Interface (CLI) accepting positional/named arguments. + +This document describes how a component can be generically interpreted by a component-enabled CLI to allow components to be directly instantiated and invoked from the command line in an idiomatic manner, corresponding to use case #2 of [invoking component exports](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md#invoking-component-exports-from-the-host). It also defines annotations which can be used to extend the default interpretation of a component to specify CLI-specific features (e.g. short flag names). + +The component type is specified here in terms of a [`*.wit`](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md) interface and annotations as [Structured Annotations](https://github.com/WebAssembly/component-model/issues/58). + +## Arguments +* Value imports are can be supplied as positional arguments in the order they are defined +* Value imports can be supplied as long-form named arguments with their defined name +* The ordering of named arguments with respect to each other and positional arguments is not constrained +* If a named argument is present, parsing of positional argument skips over it to the next position + +```rust +input: string +pattern: string +replace: string +``` + +### Usage +``` +$ replace "some-thing" "-" "_" +$ replace --input "some-thing" --pattern "-" --replace "_" +$ replace --pattern "-" --replace "_" "some-thing" +``` + +## File Preopen Arguments +* If the type of a value import is a WASI file, the host reads the corresponding argument as a path and preopens it. +* The preopen must occur even for file paths which do not exist (as long as their parent does), so that output file paths can be supported. + +```rust +import { file } from ... + +input: file +output: file +``` + +### Usage +```bash +$ copy ./input.txt --output ./output.txt +``` + +## Optional Arguments +* Value imports with type `option` are optional arguments +* If an optional argument is not provided, the value import takes value `none` +* All arguments defined after an optional argument must be optional + +```rust +import { file } from ... + +input: file +output: option +``` + +### Usage +```bash +$ foo ./input.txt ./output.txt +$ foo ./input.txt +``` + +## Flags +* Value imports with type `bool` inferred to be flags. +* Flags have value `true` if present and `false` if absent. +* By default, flags are "long" + * Equivalent to annotation `@flag(long)` + * Specified in long form with no associated value e.g. `--foobar` + * Name is inferred to be the value import name + * Name can be explicitly set `@flag(long = "foobar")` + * Does not support grouping +* Flags can annotated as "short" + * Using annotation `@flag(short)` + * Specified in short form with no associated value e.g.`-f` + * Name is inferred to be first character of value import name + * Name can be explicitly set `@flag(short = "f")` + * Supports grouping `-a -b -c` = `-abc` +* Flag can be short and long `@flag(short, long)`, value `true` if either are present + +```rust +@flag(short) +help: bool + +verbose: bool + +@flag(short = "x", long) +execute: bool +``` + +### Usage +```bash +$ foo -h +$ foo --verbose +$ foo -x +$ foo --execute -x --verbose +``` + +## Short Named Arguments +* By default named arguments are "long" (inferred as `@arg(pos, named, long)`). +* By annotating them with with the `short` parameter, they can be used in short form e.g. `-i` +* Name inference and manual assignment works the same as flags + +```rust +import { file } from ... + +input: file + +@arg(named, short, long) +output: option +``` + +### Usage +```bash +$ foo ./input.txt --output ./output.txt +$ foo ./input.txt -o ./output.txt +```