1 # spec/ysh-case
2
3 ## our_shell: ysh
4 ## oils_failures_allowed: 0
5
6 #### case syntax, one line
7 const x = "header.h"
8 case (x) {
9 *.h | *.cc { echo C++ }
10 *.py { echo Python }
11 }
12
13 # not recommended, but it works
14 case (x) { header.h { echo header.h } * { echo other } }
15
16 ## status: 0
17 ## STDOUT:
18 C++
19 header.h
20 ## END
21
22 #### case syntax, multiline
23 const x = "hello.py"
24 case (x) {
25 *.h | *.cc {
26 echo C++
27 echo 2; echo 3
28 }
29 *.py {
30 echo \
31 Python
32 }
33 }
34 ## status: 0
35 ## STDOUT:
36 Python
37 ## END
38
39 #### case syntax, simple expressions
40 const x = 3
41 case (x) {
42 (3) { echo three }
43 (4) { echo four }
44 }
45 ## status: 0
46 ## STDOUT:
47 three
48 ## END
49
50 #### case syntax, complex expressions
51 const x = 3
52 case (x) {
53 (1 + 2) { echo three }
54 (2 + 2) { echo four }
55 }
56 ## STDOUT:
57 three
58 ## END
59
60 #### case semantics, no match
61 const x = 2
62 case (x) {
63 (3) { echo three }
64 (4) { echo four }
65 }
66 ## status: 0
67 ## STDOUT:
68 ## END
69
70 #### eggex as case arm
71 const x = "main.cc"
72 case (x) {
73 / dot* '.py' / {
74 echo Python
75 }
76 / dot* ('.cc' | '.h') / {
77 echo C++
78 }
79 }
80 ## STDOUT:
81 C++
82 ## END
83
84 #### eggex respects flags
85 const x = 'MAIN.PY'
86 case (x) {
87 / dot* '.py' ; i / {
88 echo Python
89 }
90 / dot* ('.cc' | '.h') / {
91 echo C++
92 }
93 }
94 ## STDOUT:
95 Python
96 ## END
97
98 #### empty case statement
99 const x = ""
100 case (x) { }
101 ## status: 0
102 ## STDOUT:
103 ## END
104
105 #### typed args
106 const x = "0"
107 case (x) {
108 (0) { echo int }
109 ("0") { echo string }
110 }
111
112 ## status: 0
113 ## STDOUT:
114 string
115 ## END
116
117 #### eggex capture
118 for name in foo/foo.py bar/bar.cc zz {
119 case (name) {
120 / '/f' <capture dot*> '.' / { echo "g0=$[_group(0)] g1=$[_group(1)]" }
121 / '/b' <capture dot*> '.' / { echo "g0=$[_group(1)] g1=$[_group(1)]" }
122 (else) { echo 'no match' }
123 }
124 }
125 ## status: 0
126 ## STDOUT:
127 g0=/foo. g1=oo
128 g0=ar g1=ar
129 no match
130 ## END
131
132 #### else case pattern
133 var x = 123
134 case (x) {
135 (else) { echo else matches all }
136 (123) { echo unreachable }
137 }
138 ## status: 0
139 ## STDOUT:
140 else matches all
141 ## END
142
143 #### expression evaluation shortcuts
144 var x = 123
145 case (x) {
146 (x) | (y) { echo no error }
147 }
148 ## status: 0
149 ## STDOUT:
150 no error
151 ## END
152
153 #### expression evaluation order
154 var x = 123
155 case (x) {
156 (y) | (x) { echo no error }
157 }
158 ## status: 1
159 ## STDOUT:
160 ## END
161
162 #### word evaluation shortcuts
163 var x = "abc"
164 case (x) {
165 $x | $y { echo no error }
166 }
167 ## status: 0
168 ## STDOUT:
169 no error
170 ## END
171
172 #### word evaluation order
173 var x = "abc"
174 case (x) {
175 $y | $x { echo no error }
176 }
177 ## status: 1
178 ## STDOUT:
179 ## END
180
181 #### only one branch is evaluated
182 var x = "42"
183 case (x) {
184 ('42') { echo a }
185 42 { echo b }
186 / '42' / { echo c }
187 (Str(40 + 2)) { echo d }
188
189 # even errors are ignored
190 (42 / 0) { echo no error }
191 }
192 ## status: 0
193 ## STDOUT:
194 a
195 ## END
196
197 #### stop on errors
198 var x = "42"
199 case (x) {
200 (42 / 0) { echo no error }
201
202 ('42') { echo a }
203 42 { echo b }
204 / '42' / { echo c }
205 (Str(40 + 2)) { echo d }
206 }
207 ## status: 3
208 ## STDOUT:
209 ## END
210
211 #### old and new case statements
212
213 for flag in -f -x {
214
215 # We can disallow this with shopt --unset parse_old_case, because the new
216 # case statement does everything the old one does
217 #
218 # bin/osh and shopt --set ysh:upgrade let you use both styles, but bin/ysh
219 # only lets you use the new style
220
221 case $flag in
222 -f|-d)
223 echo 'file'
224 ;;
225 *)
226 echo 'other'
227 ;;
228 esac
229
230 case (flag) {
231 -f|-d { echo 'file' }
232 * { echo 'other' }
233 }
234
235 echo --
236 }
237
238 ## STDOUT:
239 file
240 file
241 --
242 other
243 other
244 --
245 ## END