1 ## our_shell: ysh
2 ## oils_failures_allowed: 1
3
4 #### Bool flag, positional args, more positional
5
6 source $LIB_YSH/args.ysh
7
8 parser (&spec) {
9 flag -v --verbose ('bool')
10 arg src
11 arg dst
12
13 rest more # allow more args
14 }
15 #json write (spec)
16
17 var argv = ['-v', 'src/path', 'dst/path', 'x', 'y', 'z']
18
19 var args = parseArgs(spec, argv)
20
21 pp test_ (args)
22
23 if (args.verbose) {
24 echo "$[args.src] -> $[args.dst]"
25 write -- @[args.more]
26 }
27
28 ## STDOUT:
29 (Dict) {"verbose":true,"src":"src/path","dst":"dst/path","more":["x","y","z"]}
30 src/path -> dst/path
31 x
32 y
33 z
34 ## END
35
36 #### Test multiple ARGVs against a parser
37
38 source $LIB_YSH/args.ysh
39
40 parser (&spec) {
41 flag -v --verbose ('bool', default=false)
42 flag -c --count ('int', default=120)
43 arg file
44 }
45
46 var argsCases = [
47 :| -v --count 120 example.sh |,
48 :| -v --count 120 example.sh -v |, # duplicate flags are ignored
49 :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
50 ]
51
52 for args in (argsCases) {
53 var args_str = join(args, ' ')
54 echo "---------- $args_str ----------"
55 echo "\$ bin/ysh example.sh $args_str"
56 pp test_ (parseArgs(spec, args))
57
58 echo
59 }
60 ## STDOUT:
61 ---------- -v --count 120 example.sh ----------
62 $ bin/ysh example.sh -v --count 120 example.sh
63 (Dict) {"verbose":true,"count":120,"file":"example.sh"}
64
65 ---------- -v --count 120 example.sh -v ----------
66 $ bin/ysh example.sh -v --count 120 example.sh -v
67 (Dict) {"verbose":true,"count":120,"file":"example.sh"}
68
69 ---------- -v --count 120 example.sh -v --count 150 ----------
70 $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
71 (Dict) {"verbose":true,"count":150,"file":"example.sh"}
72
73 ## END
74
75 #### Basic help message
76
77 source $LIB_YSH/args.ysh
78
79 parser (&spec) {
80 # TODO: implement description, prog and help message
81 description '''
82 Reference Implementation
83 '''
84 prog "program-name"
85
86 arg -v --verbose (Bool, help = "Verbose")
87 arg src
88 arg dst
89 }
90 var argv = ['-h', 'src', 'dst']
91
92 # Help
93 var args = parseArgs(spec, argv)
94
95 ## STDOUT:
96 usage: program-name [-h] [-v] src dst
97
98 Reference Implementation
99
100 positional arguments:
101 src
102 dst
103
104 options:
105 -h, --help show this help message and exit
106 -v, --verbose Verbose
107 ## END
108
109 #### Compare parseArgs() vs Python argparse
110
111 source $LIB_YSH/args.ysh
112
113 var spec = {
114 flags: [
115 {short: '-v', long: '--verbose', name: 'verbose', type: null, default: '', help: 'Enable verbose logging'},
116 {short: '-c', long: '--count', name: 'count', type: 'int', default: 80, help: 'Maximum line length'},
117 ],
118 args: [
119 {name: 'file', type: 'str', help: 'File to check line lengths of'}
120 ],
121 rest: null,
122 }
123
124 var argsCases = [
125 :| -v --count 120 example.sh |,
126 :| -v --count 120 example.sh -v |, # duplicate flags are ignored
127 :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
128 ]
129
130 var argparse_py = '''
131 import argparse
132 import sys
133
134 spec = argparse.ArgumentParser()
135 spec.add_argument("filename")
136 spec.add_argument("-c", "--count")
137 spec.add_argument("-v", "--verbose",
138 action="store_true")
139
140 result = spec.parse_args(sys.argv[1:])
141 print(result)
142 '''
143
144 for args in (argsCases) {
145 var args_str = args=>join(" ")
146 echo "---------- $args_str ----------"
147 echo "\$ bin/ysh example.sh $args_str"
148 pp test_ (parseArgs(spec, args))
149
150 echo
151 echo "\$ python3 example.py $args_str"
152 python3 -c $argparse_py @args
153
154 echo
155 }
156 ## STDOUT:
157 ---------- -v --count 120 example.sh ----------
158 $ bin/ysh example.sh -v --count 120 example.sh
159 (Dict) {"verbose":true,"count":120,"file":"example.sh"}
160
161 $ python3 example.py -v --count 120 example.sh
162 Namespace(filename='example.sh', count='120', verbose=True)
163
164 ---------- -v --count 120 example.sh -v ----------
165 $ bin/ysh example.sh -v --count 120 example.sh -v
166 (Dict) {"verbose":true,"count":120,"file":"example.sh"}
167
168 $ python3 example.py -v --count 120 example.sh -v
169 Namespace(filename='example.sh', count='120', verbose=True)
170
171 ---------- -v --count 120 example.sh -v --count 150 ----------
172 $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
173 (Dict) {"verbose":true,"count":150,"file":"example.sh"}
174
175 $ python3 example.py -v --count 120 example.sh -v --count 150
176 Namespace(filename='example.sh', count='150', verbose=True)
177
178 ## END
179
180 #### Define spec and print it
181
182 source $LIB_YSH/args.ysh
183
184 parser (&spec) {
185 flag -v --verbose ('bool')
186 arg src
187 arg dst
188
189 rest more # allow more args
190 }
191
192 json write (spec)
193 ## STDOUT:
194 {
195 "flags": [
196 {
197 "short": "-v",
198 "long": "--verbose",
199 "name": "verbose",
200 "type": "bool",
201 "default": false,
202 "help": null
203 }
204 ],
205 "args": [
206 {
207 "name": "src",
208 "help": null
209 },
210 {
211 "name": "dst",
212 "help": null
213 }
214 ],
215 "rest": "more"
216 }
217 ## END
218
219 #### Default values
220 source $LIB_YSH/args.ysh
221
222 parser (&spec) {
223 flag -S --sanitize ('bool', default=false)
224 flag -v --verbose ('bool', default=false)
225 flag -P --max-procs ('int') # Will set to null (the default default)
226 }
227
228 var args = parseArgs(spec, [])
229
230 pp test_ (args)
231 ## STDOUT:
232 (Dict) {"sanitize":false,"verbose":false,"max-procs":null}
233 ## END
234
235 #### Duplicate argument/flag names
236 source $LIB_YSH/args.ysh
237
238 try {
239 parser (&spec) {
240 flag -n --name
241 flag -N --name
242 }
243 }
244 echo status=$_status
245
246 try {
247 parser (&spec) {
248 flag -n --name
249 arg name
250 }
251 }
252 echo status=$_status
253
254 try {
255 parser (&spec) {
256 arg name
257 flag -o --other
258 arg name
259 }
260 }
261 echo status=$_status
262 ## STDOUT:
263 status=3
264 status=3
265 status=3
266 ## END
267
268 #### Error cases
269 source $LIB_YSH/args.ysh
270
271 parser (&spec) {
272 flag -v --verbose
273 flag -n --num ('int', required=true)
274
275 arg action
276 arg other (required=false)
277 }
278
279 try { call parseArgs(spec, :| -n 10 action other extra |) }
280 echo status=$_status
281
282 try { call parseArgs(spec, :| -n |) }
283 echo status=$_status
284
285 try { call parseArgs(spec, :| -n -v |) }
286 echo status=$_status
287
288 try { = parseArgs(spec, :| -n 10 |) }
289 echo status=$_status
290
291 try { call parseArgs(spec, :| -v action |) }
292 echo status=$_status
293
294 try { call parseArgs(spec, :| --unknown |) }
295 echo status=$_status
296 ## STDOUT:
297 status=2
298 status=2
299 status=2
300 status=2
301 status=2
302 status=2
303 ## END