1 ## oils_failures_allowed: 2
2
3 #### cd accepts a block, runs it in different dir
4 shopt -s ysh:all
5
6 const saved = "$PWD"
7
8 # OLDPWD is NOT defined
9 cd / { echo $PWD; echo OLDPWD=${OLDPWD:-} }; echo done
10
11 if ! test "$saved" = $PWD; then
12 echo FAIL
13 fi
14
15 cd /tmp {
16 write PWD=$PWD
17 write --sep ' ' pwd builtin: $(pwd)
18 }
19
20 if ! test "$saved" = $PWD; then
21 echo FAIL
22 fi
23
24 ## STDOUT:
25 /
26 OLDPWD=
27 done
28 PWD=/tmp
29 pwd builtin: /tmp
30 ## END
31
32 #### cd with block: requires explicit command
33 shopt --set ysh:upgrade
34
35 cd /tmp { echo $PWD }
36
37 HOME=~
38 cd { echo $PWD }
39
40 ## status: 2
41 ## STDOUT:
42 /tmp
43 ## END
44
45 #### cd passed block with return 1
46 shopt -s ysh:all
47
48 f() {
49 cd / {
50 echo block
51 return 1
52 echo 'not reached'
53 }
54 }
55 f
56 echo 'not reached'
57
58 ## status: 1
59 ## STDOUT:
60 block
61 ## END
62
63 #### cd passed a block defined in a different scope
64 shopt --set ysh:upgrade
65
66 proc my-cd (; b) {
67 cd /tmp ( ; ; b)
68 }
69
70 proc p {
71 var i = 42
72 var b = ^(echo "i = $i")
73
74 my-cd (b)
75 }
76
77 p
78
79 ## STDOUT:
80 ## END
81
82 #### io->eval() and io.captureStdout() passed a block in different scope
83 shopt --set ysh:upgrade
84
85 proc my-cd (; b) {
86 call io->eval(b)
87
88 var d = io->evalToDict(b)
89
90 pp test_ (d)
91
92 # Yup, this is a problem
93 var s = io.captureStdout(b)
94 echo "stdout $s"
95 }
96
97 proc p {
98 var i = 42
99 var b = ^(var x = 'x'; echo "i = $i")
100
101 my-cd (b)
102 }
103
104 p
105
106 ## STDOUT:
107 ## END
108
109 #### block doesn't have its own scope
110 shopt -s ysh:all
111 var x = 1
112 echo "x=$x"
113 cd / {
114 #set y = 5 # This would be an error because set doesn't do dynamic lookup
115 var x = 42
116 echo "x=$x"
117 }
118 echo "x=$x"
119 ## STDOUT:
120 x=1
121 x=42
122 x=42
123 ## END
124
125 #### redirects allowed in words, typed args, and after block
126 shopt -s ysh:upgrade
127
128 rm -f out
129 touch out
130
131 cd /tmp >>out {
132 echo 1 $PWD
133 }
134
135 cd /tmp >>out (; ; ^(echo 2 $PWD))
136
137 cd /tmp (; ; ^(echo 3 $PWD)) >>out
138
139 cd /tmp {
140 echo 4 $PWD
141 } >> out
142
143 cat out
144
145 ## STDOUT:
146 1 /tmp
147 2 /tmp
148 3 /tmp
149 4 /tmp
150 ## END
151
152 #### block literal in expression mode: ^(echo $PWD)
153 shopt -s ysh:all
154
155 const myblock = ^(echo $PWD | wc -l)
156 call io->eval(myblock)
157
158 const b2 = ^(echo one; echo two)
159 call io->eval(b2)
160
161 ## STDOUT:
162 1
163 one
164 two
165 ## END
166
167 #### block arg as typed expression
168
169 shopt -s oil:all
170
171 # literal
172 cd /tmp (; ; ^(echo $PWD))
173
174 const myblock = ^(echo $PWD)
175 cd /tmp (; ; myblock)
176
177 ## STDOUT:
178 /tmp
179 /tmp
180 ## END
181
182 #### Pass invalid typed args
183
184 cd /tmp (42) # should be a block
185 ## status: 3
186
187 #### Pass too many typed args
188
189 cd /tmp (1, 2)
190 ## status: 3
191
192 #### 'builtin' and 'command' with block
193 shopt --set oil:upgrade
194 builtin cd / {
195 echo "builtin $PWD"
196 }
197 command cd / {
198 echo "command $PWD"
199 }
200 ## STDOUT:
201 builtin /
202 command /
203 ## END
204
205 #### Consistency: Exit Status and Blocks
206 shopt --set parse_brace
207
208 cd / {
209 false
210 }
211 echo cd=$?
212
213 shopt --unset errexit {
214 false
215 }
216 echo shopt=$?
217
218 shvar FOO=foo {
219 echo " FOO=$FOO"
220 false
221 }
222 echo shvar=$?
223
224 try {
225 false
226 }
227 echo try=$?
228
229 ## STDOUT:
230 cd=0
231 shopt=0
232 FOO=foo
233 shvar=0
234 try=0
235 ## END
236
237 #### Consistency: Unwanted Blocks Are Errors
238 shopt --set parse_brace
239
240 true { echo BAD }
241 echo true $?
242
243 false ( 42, 43 )
244 echo false $?
245
246 echo { echo BAD }
247 echo echo block $?
248
249 echo ( 42, 43 )
250 echo echo args $?
251
252 command echo 'command block' { echo BAD }
253 echo command echo $?
254
255 builtin echo 'builtin block' { echo BAD }
256 echo builtin echo $?
257
258 pushd $TMP { echo BAD }
259 echo pushd $?
260
261 ## STDOUT:
262 true 2
263 false 2
264 echo block 2
265 echo args 2
266 command echo 2
267 builtin echo 2
268 pushd 2
269 ## END
270
271 #### Block with Bare Assignments
272
273 # oil:all has parse_equals
274 # is there any way to turn on parse_equals only in config blocks?
275 # but we don't know what's a block ahead of time
276 # I think we would have to check at runtime. Look at VarChecker
277
278 shopt --set oil:all
279
280 proc Rule(s ; ; ; b) {
281 echo "rule $s"
282 }
283
284 proc myrules(name) {
285 Rule $name-python {
286 kind = 'python'
287 }
288
289 Rule $name-cc {
290 kind = 'cc' # should NOT conflict
291 }
292 }
293
294 myrules foo
295 myrules bar
296
297 ## STDOUT:
298 rule foo-python
299 rule foo-cc
300 rule bar-python
301 rule bar-cc
302 ## END
303
304 #### Proc that doesn't take a block
305 shopt --set parse_brace parse_proc parse_paren
306
307 proc task(name ; ; ; b = null) {
308 echo "task name=$name"
309 if (b) {
310 call io->eval(b)
311 return 33
312 } else {
313 echo 'no block'
314 return 44
315 }
316 }
317
318 task spam
319 echo status=$?
320
321 echo
322
323 task foo {
324 echo 'running'
325 echo 'block'
326 }
327 echo status=$?
328
329 ## STDOUT:
330 task name=spam
331 no block
332 status=44
333
334 task name=foo
335 running
336 block
337 status=33
338 ## END
339