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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
# 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!
Usage: greet [--help] <name> [--be-excited|-E|--no-be-exited]
$ ./greet --help
Usage: 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
Usage: 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.
### Structs
For structs, values can be passed using positional arguments for each struct
field.
```
# foo.tm
struct Pair(x,y:Int)
func main(pair:Pair)
>> pair
$ tomo foo.tm -- --pair 1 2
Pair(x=1, y=2)
```
Tomo does not currently support omitting fields with default values or passing
individual struct fields by named flag.
### Enums
For enums, values can be passed using the enum's tag name and each of its
fields positionally (the same as for structs). Parsing is case-sensitive:
```
# foo.tm
enum Foo(Nothing, AnInteger(i:Int), TwoThings(i:Int, text:Text))
func main(foo:Foo)
>> foo
$ tomo foo.tm -- Nothing
Nothing
$ tomo foo.tm -- AnInteger 123
AnInteger(123)
$ tomo foo.tm -- TwoThings 123 hello
TwoThings(i=123, text="hello")
```
Like structs, enums do not currently support passing fields as flags or
omitting fields with default values.
### 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`
```
## Help and Manpages
When your program is generated, it will also come with a `--help` flag (unless
you have one defined) with automatically generated usage information. If you
add comments in front of your main function arguments, they will appear in the
`--help` output. Additionally, when your program is compiled, Tomo will also
build a Manpage for your program in `.build/yourprogram.1`, which will get
installed if you install your program.
```tomo
func main(
# Whether or not to frob your gropnoggles
frob: Bool = no
)
pass
```
```bash
$ tomo -e myprogram.tm
$ ./myprogram --help
# Usage: ./myprogram [--help] [--frob|--no-frob]
#
# --frob|--no-frob Whether or not to frob your gropnoggles (default:no)
#
```
```bash
$ man .build/myprogram.1
```
```
MYPROGRAM(1)
NAME
myprogram - a Tomo program
OPTIONS
--frob | --no-frob
Whether or not to frob your gropnoggles
```
## Metadata
You can specify metadata for a program, which is used for CLI messages like
`--help`, as well as manpage documentation. Metadata can be specified as either
a text literal (no interpolation) or as a file path literal.
```
USAGE: "--foo <n>"
HELP: "
This is some custom help text.
You can use these flags:
--foo <n> The foo parameter
--help Show this message
"
MANPAGE_DESCRIPTION: (./description.roff)
```
Supported metadata:
- `EXECUTABLE`: the name of the executable to compile. If not provided, the name
will be the name of the Tomo source file without the ".tm" extension.
- `USAGE`: the short form usage shown in CLI parsing errors and help pages. This
should be a single line without the name of the program, so `USAGE: "--foo"`
would translate to the error message `Usage: myprogram --foo`. If this is not
present, it will be generated automatically.
- `HELP`: The help message displayed when the `--help` flag is used or when there
is an argument parsing error. This should be a description of the program with
a multi-line documentation of commonly used flags.
- `MANPAGE`: the full manpage (overrules the options below).
- `MANPAGE_SYNOPSYS`: the synopsis section of the manpage (inserted literally).
- `MANPAGE_DESCRIPTION`: the description section of the manpage (inserted literally).
|