1 ## our_shell: ysh
2 ## oils_failures_allowed: 1
3
4 # Can we do this entirely in user code, not as a builtin?
5 #
6 # The following is as close as possible to the python argparse which seems to work well
7
8 #### Argparse bool option and positional
9
10 source --builtin args.ysh
11
12 Args (&spec) {
13 flag -v --verbose ('bool')
14 arg src
15 arg dst
16
17 rest more # allow more args
18 }
19 #json write (spec)
20
21 var argv = ['-v', 'src/path', 'dst/path']
22
23 # TODO: need destructuring with var
24 # var arg, i = parseArgs(spec, argv)
25
26 var result = parseArgs(spec, argv)
27 setvar arg, i = result
28
29 json write --pretty=F (arg)
30 json write (i)
31 ## STDOUT:
32 {"verbose":true,"src":"src/path","dst":"dst/path","more":[]}
33 3
34 ## END
35
36 #### Argparse basic help message
37
38 source --builtin args.ysh
39
40 Args (&spec) {
41 description = '''
42 Reference Implementation
43 '''
44 prog = "program-name"
45
46 arg -v --verbose (Bool, help = "Verbose")
47 arg src
48 arg dst
49 }
50 var argv = ['-h', 'src', 'dst']
51
52 # Help
53 var arg = parseArgs(spec, argv)
54
55 ## STDOUT:
56 usage: program-name [-h] [-v] src dst
57
58 Reference Implementation
59
60 positional arguments:
61 src
62 dst
63
64 options:
65 -h, --help show this help message and exit
66 -v, --verbose Verbose
67 ## END
68
69 #### Parse args using a JSON argspec
70
71 source --builtin args.ysh
72
73 var spec = {
74 flags: [
75 {short: '-v', long: '--verbose', type: null, default: '', help: 'Enable verbose logging'},
76 {short: '-c', long: '--count', type: 'int', default: 80, help: 'Maximum line length'},
77 ],
78 args: [
79 {name: 'file', type: 'str', help: 'File to check line lengths of'}
80 ],
81 rest: false,
82 }
83
84 var argsCases = [
85 :| -v --count 120 example.sh |,
86 :| -v --count 120 example.sh -v |, # duplicate flags are ignored
87 :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
88 ]
89
90 var argparse_py = '''
91 import argparse
92 import sys
93
94 spec = argparse.ArgumentParser()
95 spec.add_argument("filename")
96 spec.add_argument("-c", "--count")
97 spec.add_argument("-v", "--verbose",
98 action="store_true")
99
100 result = spec.parse_args(sys.argv[1:])
101 print(result)
102 '''
103
104 for args in (argsCases) {
105 var args_str = args->join(" ")
106 echo "---------- $args_str ----------"
107 echo "\$ bin/ysh example.sh $args_str"
108 pp line (parseArgs(spec, args))
109
110 echo
111 echo "\$ python3 example.py $args_str"
112 python3 -c $argparse_py @args
113
114 echo
115 }
116 ## STDOUT:
117 ---------- -v --count 120 example.sh ----------
118 $ bin/ysh example.sh -v --count 120 example.sh
119 (List) [{"verbose":true,"count":120,"file":"example.sh"},4]
120
121 $ python3 example.py -v --count 120 example.sh
122 Namespace(filename='example.sh', count='120', verbose=True)
123
124 ---------- -v --count 120 example.sh -v ----------
125 $ bin/ysh example.sh -v --count 120 example.sh -v
126 (List) [{"verbose":true,"count":120,"file":"example.sh"},5]
127
128 $ python3 example.py -v --count 120 example.sh -v
129 Namespace(filename='example.sh', count='120', verbose=True)
130
131 ---------- -v --count 120 example.sh -v --count 150 ----------
132 $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
133 (List) [{"verbose":true,"count":150,"file":"example.sh"},7]
134
135 $ python3 example.py -v --count 120 example.sh -v --count 150
136 Namespace(filename='example.sh', count='150', verbose=True)
137
138 ## END
139
140 #### Args spec definitions
141
142 source --builtin args.ysh
143
144 Args (&spec) {
145 flag -v --verbose ('bool')
146 arg src
147 arg dst
148
149 rest more # allow more args
150 }
151
152 json write (spec)
153 ## STDOUT:
154 {
155 "flags": [
156 {
157 "short": "-v",
158 "long": "--verbose",
159 "type": "bool",
160 "default": null,
161 "help": null
162 }
163 ],
164 "args": [
165 {
166 "name": "src",
167 "type": "str",
168 "default": null,
169 "help": null
170 },
171 {
172 "name": "dst",
173 "type": "str",
174 "default": null,
175 "help": null
176 }
177 ],
178 "rest": "more"
179 }
180 ## END
181
182 #### Args spec definitions driving argument parser
183
184 source --builtin args.ysh
185
186 Args (&spec) {
187 flag -v --verbose ('bool', false)
188 flag -c --count ('int', 120)
189 arg file
190 }
191
192 var argsCases = [
193 :| -v --count 120 example.sh |,
194 :| -v --count 120 example.sh -v |, # duplicate flags are ignored
195 :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
196 ]
197
198 for args in (argsCases) {
199 var args_str = args->join(" ")
200 echo "---------- $args_str ----------"
201 echo "\$ bin/ysh example.sh $args_str"
202 pp line (parseArgs(spec, args))
203
204 echo
205 }
206 ## STDOUT:
207 ---------- -v --count 120 example.sh ----------
208 $ bin/ysh example.sh -v --count 120 example.sh
209 (List) [{"verbose":true,"count":120,"file":"example.sh"},4]
210
211 ---------- -v --count 120 example.sh -v ----------
212 $ bin/ysh example.sh -v --count 120 example.sh -v
213 (List) [{"verbose":true,"count":120,"file":"example.sh"},5]
214
215 ---------- -v --count 120 example.sh -v --count 150 ----------
216 $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
217 (List) [{"verbose":true,"count":150,"file":"example.sh"},7]
218
219 ## END