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