| 1 | ---
|
| 2 | in_progress: yes
|
| 3 | default_highlighter: oils-sh
|
| 4 | ---
|
| 5 |
|
| 6 | Global Shell Options: Turning OSH into YSH
|
| 7 | ==========================================
|
| 8 |
|
| 9 |
|
| 10 | This document describes global shell options, which look like this:
|
| 11 |
|
| 12 | shopt --set strict_backslash # YSH style
|
| 13 | shopt --set ysh:upgrade # A whole group of options
|
| 14 | set -o errexit # Bourne shell style
|
| 15 |
|
| 16 | They can affect parsing or execution, and are used to gradually turn the
|
| 17 | [OSH]($xref:OSH) into the [YSH]($xref:YSH).
|
| 18 |
|
| 19 | For example, YSH doesn't have word splitting on whitespace. Instead, it use
|
| 20 | [Simple Word Evaluation](simple-word-eval.html). (Blog: [Oil Doesn't Require
|
| 21 | Quoting
|
| 22 | Everywhere](https://www.oilshell.org/blog/2021/04/simple-word-eval.html)). (Until 2023, YSH was called the "Oil language".)
|
| 23 |
|
| 24 | This isn't the **only** use for options, but it's an important one.
|
| 25 |
|
| 26 | <div id="toc">
|
| 27 | </div>
|
| 28 |
|
| 29 | ## What Every User Should Know (2 minutes)
|
| 30 |
|
| 31 | When you run `bin/osh`, the **option groups** `strict:all` and `ysh:upgrade` are
|
| 32 | "canned settings" that relieve you of having to know about dozens of shell
|
| 33 | options.
|
| 34 |
|
| 35 | Running `bin/ysh` is equivalent to using `shopt --set ysh:all` in `bin/osh`.
|
| 36 |
|
| 37 | Let's look at three examples.
|
| 38 |
|
| 39 | ### Strict
|
| 40 |
|
| 41 | If you put this line at the top of your shell script, it will still **run under
|
| 42 | other shells**, but OSH will act as sort of a "runtime linter":
|
| 43 |
|
| 44 | # Abort on more errors, but fixes will still be compatible
|
| 45 | shopt -s strict:all 2>/dev/null || true
|
| 46 |
|
| 47 | ### Upgrade
|
| 48 |
|
| 49 | If you want to upgrade a script, and don't care about running under other
|
| 50 | shells, use this:
|
| 51 |
|
| 52 | # Start enabling YSH syntax and semantics
|
| 53 | shopt --set ysh:upgrade
|
| 54 |
|
| 55 | This second line may break a few things, but is designed to be an easy upgrade.
|
| 56 | See [What Breaks When You Upgrade to YSH](upgrade-breakage.html).
|
| 57 |
|
| 58 | ### YSH
|
| 59 |
|
| 60 | If you're writing a new script, you can use `bin/ysh` to get **all**
|
| 61 | enhancements. Typically you use a shebang line like this:
|
| 62 |
|
| 63 | #!/usr/bin/env ysh
|
| 64 |
|
| 65 | That's all most users need to know. For more details, see the wiki page:
|
| 66 | [Gradually Upgrading Shell to Oil]($wiki).
|
| 67 |
|
| 68 | ## Using Shell Options
|
| 69 |
|
| 70 | There are several different ways of using shell options.
|
| 71 |
|
| 72 | ### Preferred Style
|
| 73 |
|
| 74 | YSH has **long flags** for readability, which are preferred:
|
| 75 |
|
| 76 | shopt --set errexit
|
| 77 | shopt --unset errexit
|
| 78 |
|
| 79 | It also allows **scoped** options:
|
| 80 |
|
| 81 | shopt --unset errexit {
|
| 82 | false # non-zero status ignored
|
| 83 | ls /bad
|
| 84 | }
|
| 85 | false # original setting restored
|
| 86 |
|
| 87 | ### Bourne Shell Style
|
| 88 |
|
| 89 | For compatibility, these styles works in YSH:
|
| 90 |
|
| 91 | set -e # abort script on non-zero exit exit code
|
| 92 | set +e # turn it off
|
| 93 |
|
| 94 | set -o errexit # a more readable version of the above
|
| 95 | set +o errexit
|
| 96 |
|
| 97 | [Bash]($xref:bash)-style option with `shopt`:
|
| 98 |
|
| 99 | shopt -s nullglob # turn it on
|
| 100 | shopt -u nullglob # turn it off
|
| 101 |
|
| 102 | ### Setting Options Via Command Line Flags
|
| 103 |
|
| 104 | You typically invoke the `shopt` builtin at the top of a script, but you
|
| 105 | can also set options at the command line:
|
| 106 |
|
| 107 | osh -O errexit -c 'shopt -p -o' # turn on Bourne option
|
| 108 | osh +O errexit -c 'shopt -p -o' # turn off Bourne option
|
| 109 |
|
| 110 | osh -O strict_tilde -c 'shopt -p' # turn on YSH option
|
| 111 | osh +O strict_tilde -c 'shopt -p' # turn off YSH option
|
| 112 |
|
| 113 | ### Inspecting Option State
|
| 114 |
|
| 115 | Shell has many ways to do this, like:
|
| 116 |
|
| 117 | set -o # print all Bourne shell options
|
| 118 | shopt -p # print all bash options
|
| 119 | shopt -p nullglob failglob # print selected options
|
| 120 | shopt -p ysh:upgrade # print options in the given group
|
| 121 |
|
| 122 | TODO: YSH should enable `shopt --print` for all options. It should have a flat
|
| 123 | list.
|
| 124 |
|
| 125 | ## Kinds of Options, With Examples
|
| 126 |
|
| 127 | *Option groups* like `ysh:upgrade` are baked into the interpreter. What follows
|
| 128 | is an informal list of *kinds* of options, which are different categorization:
|
| 129 |
|
| 130 | - Groups: How much of YSH do you want to use?
|
| 131 | - Kinds: Does this option affect parsing behavior, runtime behavior, or
|
| 132 | something else?
|
| 133 |
|
| 134 | ### Naming Conventions
|
| 135 |
|
| 136 | - `parse_*`: Change parsing.
|
| 137 | - enable new features: `parse_at`, `parse_equals`.
|
| 138 | - turn off to reject bad or old code: `parse_backticks`, `parse_backslash`,
|
| 139 | `parse_dollar`.
|
| 140 | - `strict_*`: Fail at runtime instead of ignoring the bug like bash.
|
| 141 | - `${#s}` on invalid unicode is a runtime error.
|
| 142 | - `~typo` is a runtime error.
|
| 143 | - `simple_*`: Break things to improve style.
|
| 144 | - `simple_eval_builtin`, `simple_echo`.
|
| 145 | - `simple_word_eval` is the most aggressive
|
| 146 |
|
| 147 | ### Strict Options Produce More Errors
|
| 148 |
|
| 149 | These options produce more **programming errors**. Importantly, the resulting
|
| 150 | program is still compatible with other shells.
|
| 151 |
|
| 152 | For example, `shopt -s strict_array` produces runtime errors when you confuse
|
| 153 | strings and arrays. After you fix these problems, your program will still run
|
| 154 | correctly under `bash`.
|
| 155 |
|
| 156 | In contrast, if you set `shopt -s simple_word_eval` (an option that doesn't
|
| 157 | start with `strict_`), the semantics of your program have changed, and you can
|
| 158 | **no longer** run it under other shells. It's considered an "YSH option": by
|
| 159 | setting it, you're using parts of YSH.
|
| 160 |
|
| 161 | ### Parse Options Change Syntax
|
| 162 |
|
| 163 | Options that affect parsing start with `parse_`. For example, `shopt -s
|
| 164 | parse_at` enables **splicing** with the `@` character:
|
| 165 |
|
| 166 | var words = :| ale bean |
|
| 167 | write -- @words
|
| 168 | # =>
|
| 169 | # ale
|
| 170 | # bean
|
| 171 |
|
| 172 | and inline function calls:
|
| 173 |
|
| 174 | write -- @[split('ale bean')]
|
| 175 | # =>
|
| 176 | # ale
|
| 177 | # bean
|
| 178 |
|
| 179 | As another example, `shopt --set parse_brace` takes over the `{ }` characters.
|
| 180 | Specifically, it does three things:
|
| 181 |
|
| 182 | 1. Allow builtins like `cd` to take a block (discussed in a [Zulip
|
| 183 | thread](https://oilshell.zulipchat.com/#narrow/stream/121540-oil-discuss/topic/cd.20now.20takes.20a.20Ruby-like.20block))
|
| 184 | 2. Control flow like `if`, `case`, `for`, and `while/until`, use curly brace
|
| 185 | delimiters instead of `then/fi`, `do/done`, etc. See below.
|
| 186 | 3. To remove confusion, braces must be balanced inside a word. echo `foo{` is
|
| 187 | an error. It has to be `echo foo\{` or `echo 'foo{'`.
|
| 188 | - In a correct brace expansion, they're always balanced: `{pea,coco}nut`
|
| 189 | - This is so that the syntax errors are better when you forget a space.
|
| 190 |
|
| 191 | <!--
|
| 192 | Test cases start here: <https://github.com/oilshell/oil/blob/master/spec/oil-options.test.sh#L257>
|
| 193 | -->
|
| 194 |
|
| 195 | Here's idiomatic YSH syntax after `parse_brace`:
|
| 196 |
|
| 197 | cd /tmp {
|
| 198 | echo $PWD
|
| 199 | }
|
| 200 |
|
| 201 | if test -d foo {
|
| 202 | echo 'dir'
|
| 203 | } elif test -f foo {
|
| 204 | echo 'file'
|
| 205 | } else {
|
| 206 | echo 'neither'
|
| 207 | }
|
| 208 |
|
| 209 | # Single line statements are supported:
|
| 210 | if test -d / { echo 'dir' } else { echo 'nope' }
|
| 211 |
|
| 212 | while true {
|
| 213 | echo hi
|
| 214 | break
|
| 215 | }
|
| 216 |
|
| 217 | # Loop over words
|
| 218 | for x in ale bean *.sh {
|
| 219 | echo $x
|
| 220 | }
|
| 221 |
|
| 222 | # Replace 'in' with {, and 'esac' with }
|
| 223 | case $x {
|
| 224 | *.py)
|
| 225 | echo python
|
| 226 | ;;
|
| 227 | *.sh)
|
| 228 | echo shell
|
| 229 | ;;
|
| 230 | }
|
| 231 |
|
| 232 | What's the motivation for this? Mainly familiarity: I hear a lot of feedback
|
| 233 | that nobody can remember how to write if statements in shell. See [The
|
| 234 | Simplest Explanation of
|
| 235 | Oil](//www.oilshell.org/blog/2020/01/simplest-explanation.html).
|
| 236 |
|
| 237 | <!--
|
| 238 |
|
| 239 | There are also **expression** variants of these constructs:
|
| 240 |
|
| 241 | if (x > 0) {
|
| 242 | echo hi
|
| 243 | }
|
| 244 |
|
| 245 | while (x > 0) {
|
| 246 | echo hi
|
| 247 | }
|
| 248 |
|
| 249 | (`for` and `case` to come later.)
|
| 250 |
|
| 251 | -->
|
| 252 |
|
| 253 |
|
| 254 | ### Runtime Options Change Behavior
|
| 255 |
|
| 256 | - `simple_echo`. Changes the flags accepted by the `echo` builtin, and style of flag parsing.
|
| 257 | See the `Builtins > echo` below.
|
| 258 | - `simple_word_eval`. Word evaluation consists of one stage rather than three:
|
| 259 | - No word splitting or empty elision. (In other words, arity isn't data-dependent.)
|
| 260 | - Static globbing, but no dynamic globbing. (In other words, data isn't re-parsed as code.)
|
| 261 | - This option is intended to be implemented by other shells.
|
| 262 |
|
| 263 | TODO: copy examples from spec tests
|
| 264 |
|
| 265 | echo $dir/*.py
|
| 266 |
|
| 267 | - `command_sub_errexit`. A error in a command sub can cause the **parent
|
| 268 | shell** to exit fatally. Also see `inherit_errexit` and `strict_errexit`.
|
| 269 |
|
| 270 | ## List of Options
|
| 271 |
|
| 272 | ### Selected Options
|
| 273 |
|
| 274 | `strict_arith`. Strings that don't look like integers cause a fatal error in
|
| 275 | arithmetic expressions.
|
| 276 |
|
| 277 | `strict_argv`. Empty `argv` arrays are disallowed (because there's no
|
| 278 | practical use for them). For example, the second statement in `x=''; $x`
|
| 279 | results in a fatal error.
|
| 280 |
|
| 281 | `strict_array`. No implicit conversions between string an array. In other
|
| 282 | words, turning this on gives you a "real" array type.
|
| 283 |
|
| 284 | `strict_control_flow`. `break` and `continue` outside of a loop are fatal
|
| 285 | errors.
|
| 286 |
|
| 287 | `simple_eval_builtin`. The `eval` builtin takes exactly **one** argument. It
|
| 288 | doesn't concatenate its arguments with spaces, or accept zero arguments.
|
| 289 |
|
| 290 | `strict_word_eval`. More word evaluation errors are fatal.
|
| 291 |
|
| 292 | - String slices with negative arguments like `${s: -1}` and `${s: 1 : -1}`
|
| 293 | result in a fatal error. (NOTE: In array slices, negative start indices are
|
| 294 | allowed, but negative lengths are always fatal, regardless of
|
| 295 | `strict_word_eval`.)
|
| 296 | - UTF-8 decoding errors are fatal when computing lengths (`${#s}`) and slices.
|
| 297 |
|
| 298 | For options affecting exit codes, see the [error handling
|
| 299 | doc](error-handling.html).
|
| 300 |
|
| 301 | ### Complete List
|
| 302 |
|
| 303 | See the [Chapter on Global Shell Options](ref/chap-option.html) in the
|
| 304 | reference.
|
| 305 |
|
| 306 | ## FAQ: Aren't Global Variables Bad?
|
| 307 |
|
| 308 | Options are technically globals, but YSH controls them in 2 ways:
|
| 309 |
|
| 310 | 1. It has scoped mutation with Ruby-like [blocks](proc-block-func.html).
|
| 311 | - Example: `shopt --unset errexit { false }`
|
| 312 | 2. Like all Bourne shells, YSH uses process-based concurrency. It doesn't have
|
| 313 | shared memory.
|
| 314 |
|
| 315 | ## Related Documents
|
| 316 |
|
| 317 | - Up: [Interpreter State](interpreter-state.html), which is under construction
|
| 318 |
|