1 ## oils_failures_allowed: 1
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()/io.captureAll() 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 setvar s = io.captureAll(b)
97 echo "stdout $[s.stdout]" # Adds a newline
98 }
99
100 proc p {
101 var i = 42
102 var b = ^(var x = 'x'; echo "i = $i")
103
104 my-cd (b)
105 }
106
107 p
108
109 ## STDOUT:
110 i = 42
111 i = 42
112 (Dict) {"x":"x"}
113 stdout i = 42
114 stdout i = 42
115
116 ## END
117
118 #### block doesn't have its own scope
119 shopt -s ysh:all
120 var x = 1
121 echo "x=$x"
122 cd / {
123 #set y = 5 # This would be an error because set doesn't do dynamic lookup
124 var x = 42
125 echo "x=$x"
126 }
127 echo "x=$x"
128 ## STDOUT:
129 x=1
130 x=42
131 x=42
132 ## END
133
134 #### redirects allowed in words, typed args, and after block
135 shopt -s ysh:upgrade
136
137 rm -f out
138 touch out
139
140 cd /tmp >>out {
141 echo 1 $PWD
142 }
143
144 cd /tmp >>out (; ; ^(echo 2 $PWD))
145
146 cd /tmp (; ; ^(echo 3 $PWD)) >>out
147
148 cd /tmp {
149 echo 4 $PWD
150 } >> out
151
152 cat out
153
154 ## STDOUT:
155 1 /tmp
156 2 /tmp
157 3 /tmp
158 4 /tmp
159 ## END
160
161 #### block literal in expression mode: ^(echo $PWD)
162 shopt -s ysh:all
163
164 const myblock = ^(echo $PWD | wc -l)
165 call io->eval(myblock)
166
167 const b2 = ^(echo one; echo two)
168 call io->eval(b2)
169
170 ## STDOUT:
171 1
172 one
173 two
174 ## END
175
176 #### block arg as typed expression
177
178 shopt -s oil:all
179
180 # literal
181 cd /tmp (; ; ^(echo $PWD))
182
183 const myblock = ^(echo $PWD)
184 cd /tmp (; ; myblock)
185
186 ## STDOUT:
187 /tmp
188 /tmp
189 ## END
190
191 #### Pass invalid typed args
192
193 cd /tmp (42) # should be a block
194 ## status: 3
195
196 #### Pass too many typed args
197
198 cd /tmp (1, 2)
199 ## status: 3
200
201 #### 'builtin' and 'command' with block
202 shopt --set oil:upgrade
203 builtin cd / {
204 echo "builtin $PWD"
205 }
206 command cd / {
207 echo "command $PWD"
208 }
209 ## STDOUT:
210 builtin /
211 command /
212 ## END
213
214 #### Consistency: Exit Status and Blocks
215 shopt --set parse_brace
216
217 cd / {
218 false
219 }
220 echo cd=$?
221
222 shopt --unset errexit {
223 false
224 }
225 echo shopt=$?
226
227 shvar FOO=foo {
228 echo " FOO=$FOO"
229 false
230 }
231 echo shvar=$?
232
233 try {
234 false
235 }
236 echo try=$?
237
238 ## STDOUT:
239 cd=0
240 shopt=0
241 FOO=foo
242 shvar=0
243 try=0
244 ## END
245
246 #### Consistency: Unwanted Blocks Are Errors
247 shopt --set parse_brace
248
249 true { echo BAD }
250 echo true $?
251
252 false ( 42, 43 )
253 echo false $?
254
255 echo { echo BAD }
256 echo echo block $?
257
258 echo ( 42, 43 )
259 echo echo args $?
260
261 command echo 'command block' { echo BAD }
262 echo command echo $?
263
264 builtin echo 'builtin block' { echo BAD }
265 echo builtin echo $?
266
267 pushd $TMP { echo BAD }
268 echo pushd $?
269
270 ## STDOUT:
271 true 2
272 false 2
273 echo block 2
274 echo args 2
275 command echo 2
276 builtin echo 2
277 pushd 2
278 ## END
279
280 #### Block with Bare Assignments
281
282 # oil:all has parse_equals
283 # is there any way to turn on parse_equals only in config blocks?
284 # but we don't know what's a block ahead of time
285 # I think we would have to check at runtime. Look at VarChecker
286
287 shopt --set oil:all
288
289 proc Rule(s ; ; ; b) {
290 echo "rule $s"
291 }
292
293 proc myrules(name) {
294 Rule $name-python {
295 kind = 'python'
296 }
297
298 Rule $name-cc {
299 kind = 'cc' # should NOT conflict
300 }
301 }
302
303 myrules foo
304 myrules bar
305
306 ## STDOUT:
307 rule foo-python
308 rule foo-cc
309 rule bar-python
310 rule bar-cc
311 ## END
312
313 #### Proc that doesn't take a block
314 shopt --set parse_brace parse_proc parse_paren
315
316 proc task(name ; ; ; b = null) {
317 echo "task name=$name"
318 if (b) {
319 call io->eval(b)
320 return 33
321 } else {
322 echo 'no block'
323 return 44
324 }
325 }
326
327 task spam
328 echo status=$?
329
330 echo
331
332 task foo {
333 echo 'running'
334 echo 'block'
335 }
336 echo status=$?
337
338 ## STDOUT:
339 task name=spam
340 no block
341 status=44
342
343 task name=foo
344 running
345 block
346 status=33
347 ## END
348