-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseopt.arc
More file actions
144 lines (130 loc) · 4.39 KB
/
Copy pathparseopt.arc
File metadata and controls
144 lines (130 loc) · 4.39 KB
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
(require "re.arc")
(= version* "0.0.1")
(with (prog_ (re-replace ".*/" args*.0 "")
spec_ (table)
opts_ (table)
count_ 0
args_ nil
help_ nil)
(def pr-version ()
(w/stdout (stderr)
(prn prog_ " version " version*))
(quit 1))
(def pr-usage ()
(w/stdout (stderr)
(pr "Usage: " prog_ " [OPTION]...")
((afn (x)
(awhen (and (acons x) (car x))
(pr " " upcase.it))
(if (no x) nil
(~acons x) (pr " [" upcase.x "]...")
(self cdr.x))) args_)
(prn #\newline)
(map (fn ((x y))
(pr " " x)
(if blank.y
(prn)
(if (len> x 21)
(prn #\newline (newstring 24 #\space) y)
(prn (newstring (- 22 len.x) #\space) y))))
rev.help_)
(prn " --help display this help and exit")
(prn " --version output version information and exit")
)
(quit 1))
(def invalid-opt-err (x)
(w/stdout (stderr)
(if (len> x 1)
(prn prog_ ": unrecognized option '--" x "'")
(prn prog_ ": invalid option -- '" x "'"))
(prn "Try `" prog_ " --help' for more information."))
(quit 4))
(def require-arg-err (x)
(w/stdout (stderr)
(pr prog_ ": option requires an argument ")
(if (len> x 1)
(prn "'--" x "'")
(prn "-- '" x "'"))
(prn "Try `" prog_ " --help' for more information."))
(quit 2))
(def missing-operand-err ()
(w/stdout (stderr)
(prn prog_ ": missing operand")
(prn "Try `" prog_ " --help' for more information."))
(quit 1))
(def parseopt-err (opt msg (o code 1))
(w/stdout (stderr)
(prn prog_ ": " opt ": invalid argument")
(prn msg))
(quit code))
(def setup-optspec ((name spec default (o help "")))
(if (is name 'args)
(= args_ spec)
(withs ((k v) (tokens spec #\=)
(v m) (only.tokens v #\:)
(s l) (tokens k #\|)
h nil)
(= opts_.name default)
(++ count_)
(when (len> s 1)
(= l s
s nil))
(when s
(= spec_.s (obj name name value v default default))
(= h (+ "-" s (when v (+ " " (or m "VALUE"))))))
(when l
(= spec_.l (obj name name value v default default))
(= h (string h (when s ", ") "--" l (when v (+ "=" (or m "VALUE"))))))
(push (list h help) help_))))
(def lenargs (x (o acc 1))
(if (~acons x) 0
(acons cdr.x) (lenargs cdr.x (+ 1 acc))
acc))
(def parseopt ((o args (cdr:copy args*)))
(if (find "--help" args) (pr-usage)
(find "--version" args) (pr-version)
(with (oargs nil opts (copy opts_))
(whilet x (pop args)
(if (is x "--")
(do (= oargs (join rev.args oargs))
(wipe args))
(~litmatch "-" x)
(push x oargs)
(withs ((k v) (tokens x #\=)
x (if (litmatch "--" k)
(list:trim k 'front #\-)
(map [string _] (cdr:coerce k 'cons)))
lasti (- len.x 1))
(on k x
(aif (spec_ string.k)
(let val (if it!value
(aif (and (is index lasti) (or v (pop args)))
it
(require-arg-err k))
t)
(= (opts it!name)
(on-err [parseopt-err k details._ 2]
(fn ()
(case it!value
"i" (int val)
val)))))
(invalid-opt-err k))))))
(if (len< oargs (lenargs args_))
(missing-operand-err)
(list opts rev.oargs)))))
(mac defopts args
(= spec_ (table) opts_ (table) count_ 0 args_ nil help_ nil)
(each x args
(setup-optspec x)))
(mac w/opts (spec . body)
(= spec_ (table) opts_ (table) count_ 0 args_ nil help_ nil)
(w/uniq g
(each x spec
(setup-optspec x))
(withs ((opts args) (parseopt)
g (accum a (each x (map car spec)
(a x)
(a opts.x))))
`(with (,@g ,args_ ',args)
,@body))))
)