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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
# 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|E:Bool=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 -e greet.tm
Compiled executable: greet
$ ./greet
greet: Required argument 'name' was not provided!
Signature: greet [--help] <name> [--be-excited|-E|--no-be-exited]
$ ./greet --help
Signature: greet [--help] <name> [--be-excited|-E|--no-be-excited]
$ ./greet "Zaphod"
Hi Zaphod.
$ ./greet "Zaphod" --be-excited
Hello Zaphod!!!
$ ./greet "Zaphod" -E
Hello Zaphod!!!
$ ./greet --no-be-excited --name="Zaphod"
Hi Zaphod.
$ ./greet --not-a-real-argument "Bob"
greet: Unrecognized argument: --not-a-real-argument
Signature: greet [--help] <name> [--be-excited|-E|--no-be-excited]
```
Underscores in argument names are converted to dashes when parsing command line
arguments.
## Running Programs Directly
If you want to run a program directly (instead of compiling to an executable
with `tomo -e`), you can run the program with `tomo program.tm -- [program
arguments...]`. The `--` is required to separate the arguments passed to the
Tomo compiler from those being passed to your program. For example, `tomo
greet.tm -- --help` will pass the argument `--help` to your program, whereas
`tomo greet.tm --help` will pass `--help` to `tomo`.
## 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
# Signature:
$ tomo foo.tm one
>> Foo.One
$ tomo foo.tm xxx
foo: Invalid value provided for --foo; valid values are: One Two
Signature: foo [--help] <foo>
```
### Lists of Text
Currently, Tomo supports accepting arguments that take a list of text.
List-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]
```
## Aliases and Flag Arguments
Each argument may optionally have an alias of the form `name|alias`. This allows
you to specify a long-form argument and a single-letter flag like `verbose|v =
no`. Single letter flags (whether as an alias or as a main flag name) have
slightly different command line parsing rules:
- Single letter flags use only a single dash: `-v` vs `--verbose`
- Single letter flags can coalesce with other single letter flags: `-abc` is the
same as `-a -b -c`
When single letter flags coalesce together, the first flags in the cluster must
be boolean values, while the last one is allowed to be any type. This lets you
specify several flags at once while still providing arguments:
```tomo
func main(output|o:Path? = none, verbose|v:Bool = no)
...
```
```bash
$ tomo -e program.tm && ./program -vo outfile.txt`
```
|