diff --git a/README.md b/README.md index f9eb2e2..f2f9611 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ language features. - Full-featured [libraries/modules](docs/libraries.md) - [Full UTF8 support](docs/text.md) for all text operations - Built-in doctests with syntax highlighting -- Automatic command line argument parsing with type safety +- [Automatic command line argument parsing with type safety](docs/command-line-parsing.md) - Easy interoperability with C ## Dependencies diff --git a/docs/command-line-parsing.md b/docs/command-line-parsing.md new file mode 100644 index 0000000..5d8af9d --- /dev/null +++ b/docs/command-line-parsing.md @@ -0,0 +1,123 @@ +# Command Line Parsing + +Tomo supports automatic command line argument parsing for programs. +Here's a simple example: + +```tomo +# greet.tm +func main(name:Text, be_excited=no): + if be_excited + say("Hello $name!!!") + else: + say("Hi $name.") +``` + +This program will automatically support command line argument parsing +for the arguments to `main()`: + +```bash +$ tomo greet.tm +greet: Required argument 'name' was not provided! +Usage: greet [--help] [--be-excited] + +$ tomo greet.tm --help +Usage: greet [--help] [--be-excited] + +$ tomo greet.tm "Zaphod" +Hi Zaphod. + +$ tomo greet.tm "Zaphod" --be-excited +Hello Zaphod!!! + +$ tomo greet.tm --no-be-excited --name="Zaphod" +Hi Zaphod. + +$ tomo greet.tm --not-a-real-argument "Bob" +greet: Unrecognized argument: --not-a-real-argument +Usage: greet [--help] [--be-excited] +``` + +Underscores in argument names are converted to dashes when parsing command line +arguments. + +## Positional vs Default Arguments + +Any arguments with a default value must be specified with a `--flag=value` or +`--flag value`. Arguments without a default value can be specified either by +explicit `--flag` or positionally. If an argument does not have a default value +it is required and the program will report a usage error if it is missing. + +## Supported Argument Types + +Tomo automatically supports several argument types out of the box, but if there +is a type that isn't supported, you can always fall back to accepting a `Text` +argument and parsing it yourself. + +### Text + +Text arguments are the simplest: the input arguments are taken verbatim. + +### Bool + +For a boolean argument, `foo`, the argument can be passed in several ways: + +- `--foo` or `--no-foo` provide the argument as `yes`/`no` respectively +- `--foo=yes`/`--foo=on`/`--foo=true`/`--foo=1` all parse as `yes` (case insensitive) +- `--foo=no`/`--foo=off`/`--foo=false`/`--foo=0` all parse as `no` (case insensitive) +- Any other values will report a usage error + +### Integers and Numbers + +Integer and number values can be passed and parsed automatically. Any failures +to parse will cause a usage error. Integers support decimal (`123`), +hexadecimal (`0xFF`), and octal values (`0o644`). Nums support regular (`123` +or `1.23`) or scientific notation (`1e99`). + +For fixed-size integers (`Int64`, `Int32`, `Int16`, `Int8`), arguments that +exceed the representable range for those values are considered usage errors. + +### Enums + +For enums that do not have member values (e.g. `enum Foo(Baz, Qux)`, not `enum +Foo(Baz(x:Int), Qux)`, Tomo supports automatic command line argument parsing. +Parsing is case-insensitive: + +``` +# foo.tm +enum Foo(One, Two, Three) +func main(foo:Foo): + >> foo + +# Usage: +$ tomo foo.tm one +>> Foo.One + +$ tomo foo.tm xxx +foo: Invalid value provided for --foo; valid values are: One Two +Usage: foo [--help] +``` + +### Arrays of Text + +Currently, Tomo supports accepting arguments that take an array of text. +Array-of-text arguments can be passed like this: + +```tomo +# many-texts.tm +func main(args:[Text]): + >> args +``` + +```bash +$ tomo many-texts.tm +>> [] : [Text] + +$ tomo many-texts.tm one two three +>> ["one", "two", "three"] : [Text] + +$ tomo many-texts.tm --args=one,two,three +>> ["one", "two", "three"] : [Text] + +$ tomo many-texts.tm -- one --not-a-flag 'a space' +>> ["one", "--not-a-flag", "a space"] : [Text] +```