1 |
# Demonstrations for users. Could go in docs. |
2 |
|
3 |
#### GetValue scope and shopt --unset dynamic_scope |
4 |
|
5 |
f() { |
6 |
echo "sh x=$x" |
7 |
} |
8 |
|
9 |
proc p { |
10 |
echo "oil x=$x" |
11 |
} |
12 |
|
13 |
demo() { |
14 |
local x=dynamic |
15 |
f |
16 |
p |
17 |
|
18 |
shopt --unset dynamic_scope |
19 |
f |
20 |
} |
21 |
|
22 |
x=global |
23 |
demo |
24 |
echo x=$x |
25 |
|
26 |
## STDOUT: |
27 |
sh x=dynamic |
28 |
oil x=global |
29 |
sh x=global |
30 |
x=global |
31 |
## END |
32 |
|
33 |
|
34 |
#### SetValue scope and shopt --unset dynamic_scope |
35 |
f() { |
36 |
x=f |
37 |
} |
38 |
|
39 |
proc p { |
40 |
x=p |
41 |
} |
42 |
|
43 |
demo() { |
44 |
local x=stack |
45 |
echo x=$x |
46 |
echo --- |
47 |
|
48 |
f |
49 |
echo f x=$x |
50 |
|
51 |
x=stack |
52 |
p |
53 |
echo p x=$x |
54 |
|
55 |
shopt --unset dynamic_scope |
56 |
x=stack |
57 |
f |
58 |
echo funset x=$x |
59 |
} |
60 |
|
61 |
x=global |
62 |
demo |
63 |
|
64 |
echo --- |
65 |
echo x=$x |
66 |
|
67 |
## STDOUT: |
68 |
x=stack |
69 |
--- |
70 |
f x=f |
71 |
p x=stack |
72 |
funset x=stack |
73 |
--- |
74 |
x=global |
75 |
## END |
76 |
|
77 |
#### read scope (setref) |
78 |
read-x() { |
79 |
echo new | read x |
80 |
} |
81 |
demo() { |
82 |
local x=42 |
83 |
echo x=$x |
84 |
read-x |
85 |
echo x=$x |
86 |
} |
87 |
demo |
88 |
echo x=$x |
89 |
|
90 |
echo --- |
91 |
|
92 |
shopt --unset dynamic_scope # should NOT affect read |
93 |
demo |
94 |
echo x=$x |
95 |
|
96 |
## STDOUT: |
97 |
x=42 |
98 |
x=new |
99 |
x= |
100 |
--- |
101 |
x=42 |
102 |
x=new |
103 |
x= |
104 |
## END |
105 |
|
106 |
#### printf -v scope (setref) |
107 |
set-x() { |
108 |
printf -v x "%s" new |
109 |
} |
110 |
demo() { |
111 |
local x=42 |
112 |
echo x=$x |
113 |
set-x |
114 |
echo x=$x |
115 |
} |
116 |
demo |
117 |
echo x=$x |
118 |
|
119 |
echo --- |
120 |
|
121 |
shopt --unset dynamic_scope # should NOT affect read |
122 |
demo |
123 |
echo x=$x |
124 |
|
125 |
## STDOUT: |
126 |
x=42 |
127 |
x=new |
128 |
x= |
129 |
--- |
130 |
x=42 |
131 |
x=new |
132 |
x= |
133 |
## END |
134 |
|
135 |
#### ${undef=a} and shopt --unset dynamic_scope |
136 |
|
137 |
set-x() { |
138 |
: ${x=new} |
139 |
} |
140 |
demo() { |
141 |
local x |
142 |
echo x=$x |
143 |
set-x |
144 |
echo x=$x |
145 |
} |
146 |
|
147 |
demo |
148 |
echo x=$x |
149 |
|
150 |
echo --- |
151 |
|
152 |
# Now this IS affected? |
153 |
shopt --unset dynamic_scope |
154 |
demo |
155 |
echo x=$x |
156 |
## STDOUT: |
157 |
x= |
158 |
x=new |
159 |
x= |
160 |
--- |
161 |
x= |
162 |
x= |
163 |
x= |
164 |
## END |
165 |
|
166 |
#### declare -p respects it |
167 |
__g=G |
168 |
show-vars() { |
169 |
local __x=X |
170 |
declare -p | grep '__' |
171 |
echo status=$? |
172 |
|
173 |
echo - |
174 |
declare -p __y | grep '__' |
175 |
echo status=$? |
176 |
} |
177 |
|
178 |
demo() { |
179 |
local __y=Y |
180 |
|
181 |
show-vars |
182 |
echo --- |
183 |
shopt --unset dynamic_scope |
184 |
show-vars |
185 |
} |
186 |
|
187 |
demo |
188 |
|
189 |
## STDOUT: |
190 |
declare -- __g=G |
191 |
declare -- __x=X |
192 |
declare -- __y=Y |
193 |
status=0 |
194 |
- |
195 |
declare -- __y=Y |
196 |
status=0 |
197 |
--- |
198 |
declare -- __g=G |
199 |
declare -- __x=X |
200 |
status=0 |
201 |
- |
202 |
status=1 |
203 |
## END |
204 |
|
205 |
|
206 |
|
207 |
#### unset composes because it uses dynamic scope (even in Oil) |
208 |
shopt -s oil:all |
209 |
|
210 |
proc unset-two { |
211 |
unset $1 |
212 |
unset $2 |
213 |
} |
214 |
|
215 |
demo() { |
216 |
local x=X |
217 |
local y=Y |
218 |
|
219 |
echo "x=$x y=$y" |
220 |
|
221 |
unset-two x y |
222 |
|
223 |
shopt --unset nounset |
224 |
echo "x=$x y=$y" |
225 |
} |
226 |
|
227 |
demo |
228 |
## STDOUT: |
229 |
x=X y=Y |
230 |
x= y= |
231 |
## END |
232 |
|
233 |
|
234 |
#### SetLocalShopt constructs |
235 |
|
236 |
f() { |
237 |
(( x = 42 )) |
238 |
} |
239 |
demo() { |
240 |
f |
241 |
echo x=$x |
242 |
} |
243 |
|
244 |
demo |
245 |
|
246 |
echo --- |
247 |
|
248 |
shopt --unset dynamic_scope |
249 |
|
250 |
unset x |
251 |
|
252 |
demo |
253 |
|
254 |
echo --- global |
255 |
echo x=$x |
256 |
## STDOUT: |
257 |
x=42 |
258 |
--- |
259 |
x= |
260 |
--- global |
261 |
x= |
262 |
## END |
263 |
|
264 |
|
265 |
#### shell assignments 'neutered' inside 'proc' |
266 |
|
267 |
# They can't mutate globals or anything higher on the stack |
268 |
|
269 |
proc p { |
270 |
g=PROC |
271 |
export e=PROC |
272 |
} |
273 |
|
274 |
f() { |
275 |
g=SH |
276 |
export e=SH |
277 |
} |
278 |
|
279 |
e=E |
280 |
g=G |
281 |
p |
282 |
echo e=$e g=$g |
283 |
|
284 |
p |
285 |
echo e=$e g=$g |
286 |
|
287 |
f |
288 |
echo e=$e g=$g |
289 |
|
290 |
## STDOUT: |
291 |
e=E g=G |
292 |
e=E g=G |
293 |
e=SH g=SH |
294 |
## END |
295 |
|
296 |
#### setvar still allows setting globals |
297 |
|
298 |
proc p { |
299 |
setvar new_global = 'p' |
300 |
setvar g = 'p' |
301 |
} |
302 |
|
303 |
var g = 'G' |
304 |
|
305 |
p |
306 |
|
307 |
echo g=$g new_global=$new_global |
308 |
## STDOUT: |
309 |
g=p new_global=p |
310 |
## END |
311 |
|
312 |
#### setref with :out param |
313 |
|
314 |
# The name is mangled with : so you can't use it |
315 |
proc append(:s, suffix) { |
316 |
setref s = "$s-$suffix" |
317 |
} |
318 |
|
319 |
proc set-it(:s, val) { |
320 |
#pp cell __s |
321 |
setref s = "foo-$val" |
322 |
} |
323 |
|
324 |
proc demo { |
325 |
var s = 'abc' |
326 |
var t = 'def' |
327 |
set-it :s SS |
328 |
set-it :t TT |
329 |
|
330 |
echo $s |
331 |
echo $t |
332 |
} |
333 |
|
334 |
demo |
335 |
|
336 |
## STDOUT: |
337 |
foo-SS |
338 |
foo-TT |
339 |
## END |
340 |
|
341 |
#### setref without :out param |
342 |
proc set-it(:s, val) { |
343 |
setref val = 'oops' |
344 |
} |
345 |
|
346 |
var s = 'abc' |
347 |
set-it :s SS |
348 |
echo $s |
349 |
|
350 |
## status: 1 |
351 |
## STDOUT: |
352 |
## END |
353 |
|
354 |
#### setref: syntax without pgen2 using open proc |
355 |
|
356 |
# This is kind of what we compile to. Ref params get an extra __ prefix? then |
357 |
# that means you can't really READ them either? I think that's OK. |
358 |
|
359 |
# At call time, param binding time: |
360 |
# If the PARAM has a colon prefix: |
361 |
# Assert that the ARG has a colon prefix. Don't remove it. |
362 |
# Set the cell.nameref flag. |
363 |
# |
364 |
# At Setref time: |
365 |
# Check that it's cell.nameref. |
366 |
# Add extra : to lvalue.{Named,Indexed,Keyed} and perform it. |
367 |
# |
368 |
# The __ avoids the nameref cycle check. |
369 |
# And we probably disallow reading from the ref. That's OK. The caller can |
370 |
# pass it in as a regular value! |
371 |
|
372 |
proc set-it { |
373 |
local -n __s=$1 # nameref flag needed with setref |
374 |
local val=$2 |
375 |
|
376 |
# well this part requires pgen2 |
377 |
setref s = "foo-$val" |
378 |
} |
379 |
|
380 |
var s = 'abc' |
381 |
var t = 'def' |
382 |
set-it s SS |
383 |
set-it t TT # no colon here |
384 |
echo $s |
385 |
echo $t |
386 |
|
387 |
## STDOUT: |
388 |
foo-SS |
389 |
foo-TT |
390 |
## END |
391 |
|
392 |
#### setref a[i] |
393 |
|
394 |
# You can do this in bash/mksh. See nameref! |
395 |
|
396 |
proc set1(:a, item) { |
397 |
setref a[1] = item |
398 |
} |
399 |
|
400 |
var a = %(one two three) |
401 |
var myarray = %(a b c) |
402 |
|
403 |
set1 :a zzz |
404 |
set1 :myarray z |
405 |
|
406 |
shopt --set oil:basic |
407 |
#write -- @a |
408 |
write -- @myarray |
409 |
|
410 |
## STDOUT: |
411 |
a |
412 |
z |
413 |
c |
414 |
## END |