1 | ## our_shell: ysh
|
2 |
|
3 | #### For loop over expression: List
|
4 | var mylist = [1, 2, 3]
|
5 | for item in (mylist) {
|
6 | echo "item $item"
|
7 | }
|
8 |
|
9 | ## STDOUT:
|
10 | item 1
|
11 | item 2
|
12 | item 3
|
13 | ## END
|
14 |
|
15 | #### For loop over expression: Dict, not BashAssoc
|
16 |
|
17 | var mydict = {name: 'bob', age: 40}
|
18 | for key in (mydict) {
|
19 | echo "key $key"
|
20 | }
|
21 |
|
22 | declare -A A=([name]=bob)
|
23 | for key in (A) {
|
24 | echo "key $key"
|
25 | }
|
26 |
|
27 | ## status: 3
|
28 | ## STDOUT:
|
29 | key name
|
30 | key age
|
31 | ## END
|
32 |
|
33 |
|
34 | #### For loop over range
|
35 | var myrange = 0 ..< 3
|
36 | for i in (myrange) {
|
37 | echo "i $i"
|
38 | }
|
39 |
|
40 | ## STDOUT:
|
41 | i 0
|
42 | i 1
|
43 | i 2
|
44 | ## END
|
45 |
|
46 | #### Shell for loop with index (equivalent of enumerate())
|
47 | for i, item in a b c {
|
48 | echo "$i $item"
|
49 | }
|
50 | ## STDOUT:
|
51 | 0 a
|
52 | 1 b
|
53 | 2 c
|
54 | ## END
|
55 |
|
56 | #### 3 indices with (mylist) is a runtime error
|
57 | for i, item bad in (['foo', 'bar']) {
|
58 | echo "$i $item $bad"
|
59 | }
|
60 | ## status: 2
|
61 |
|
62 | #### Shell for loop can't have 3 indices
|
63 | for i, bad, bad in a b c {
|
64 | echo $i $item
|
65 | }
|
66 | ## status: 2
|
67 |
|
68 | #### Any for loop can't have 4 indices
|
69 | for a, b, c, d in (['foo']) {
|
70 | echo $i $item
|
71 | }
|
72 | ## status: 2
|
73 |
|
74 | #### Expression for loop with index: List
|
75 | for i, item in (['spam', 'eggs']) {
|
76 | echo "$i $item"
|
77 | }
|
78 | ## STDOUT:
|
79 | 0 spam
|
80 | 1 eggs
|
81 | ## END
|
82 |
|
83 | #### Expression for loop with index: Dict (TODO: define dict iter order)
|
84 | for key, value in ({name: 'bob', age: 40}) {
|
85 | echo "pair $key $value"
|
86 | }
|
87 | ## STDOUT:
|
88 | pair name bob
|
89 | pair age 40
|
90 | ## END
|
91 |
|
92 | #### Dict: index key value loop (TODO: define dict iter order)
|
93 | for i, key, value in ({name: 'bob', age: 40}) {
|
94 | echo "entry $i $key $value"
|
95 | }
|
96 | ## STDOUT:
|
97 | entry 0 name bob
|
98 | entry 1 age 40
|
99 | ## END
|
100 |
|
101 |
|
102 | #### Equivalent of zip()
|
103 |
|
104 | var array = :| d e f |
|
105 |
|
106 | for i, item in a b c {
|
107 | echo "$i $item $[array[i]]"
|
108 | }
|
109 |
|
110 | ## STDOUT:
|
111 | 0 a d
|
112 | 1 b e
|
113 | 2 c f
|
114 | ## END
|
115 |
|
116 | #### parse_bare_word eliminates confusion
|
117 |
|
118 | shopt --unset parse_bare_word
|
119 |
|
120 | for x in mylist { # THIS FAILS
|
121 | echo "BAD $x"
|
122 | }
|
123 |
|
124 | ## status: 2
|
125 | ## STDOUT:
|
126 | ## END
|
127 |
|
128 |
|
129 | #### Object that's not iterable
|
130 |
|
131 | echo hi
|
132 | for x in (42) {
|
133 | echo $x
|
134 | }
|
135 |
|
136 | ## status: 3
|
137 | ## STDOUT:
|
138 | hi
|
139 | ## END
|
140 |
|
141 | #### YSH for with brace substitution and glob
|
142 |
|
143 | touch {foo,bar}.py
|
144 | for i, file in *.py {README,foo}.md {
|
145 | echo "$i $file"
|
146 | }
|
147 | ## STDOUT:
|
148 | 0 bar.py
|
149 | 1 foo.py
|
150 | 2 README.md
|
151 | 3 foo.md
|
152 | ## END
|
153 |
|
154 | #### for x in (io.stdin) {
|
155 |
|
156 | # to avoid stdin conflict
|
157 |
|
158 | $[ENV.SH] $[ENV.REPO_ROOT]/spec/testdata/ysh-for-stdin.ysh
|
159 |
|
160 | ## STDOUT:
|
161 | -1-
|
162 | -2-
|
163 | -3-
|
164 |
|
165 | 0 1
|
166 | 1 2
|
167 | 2 3
|
168 |
|
169 | empty
|
170 | done
|
171 |
|
172 | empty2
|
173 | done2
|
174 |
|
175 | space
|
176 | hi
|
177 | ## END
|
178 |
|
179 | #### I/O error in for x in (stdin) {
|
180 |
|
181 | set +o errexit
|
182 |
|
183 | # EISDIR - stdin descriptor is dir
|
184 | $[ENV.SH] -c 'for x in (io.stdin) { echo $x }' < /
|
185 | if test $? -ne 0; then
|
186 | echo pass
|
187 | fi
|
188 |
|
189 | ## STDOUT:
|
190 | pass
|
191 | ## END
|
192 |
|
193 | #### Append to List in loop extends the loop (matches JS)
|
194 |
|
195 | # see demo/survey-loop
|
196 |
|
197 | var mylist = [1,2,3]
|
198 | for x in (mylist) {
|
199 | if (x === 2) {
|
200 | call mylist->append(99)
|
201 | }
|
202 | echo $x
|
203 | }
|
204 | ## STDOUT:
|
205 | 1
|
206 | 2
|
207 | 3
|
208 | 99
|
209 | ## END
|
210 |
|
211 | #### Remove from List in loop shortens it (matches JS)
|
212 |
|
213 | # see demo/survey-loop
|
214 |
|
215 | var mylist = [1,2,3,4]
|
216 | for x in (mylist) {
|
217 | if (x === 2) {
|
218 | call mylist->pop()
|
219 | }
|
220 | echo $x
|
221 | }
|
222 | ## STDOUT:
|
223 | 1
|
224 | 2
|
225 | 3
|
226 | ## END
|
227 |
|
228 | #### Adding to Dict in loop does NOT extend the loop (matches JS)
|
229 |
|
230 | # see demo/survey-loop
|
231 |
|
232 | var mydict = {"1": null, "2": null, "3": null}
|
233 | for x in (mydict) {
|
234 | if (x === "2") {
|
235 | setvar mydict["99"] = null
|
236 | }
|
237 | echo $x
|
238 | }
|
239 | ## STDOUT:
|
240 | 1
|
241 | 2
|
242 | 3
|
243 | ## END
|
244 |
|
245 | #### Removing from Dict in loop does NOT change the loop (does NOT match JS)
|
246 |
|
247 | # see demo/survey-loop
|
248 |
|
249 | var mydict = {"1": null, "2": null, "3": null, "4": null}
|
250 | for x in (mydict) {
|
251 | if (x === "2") {
|
252 | call mydict->erase("1")
|
253 | call mydict->erase("3")
|
254 | }
|
255 | echo $x
|
256 | }
|
257 | ## STDOUT:
|
258 | 1
|
259 | 2
|
260 | 3
|
261 | 4
|
262 | ## END
|