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