OILS / doc / quirks.md View on Github | oilshell.org

126 lines, 78 significant
1---
2default_highlighter: oils-sh
3---
4
5OSH Quirks
6==========
7
8This document describes corner cases in OSH.
9
10Related: [Known Differences](known-differences.html).
11
12<div id="toc">
13</div>
14
15## For Bash Compatibility
16
17### The meaning of `()` on the RHS
18
19In Oils, **values** are tagged with types like `Str` and `AssocArray`, as
20opposed to the *locations* of values (cells).
21
22This statement binds an empty indexed array to the name `x`:
23
24 x=() # indexed by integers
25
26**Quirk**: When it's clear from the context, `()` means an empty
27**associative** array:
28
29 declare -A x=() # indexed by strings, because of -A
30
31This only applies when the array is empty. Otherwise the type is determined by
32the literal:
33
34 declare x=(one two) # indexed array
35 declare x=(['k']=v) # associative array
36
37Redundant but OK:
38
39 declare -a x=(one two) # indexed array
40 declare -A x=(['k']=v) # associative array
41
42Errors:
43
44 declare -A x=(one two) # inconsistent
45 declare -a x=(['k']=v) # inconsistent
46
47## Interactive Shell
48
49### With job control, the DEBUG trap is disabled for the last part of a pipeline
50
51First, some background. These two shell features are fundamentally
52incompatible:
53
54- Job control: e.g. putting a pipeline in a process group, so it can be
55 suspended and cancelled all at once.
56- `shopt -s lastpipe` semantics: the last part of a pipeline can (sometimes) be
57 run in the current shell.
58 - [OSH]($xref) uses it by default because it makes `echo hi | read myvar` work. So
59 [OSH]($xref) is like [zsh]($xref), but unlike [bash](xref).
60
61As evidence of this incompatibility, note that:
62
63- [bash]($xref) simply ignores the `shopt -s lastpipe` setting in job control
64 shells
65- [zsh]($xref) doesn't allow you to suspend some pipelines
66
67---
68
69Now that we have that background, note that there's is a **third** feature that
70interacts: the `DEBUG` trap.
71
72[OSH]($xref) emulates the [bash]($xref) `DEBUG` trap, which runs before "leaf"
73commands like `echo hi`, `a=b`, etc.
74
75If we run this trap before the last part of a pipeline, **and** that part is
76run in the current shell (`lastpipe`), then the DEBUG trap makes an existing
77race condition worse.
78
79For example, in
80
81 echo hi | cat
82
83there's nothing stopping `echo hi` from finishing before `cat` is even started,
84which means that `cat` can't join the process group of the leader.
85
86So we simply disable the `DEBUG` trap for the last part of the pipeline, but
87**only** when job control is enabled. This won't affect debugging batch
88programs.
89
90Related issues in other shells:
91
92- bash: <https://superuser.com/questions/1084406/chained-pipes-in-bash-throws-operation-not-permitted>
93- fish: <https://github.com/fish-shell/fish-shell/issues/7474>
94
95
96<!--
97
98### errexit message and optimized subshells
99
100For all shells:
101
102 sh -c 'date'
103
104gets rewritten into:
105
106 sh -c 'exec date'
107
108That is, they **reuse the parent process**.
109
110Most shells don't print any diagnostic info when `errexit` is on. However, YSH
111does:
112
113 osh -o errexit -c 'false'
114 [ -c flag ]:1: fatal: Exiting with status 1
115
116`false` is a builtin rather than an external process, so YSH can print that
117message. But when running an external process, the message is lost:
118
119 osh -o errexit -c 'env false'
120 (silently fails with code 1)
121-->
122
123## Related
124
125- The doc on [warts](warts.html) relates to YSH.
126