1 |
# Oil builtins |
2 |
|
3 |
#### append onto a=(1 2) |
4 |
shopt -s parse_at |
5 |
a=(1 2) |
6 |
append :a '3 4' '5' |
7 |
argv.py @a |
8 |
append -- :a 6 |
9 |
argv.py @a |
10 |
## STDOUT: |
11 |
['1', '2', '3 4', '5'] |
12 |
['1', '2', '3 4', '5', '6'] |
13 |
## END |
14 |
|
15 |
#### append onto var a = %(1 2) |
16 |
shopt -s parse_at parse_proc |
17 |
var a = %(1 2) |
18 |
append a '3 4' '5' # : is optional |
19 |
argv.py @a |
20 |
## STDOUT: |
21 |
['1', '2', '3 4', '5'] |
22 |
## END |
23 |
|
24 |
#### append onto var a = ['1', '2'] |
25 |
shopt -s parse_at parse_proc |
26 |
var a = ['1', '2'] |
27 |
append a '3 4' '5' # : is optional |
28 |
argv.py @a |
29 |
## STDOUT: |
30 |
['1', '2', '3 4', '5'] |
31 |
## END |
32 |
|
33 |
#### append with invalid type |
34 |
s='' |
35 |
append :s a b |
36 |
echo status=$? |
37 |
## stdout: status=1 |
38 |
|
39 |
#### append with invalid var name |
40 |
append - a b |
41 |
echo status=$? |
42 |
## stdout: status=2 |
43 |
|
44 |
#### write --sep, --end, -n, varying flag syntax |
45 |
shopt -s oil:all |
46 |
var a = %('a b' 'c d') |
47 |
write @a |
48 |
write . |
49 |
write -- @a |
50 |
write . |
51 |
|
52 |
write --sep '' --end '' @a; write |
53 |
write . |
54 |
|
55 |
write --sep '_' -- @a |
56 |
write --sep '_' --end $' END\n' -- @a |
57 |
|
58 |
# with = |
59 |
write --sep='_' --end=$' END\n' -- @a |
60 |
|
61 |
write -n x |
62 |
write -n y |
63 |
write |
64 |
|
65 |
## STDOUT: |
66 |
a b |
67 |
c d |
68 |
. |
69 |
a b |
70 |
c d |
71 |
. |
72 |
a bc d |
73 |
. |
74 |
a b_c d |
75 |
a b_c d END |
76 |
a b_c d END |
77 |
xy |
78 |
## END |
79 |
|
80 |
#### write --qsn |
81 |
write --qsn foo bar |
82 |
write __ |
83 |
|
84 |
write --qsn 'abc def' ' 123 456' |
85 |
write __ |
86 |
|
87 |
write --qsn $'one\ttwo\n' |
88 |
|
89 |
write __ |
90 |
write --qsn $'\u{3bc}' |
91 |
|
92 |
|
93 |
## STDOUT: |
94 |
foo |
95 |
bar |
96 |
__ |
97 |
'abc def' |
98 |
' 123 456' |
99 |
__ |
100 |
'one\ttwo\n' |
101 |
__ |
102 |
'μ' |
103 |
## END |
104 |
|
105 |
|
106 |
#### write --qsn --unicode |
107 |
write --qsn $'\u{3bc}' |
108 |
write --qsn --unicode u $'\u{3bc}' |
109 |
write --qsn --unicode x $'\u{3bc}' |
110 |
|
111 |
## STDOUT: |
112 |
'μ' |
113 |
'\u{3bc}' |
114 |
'\xce\xbc' |
115 |
## END |
116 |
|
117 |
#### write -e not supported |
118 |
shopt -s oil:all |
119 |
write -e foo |
120 |
write status=$? |
121 |
## stdout-json: "" |
122 |
## status: 2 |
123 |
|
124 |
#### write syntax error |
125 |
shopt -s oil:all |
126 |
write ---end foo |
127 |
write status=$? |
128 |
## stdout-json: "" |
129 |
## status: 2 |
130 |
|
131 |
#### write -- |
132 |
shopt -s oil:all |
133 |
write -- |
134 |
# This is annoying |
135 |
write -- -- |
136 |
write done |
137 |
|
138 |
# this is a syntax error! Doh. |
139 |
write --- |
140 |
## status: 2 |
141 |
## STDOUT: |
142 |
|
143 |
-- |
144 |
done |
145 |
## END |
146 |
|
147 |
#### read flag usage |
148 |
read --lin |
149 |
echo status=$? |
150 |
|
151 |
read --line :var extra |
152 |
echo status=$? |
153 |
## STDOUT: |
154 |
status=2 |
155 |
status=2 |
156 |
## END |
157 |
|
158 |
#### read :x :y is allowed |
159 |
shopt --set parse_proc |
160 |
|
161 |
echo 'foo bar' | read :x :y |
162 |
echo x=$x y=$y |
163 |
|
164 |
proc p { |
165 |
# If these aren't here, it will LEAK because 'read' uses DYNAMIC SCOPE. |
166 |
# TODO: Change semantics of : to be enforce that a local exists too? |
167 |
var x = '' |
168 |
var y = '' |
169 |
echo 'spam eggs' | read x :y # OPTIONAL |
170 |
echo x=$x y=$y |
171 |
} |
172 |
p |
173 |
|
174 |
echo x=$x y=$y |
175 |
|
176 |
## STDOUT: |
177 |
x=foo y=bar |
178 |
x=spam y=eggs |
179 |
x=foo y=bar |
180 |
## END |
181 |
|
182 |
#### Idiom for returning 'read' |
183 |
shopt --set parse_proc |
184 |
|
185 |
proc p(out Ref) { |
186 |
#var tmp = '' |
187 |
|
188 |
# We can't do read :out in Oil. I think that's OK -- there's consistency in |
189 |
# using setref everywhere. |
190 |
echo foo | read :tmp |
191 |
setref out = tmp |
192 |
} |
193 |
p :z |
194 |
echo z=$z |
195 |
## STDOUT: |
196 |
z=foo |
197 |
## END |
198 |
|
199 |
#### read --line --with-eol |
200 |
shopt -s oil:upgrade |
201 |
|
202 |
# Hm this preserves the newline? |
203 |
seq 3 | while read --line { |
204 |
write line=$_line # implisict |
205 |
} |
206 |
write a b | while read --line --with-eol :myline { |
207 |
write --end '' line=$myline |
208 |
} |
209 |
## STDOUT: |
210 |
line=1 |
211 |
line=2 |
212 |
line=3 |
213 |
line=a |
214 |
line=b |
215 |
## END |
216 |
|
217 |
#### read --line --qsn |
218 |
read --line --qsn <<EOF |
219 |
'foo\n' |
220 |
EOF |
221 |
write --qsn -- "$_line" |
222 |
|
223 |
read --line --qsn <<EOF |
224 |
'foo\tbar hex=\x01 mu=\u{3bc}' |
225 |
EOF |
226 |
write --qsn --unicode u -- "$_line" |
227 |
|
228 |
echo '$' | read --line --qsn |
229 |
write --qsn -- "$_line" |
230 |
|
231 |
## STDOUT: |
232 |
'foo\n' |
233 |
'foo\tbar hex=\u{1} mu=\u{3bc}' |
234 |
'$' |
235 |
## END |
236 |
|
237 |
#### read --line --qsn accepts optional $'' |
238 |
|
239 |
# PROBLEM: is it limited to $' ? What about $3.99 ? |
240 |
# I think you just check for those 2 chars |
241 |
|
242 |
echo $'$\'foo\'' | read --line --qsn |
243 |
write -- "$_line" |
244 |
## STDOUT: |
245 |
foo |
246 |
## END |
247 |
|
248 |
#### read --line --with-eol --qsn |
249 |
|
250 |
# whitespace is allowed after closing single quote; it doesn't make a |
251 |
# difference. |
252 |
|
253 |
read --line --with-eol --qsn <<EOF |
254 |
'foo\n' |
255 |
EOF |
256 |
write --qsn -- "$_line" |
257 |
## STDOUT: |
258 |
'foo\n' |
259 |
## END |
260 |
|
261 |
#### read --qsn usage |
262 |
read --qsn << EOF |
263 |
foo |
264 |
EOF |
265 |
echo status=$? |
266 |
|
267 |
## STDOUT: |
268 |
status=2 |
269 |
## END |
270 |
|
271 |
#### read --all-lines |
272 |
seq 3 | read --all-lines :nums |
273 |
write --sep ' ' -- @nums |
274 |
## STDOUT: |
275 |
1 2 3 |
276 |
## END |
277 |
|
278 |
#### read --all-lines --with-eol |
279 |
seq 3 | read --all-lines --with-eol :nums |
280 |
write --sep '' -- @nums |
281 |
## STDOUT: |
282 |
1 |
283 |
2 |
284 |
3 |
285 |
## END |
286 |
|
287 |
#### read --all-lines --qsn --with-eol |
288 |
read --all-lines --qsn --with-eol :lines << EOF |
289 |
foo |
290 |
bar |
291 |
'one\ntwo' |
292 |
EOF |
293 |
write --sep '' -- @lines |
294 |
## STDOUT: |
295 |
foo |
296 |
bar |
297 |
one |
298 |
two |
299 |
## END |
300 |
|
301 |
#### read --all |
302 |
echo foo | read --all |
303 |
echo "[$_all]" |
304 |
|
305 |
echo bad > tmp.txt |
306 |
read --all :x < tmp.txt |
307 |
echo "[$x]" |
308 |
|
309 |
## STDOUT: |
310 |
[foo |
311 |
] |
312 |
[bad |
313 |
] |
314 |
## END |
315 |
|
316 |
#### read --line from directory is an error (EISDIR) |
317 |
mkdir -p ./dir |
318 |
read --line < ./dir |
319 |
echo status=$? |
320 |
## STDOUT: |
321 |
status=1 |
322 |
## END |
323 |
|
324 |
#### read --all from directory is an error (EISDIR) |
325 |
mkdir -p ./dir |
326 |
read --all < ./dir |
327 |
echo status=$? |
328 |
## STDOUT: |
329 |
status=1 |
330 |
## END |
331 |
|
332 |
#### read -0 is like read -r -d '' |
333 |
set -o errexit |
334 |
|
335 |
mkdir -p read0 |
336 |
cd read0 |
337 |
touch a\\b\\c\\d |
338 |
|
339 |
find . -type f -a -print0 | read -r -d '' name |
340 |
echo "[$name]" |
341 |
|
342 |
find . -type f -a -print0 | read -0 |
343 |
echo "[$REPLY]" |
344 |
|
345 |
## STDOUT: |
346 |
[./a\b\c\d] |
347 |
[./a\b\c\d] |
348 |
## END |
349 |
|
350 |
#### simple_test_builtin |
351 |
|
352 |
test -n "foo" |
353 |
echo status=$? |
354 |
|
355 |
test -n "foo" -a -n "bar" |
356 |
echo status=$? |
357 |
|
358 |
[ -n foo ] |
359 |
echo status=$? |
360 |
|
361 |
shopt --set oil:all |
362 |
shopt --unset errexit |
363 |
|
364 |
test -n "foo" -a -n "bar" |
365 |
echo status=$? |
366 |
|
367 |
[ -n foo ] |
368 |
echo status=$? |
369 |
|
370 |
test -z foo |
371 |
echo status=$? |
372 |
|
373 |
## STDOUT: |
374 |
status=0 |
375 |
status=0 |
376 |
status=0 |
377 |
status=2 |
378 |
status=2 |
379 |
status=1 |
380 |
## END |
381 |
|
382 |
#### long flags to test |
383 |
# no options necessary! |
384 |
|
385 |
test --dir / |
386 |
echo status=$? |
387 |
|
388 |
touch foo |
389 |
test --file foo |
390 |
echo status=$? |
391 |
|
392 |
test --exists / |
393 |
echo status=$? |
394 |
|
395 |
test --symlink foo |
396 |
echo status=$? |
397 |
|
398 |
test --typo foo |
399 |
echo status=$? |
400 |
|
401 |
## STDOUT: |
402 |
status=0 |
403 |
status=0 |
404 |
status=0 |
405 |
status=1 |
406 |
status=2 |
407 |
## END |
408 |
|
409 |
|
410 |
#### push-registers |
411 |
shopt --set oil:upgrade |
412 |
shopt --unset errexit |
413 |
|
414 |
status_code() { |
415 |
return $1 |
416 |
} |
417 |
|
418 |
[[ foo =~ (.*) ]] |
419 |
|
420 |
status_code 42 |
421 |
push-registers { |
422 |
status_code 43 |
423 |
echo status=$? |
424 |
|
425 |
[[ bar =~ (.*) ]] |
426 |
echo ${BASH_REMATCH[@]} |
427 |
} |
428 |
# WEIRD SEMANTIC TO REVISIT: push-registers is "SILENT" as far as exit code |
429 |
# This is for the headless shell, but hasn't been tested. |
430 |
# Better method: maybe we should provide a way of SETTING $? |
431 |
|
432 |
echo status=$? |
433 |
|
434 |
echo ${BASH_REMATCH[@]} |
435 |
## STDOUT: |
436 |
status=43 |
437 |
bar bar |
438 |
status=42 |
439 |
foo foo |
440 |
## END |
441 |
|
442 |
#### push-registers usage |
443 |
shopt --set parse_brace |
444 |
|
445 |
push-registers |
446 |
echo status=$? |
447 |
|
448 |
push-registers a b |
449 |
echo status=$? |
450 |
|
451 |
push-registers a b { # hm extra args are ignored |
452 |
echo hi |
453 |
} |
454 |
echo status=$? |
455 |
|
456 |
## STDOUT: |
457 |
status=2 |
458 |
status=2 |
459 |
hi |
460 |
status=0 |
461 |
## END |
462 |
|
463 |
|
464 |
#### module |
465 |
shopt --set oil:upgrade |
466 |
|
467 |
module 'main' || return 0 |
468 |
source $REPO_ROOT/spec/testdata/module/common.oil |
469 |
source $REPO_ROOT/spec/testdata/module/module1.oil |
470 |
## STDOUT: |
471 |
common |
472 |
module1 |
473 |
## END |
474 |
|
475 |
|
476 |
#### runproc |
477 |
shopt --set parse_proc |
478 |
|
479 |
f() { |
480 |
write -- f "$@" |
481 |
} |
482 |
proc p { |
483 |
write -- p "$@" |
484 |
} |
485 |
runproc f 1 2 |
486 |
echo status=$? |
487 |
|
488 |
runproc p 3 4 |
489 |
echo status=$? |
490 |
|
491 |
runproc invalid 5 6 |
492 |
echo status=$? |
493 |
|
494 |
runproc |
495 |
echo status=$? |
496 |
|
497 |
## STDOUT: |
498 |
f |
499 |
1 |
500 |
2 |
501 |
status=0 |
502 |
p |
503 |
3 |
504 |
4 |
505 |
status=0 |
506 |
status=1 |
507 |
status=2 |
508 |
## END |
509 |
|
510 |
#### runproc typed args |
511 |
shopt --set parse_brace parse_proc |
512 |
|
513 |
proc p { |
514 |
echo hi |
515 |
} |
516 |
|
517 |
# The block is ignored for now |
518 |
runproc p { |
519 |
echo myblock |
520 |
} |
521 |
## STDOUT: |
522 |
hi |
523 |
## END |
524 |
|
525 |
|
526 |
#### fopen |
527 |
shopt --set parse_brace parse_proc |
528 |
|
529 |
proc p { |
530 |
echo 'proc' |
531 |
} |
532 |
|
533 |
fopen >out.txt { |
534 |
p |
535 |
echo 'builtin' |
536 |
} |
537 |
|
538 |
cat out.txt |
539 |
|
540 |
echo --- |
541 |
|
542 |
fopen <out.txt { |
543 |
tac |
544 |
} |
545 |
|
546 |
# Awkward bash syntax, but we'll live with it |
547 |
fopen {left}>left.txt {right}>right.txt { |
548 |
echo 1 >& $left |
549 |
echo 1 >& $right |
550 |
|
551 |
echo 2 >& $left |
552 |
echo 2 >& $right |
553 |
|
554 |
echo 3 >& $left |
555 |
} |
556 |
|
557 |
echo --- |
558 |
comm -23 left.txt right.txt |
559 |
|
560 |
## STDOUT: |
561 |
proc |
562 |
builtin |
563 |
--- |
564 |
builtin |
565 |
proc |
566 |
--- |
567 |
3 |
568 |
## END |