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