-
Notifications
You must be signed in to change notification settings - Fork 0
/
args.myr
126 lines (96 loc) · 2.1 KB
/
args.myr
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
/*
Command line flag handling library, respects -- to end flags
Styled after the Inferno arg.m as per http://man.cat-v.org/inferno/2/arg
*/
use std
pkg args =
const init : (args : byte[:][:] -> void) // Must be called first
const setusage : (str : byte[:] -> void)
const usage : (-> void)
const opt : (-> char)
const earg : (-> byte[:])
const progname : (-> byte[:])
const argv : (-> byte[:][:])
;;
var initialized = false // Has the lib been init()'d ?
var done = false // Are we done parsing ?
var usagestr // String to print after usage:
var argv0 : byte[:] // The argv[0] program name
var argen : byte[:][:] // The arguments argv[1:]
var i = 0 // Position in argv
// Initializes the argument library
const init = {args : byte[:][:]
if initialized
-> void
;;
initialized = true
/* Ingest arguments */
if ! (args.len > 0)
-> void
;;
argv0 = args[0]
if ! (args.len > 1)
-> void
;;
argen = args[1:]
}
// Sets the library usage string
const setusage = {str : byte[:]
initcheck()
usagestr = std.fmt("usage: {}\n", str)
}
// Emits and exits for usage
const usage = {
initcheck()
std.fatal(usagestr)
}
// Emits the next flag character in the flag chain
const opt = {
initcheck()
// If we hit --, stop parsing
match argen[i]
| "--":
done = true
| _:
;
;;
// Conditions for not yielding a character
if done || i >= argen.len || argen[i].len < 2 || argen[i][0] != ('-' : byte)
-> (0 : char)
;;
-> (argen[i++][1] : char)
}
// Returns the current argument which must not be nil
const earg = {
initcheck()
// If we hit --, stop parsing
match argen[i]
| "--":
done = true
| _:
;
;;
if done || argen[i].len < 1 || i >= argen.len
usage()
;;
// So we avoid parsing out a flag, use -- to avoid this?
if argen[i][0] == ('-' : byte)
usage()
;;
-> argen[i++]
}
// Returns the argv0 of the input, our program name
const progname = {
initcheck()
-> argv0
}
// Print remaining arguments
const argv = {
-> argen[i:]
}
// Verifies if init() has been called
const initcheck = {
if !initialized
std.fatal("err: must call args.init() first\n")
;;
}