1 ## oils_failures_allowed: 3
2
3 #### append onto BashArray a=(1 2)
4 shopt -s parse_at
5 a=(1 2)
6 append '3 4' '5' (a)
7 argv.py "${a[@]}"
8
9 append -- 6 (a)
10 argv.py "${a[@]}"
11
12 ## STDOUT:
13 ['1', '2', '3 4', '5']
14 ['1', '2', '3 4', '5', '6']
15 ## END
16
17 #### append onto var a = :| 1 2 |
18 shopt -s parse_at parse_proc
19 var a = :| 1 2 |
20 append '3 4' '5' (a)
21 argv.py @a
22 ## STDOUT:
23 ['1', '2', '3 4', '5']
24 ## END
25
26 #### append onto var a = ['1', '2']
27 shopt -s parse_at parse_proc
28 var a = ['1', '2']
29 append '3 4' '5' (a)
30 argv.py @a
31 ## STDOUT:
32 ['1', '2', '3 4', '5']
33 ## END
34
35 #### append without typed arg
36 append a b
37 ## status: 3
38
39 #### append passed invalid type
40 s=''
41 append a b (s)
42 echo status=$?
43 ## status: 3
44
45 #### write --sep, --end, -n, varying flag syntax
46 shopt -s ysh:all
47 var a = %('a b' 'c d')
48 write @a
49 write .
50 write -- @a
51 write .
52
53 write --sep '' --end '' @a; write
54 write .
55
56 write --sep '_' -- @a
57 write --sep '_' --end $' END\n' -- @a
58
59 # with =
60 write --sep='_' --end=$' END\n' -- @a
61
62 write -n x
63 write -n y
64 write
65
66 ## STDOUT:
67 a b
68 c d
69 .
70 a b
71 c d
72 .
73 a bc d
74 .
75 a b_c d
76 a b_c d END
77 a b_c d END
78 xy
79 ## END
80
81 #### write --json
82 shopt --set ysh:upgrade
83
84 write --json u'\u{3bc}' x
85 write --json b'\yfe\yff' y
86
87 ## STDOUT:
88 "μ"
89 "x"
90 "��"
91 "y"
92 ## END
93
94 #### write --j8
95 shopt --set ysh:upgrade
96
97 write --j8 u'\u{3bc}' x
98 write --j8 b'\yfe\yff' y
99
100 ## STDOUT:
101 "μ"
102 "x"
103 b'\yfe\yff'
104 "y"
105 ## END
106
107 #### write -e not supported
108 shopt -s ysh:all
109 write -e foo
110 write status=$?
111 ## stdout-json: ""
112 ## status: 2
113
114 #### write syntax error
115 shopt -s ysh:all
116 write ---end foo
117 write status=$?
118 ## stdout-json: ""
119 ## status: 2
120
121 #### write --
122 shopt -s ysh:all
123 write --
124 # This is annoying
125 write -- --
126 write done
127
128 # this is a syntax error! Doh.
129 write ---
130 ## status: 2
131 ## STDOUT:
132
133 --
134 done
135 ## END
136
137 #### read flag usage
138 read --lin
139 echo status=$?
140
141 read --line :var extra
142 echo status=$?
143 ## STDOUT:
144 status=2
145 status=2
146 ## END
147
148 #### read (&x) is usage error
149
150 var x = null # allow no initialization
151 echo hello | read (&x)
152 echo status=$?
153
154 ## STDOUT:
155 status=2
156 ## END
157
158 #### read --raw-line
159
160 echo hi | read --raw-line
161 echo "reply=$_reply"
162 echo len=$[len(_reply)]
163
164 echo hi | read -r
165 if test "$REPLY" = "$_reply"; then
166 echo pass
167 fi
168
169 ## STDOUT:
170 reply=hi
171 len=2
172 pass
173 ## END
174
175 #### read --raw-line in a loop
176
177 write --end '' $'\na\nb\n\n' | while read --raw-line; do
178 pp test_ (_reply)
179 done
180
181 echo
182
183 write --end '' $'a\n\nb' | while read --raw-line; do
184 pp test_ (_reply)
185 done
186
187
188 ## STDOUT:
189 (Str) ""
190 (Str) "a"
191 (Str) "b"
192 (Str) ""
193
194 (Str) "a"
195 (Str) ""
196 (Str) "b"
197 ## END
198
199
200 #### read --raw-line --with-eol in a loop
201
202 write --end '' $'\na\nb\n\n' | while read --raw-line --with-eol; do
203 pp test_ (_reply)
204 done
205
206 echo
207
208 write --end '' $'a\n\nb' | while read --raw-line --with-eol; do
209 pp test_ (_reply)
210 done
211
212 ## STDOUT:
213 (Str) "\n"
214 (Str) "a\n"
215 (Str) "b\n"
216 (Str) "\n"
217
218 (Str) "a\n"
219 (Str) "\n"
220 (Str) "b"
221 ## END
222
223 #### Mixing read --raw-line with read -r
224
225 $SH $REPO_ROOT/spec/testdata/ysh-read-0.sh
226
227 ## STDOUT:
228 read -r
229 REPLY=1
230 REPLY=2
231
232 read --raw-line
233 _reply=1
234 _reply=2
235
236 Mixed
237 REPLY=1
238 REPLY=2
239 _reply=3
240 REPLY=4
241 ## END
242
243 #### read --raw-line --with-eol
244
245 $SH $REPO_ROOT/spec/testdata/ysh-read-1.sh
246
247 ## STDOUT:
248 reply=1
249 reply=2
250 reply=3
251 myline=a
252 myline=b
253 ## END
254
255 #### read --raw-line --j8
256
257 # TODO: is this similar to @() ? It reads j8 lines?
258 #
259 # But using a function is better?
260 #
261 # var x = fromJ8Line(_reply)
262 # var x = fromJson(_reply) # this is https://jsonlines.org
263
264 echo $'u\'foo\'' | read --raw-line --j8
265 write -- "$_reply"
266
267 ## STDOUT:
268 foo
269 ## END
270
271 #### echo builtin should disallow typed args - literal
272 shopt -s ysh:all
273 #shopt -p simple_echo
274
275 echo (42)
276 ## status: 2
277 ## STDOUT:
278 ## END
279
280 #### echo builtin should disallow typed args - variable
281 shopt -s ysh:all
282 #shopt -p simple_echo
283
284 var x = 43
285 echo (x)
286 ## status: 2
287 ## STDOUT:
288 ## END
289
290 #### read --all-lines
291 seq 3 | read --all-lines :nums
292 write --sep ' ' -- @nums
293 ## STDOUT:
294 1 2 3
295 ## END
296
297 #### read --all-lines --with-eol
298 seq 3 | read --all-lines --with-eol :nums
299 write --sep '' -- @nums
300 ## STDOUT:
301 1
302 2
303 3
304 ## END
305
306 #### Can simulate read --all-lines with a proc and value.Place
307
308 $SH $REPO_ROOT/spec/testdata/ysh-read-2.sh
309
310 ## STDOUT:
311 [
312 "1",
313 "2",
314 "3"
315 ]
316 ## END
317
318 #### read --all
319 echo foo | read --all
320 echo "[$_reply]"
321
322 echo bad > tmp.txt
323 read --all (&x) < tmp.txt
324 echo "[$x]"
325
326 ## STDOUT:
327 [foo
328 ]
329 [bad
330 ]
331 ## END
332
333 #### read --all from directory is an error (EISDIR)
334 mkdir -p ./dir
335 read --all < ./dir
336 echo status=$?
337 ## STDOUT:
338 status=1
339 ## END
340
341 #### read --num-bytes
342
343 echo ' a b ' | read --num-bytes 4; echo "reply=[$_reply]"
344 echo ' a b ' | read --num-bytes 5; echo "reply=[$_reply]"
345
346 echo ' a b ' | read --num-bytes 4 (&x); echo "x=[$x]"
347 echo ' a b ' | read --num-bytes 5 (&x); echo "x=[$x]"
348
349 ## STDOUT:
350 reply=[ a ]
351 reply=[ a b]
352 x=[ a ]
353 x=[ a b]
354 ## END
355
356 #### read -0 is like read -r -d ''
357 set -o errexit
358
359 mkdir -p read0
360 cd read0
361 touch a\\b\\c\\d
362
363 find . -type f -a -print0 | read -r -d '' name
364 echo "[$name]"
365
366 find . -type f -a -print0 | read -0
367 echo "[$REPLY]"
368
369 ## STDOUT:
370 [./a\b\c\d]
371 [./a\b\c\d]
372 ## END
373
374 #### read -0 myvar doesn't do anything with IFS
375
376 touch 'foo bar '
377 find -type f -print0 | read -0
378 echo "[$REPLY]"
379
380 find -type f -print0 | read -0 myvar
381 echo "[$myvar]"
382
383 ## STDOUT:
384 [./foo bar ]
385 [./foo bar ]
386 ## END
387
388 #### simple_test_builtin
389
390 test -n "foo"
391 echo status=$?
392
393 test -n "foo" -a -n "bar"
394 echo status=$?
395
396 [ -n foo ]
397 echo status=$?
398
399 shopt --set ysh:all
400 shopt --unset errexit
401
402 test -n "foo" -a -n "bar"
403 echo status=$?
404
405 [ -n foo ]
406 echo status=$?
407
408 test -z foo
409 echo status=$?
410
411 ## STDOUT:
412 status=0
413 status=0
414 status=0
415 status=2
416 status=2
417 status=1
418 ## END
419
420 #### long flags to test
421 # no options necessary!
422
423 test --dir /
424 echo status=$?
425
426 touch foo
427 test --file foo
428 echo status=$?
429
430 test --exists /
431 echo status=$?
432
433 test --symlink foo
434 echo status=$?
435
436 test --typo foo
437 echo status=$?
438
439 ## STDOUT:
440 status=0
441 status=0
442 status=0
443 status=1
444 status=2
445 ## END
446
447 #### test --true; test --false
448 shopt --set ysh:upgrade
449
450 for expr in (true, false, '', 'other') {
451 pp test_ (expr)
452
453 try {
454 test --true $[expr]
455 }
456 echo true=$[_error.code]
457
458 try {
459 test --false $[expr]
460 }
461 echo false=$[_error.code]
462 echo
463 }
464
465 ## STDOUT:
466 (Bool) true
467 true=0
468 false=1
469
470 (Bool) false
471 true=1
472 false=0
473
474 (Str) ""
475 true=1
476 false=1
477
478 (Str) "other"
479 true=1
480 false=1
481
482 ## END
483
484 #### More test --true --false
485 shopt --set ysh:upgrade
486
487 var d = {}
488
489 try {
490 test --true $[bool(d)]
491 }
492 echo dict=$[_error.code]
493
494 setvar d.key = 'val'
495
496 try {
497 test --true $[bool(d)]
498 }
499 echo dict=$[_error.code]
500
501 echo
502
503 if test --true $[bool(d)] && ! test -f / {
504 echo AndOr
505 }
506
507 ## STDOUT:
508 dict=1
509 dict=0
510
511 AndOr
512 ## END
513
514
515 #### Make sure [[ is not affected by --true --false
516
517 set +o errexit
518
519 $SH +o ysh:all -c '[[ --true ]]; echo dbracket=$?'
520 $SH +o ysh:all -c '[[ --false ]]; echo dbracket=$?'
521
522 $SH +o ysh:all -c '[[ --true true ]]; echo dbracket=$?'
523 echo "parse error $?"
524 $SH +o ysh:all -c '[[ --false false ]]; echo dbracket=$?'
525 echo "parse error $?"
526
527 ## STDOUT:
528 dbracket=0
529 dbracket=0
530 parse error 2
531 parse error 2
532 ## END
533
534 #### push-registers
535 shopt --set ysh:upgrade
536 shopt --unset errexit
537
538 status_code() {
539 return $1
540 }
541
542 [[ foo =~ (.*) ]]
543
544 status_code 42
545 push-registers {
546 status_code 43
547 echo status=$?
548
549 [[ bar =~ (.*) ]]
550 echo ${BASH_REMATCH[@]}
551 }
552 # WEIRD SEMANTIC TO REVISIT: push-registers is "SILENT" as far as exit code
553 # This is for the headless shell, but hasn't been tested.
554 # Better method: maybe we should provide a way of SETTING $?
555
556 echo status=$?
557
558 echo ${BASH_REMATCH[@]}
559 ## STDOUT:
560 status=43
561 bar bar
562 status=42
563 foo foo
564 ## END
565
566 #### push-registers usage
567 shopt --set parse_brace
568
569 push-registers
570 echo status=$?
571
572 push-registers a b
573 echo status=$?
574
575 push-registers a b { # hm extra args are ignored
576 echo hi
577 }
578 echo status=$?
579
580 ## STDOUT:
581 status=2
582 status=2
583 hi
584 status=0
585 ## END
586
587 #### redir
588 shopt --set parse_brace parse_proc
589
590 proc p {
591 echo 'proc'
592 }
593
594 redir >out.txt {
595 p
596 echo 'builtin'
597 }
598
599 cat out.txt
600
601 echo ---
602
603 redir <out.txt {
604 tac
605 }
606
607 # Awkward bash syntax, but we'll live with it
608 redir {left}>left.txt {right}>right.txt {
609 echo 1 >& $left
610 echo 1 >& $right
611
612 echo 2 >& $left
613 echo 2 >& $right
614
615 echo 3 >& $left
616 }
617
618 echo ---
619 comm -23 left.txt right.txt
620
621 ## STDOUT:
622 proc
623 builtin
624 ---
625 builtin
626 proc
627 ---
628 3
629 ## END
630
631 #### type(x)
632 echo $[type(1234)]
633 echo $[type('foo')]
634 echo $[type(false)]
635 echo $[type(1.234)]
636 echo $[type([])]
637 echo $[type({})]
638 echo $[type(null)]
639
640 shopt --set ysh:upgrade
641
642 func f() {
643 return (42)
644 }
645
646 echo $[type(f)]
647 echo $[type(len)]
648 echo $[type('foo'=>startsWith)]
649 echo $[type('foo'=>join)] # Type error happens later
650 echo $[type(1..<3)]
651 ## STDOUT:
652 Int
653 Str
654 Bool
655 Float
656 List
657 Dict
658 Null
659 Func
660 BuiltinFunc
661 BoundFunc
662 BoundFunc
663 Range
664 ## END
665
666 #### source ///osh/two.sh and $LIB_OSH
667
668 source ///osh/two.sh
669 echo status=$?
670
671 source $LIB_OSH/two.sh
672 echo status=$?
673
674 # errors
675 source ///
676 echo status=$?
677 source ///x
678 echo status=$?
679
680 ## STDOUT:
681 status=0
682 status=0
683 status=1
684 status=1
685 ## END