aboutsummaryrefslogtreecommitdiff
path: root/docs/command-line-parsing.md
blob: 5d8af9d5b0ef298515fb2e601d8f4734e235fda9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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] <name> [--be-excited]

$ tomo greet.tm --help
Usage: greet [--help] <name> [--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] <name> [--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] <foo>
```

### 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]
```