| 1 | ---
 | 
| 2 | default_highlighter: oils-sh
 | 
| 3 | ---
 | 
| 4 | 
 | 
| 5 | What Breaks When You Upgrade to YSH
 | 
| 6 | ===================================
 | 
| 7 | 
 | 
| 8 | Only a few things break when you put this at the top of a shell script:
 | 
| 9 | 
 | 
| 10 |     shopt --set ysh:upgrade
 | 
| 11 | 
 | 
| 12 | This doc enumerates and explains them.
 | 
| 13 | 
 | 
| 14 | <div id="toc">
 | 
| 15 | </div>
 | 
| 16 | 
 | 
| 17 | ## Reasons for Upgrading
 | 
| 18 | 
 | 
| 19 | First, let's emphasize the **good** things that happen when you upgrade:
 | 
| 20 | 
 | 
| 21 | - You can write `if (x > 0)` instead of `if [ "$x" -gt 0 ]`.
 | 
| 22 | - You can pass blocks to commands, like `cd /tmp { echo $PWD }`
 | 
| 23 | - [Simple Word Evaluation](simple-word-eval.html): You can write `$var` instead
 | 
| 24 |   of `"$var"`, and splice arrays with `@myarray`.
 | 
| 25 | - [Reliable Error Handling](error-handling.html) becomes the default.
 | 
| 26 | - ... and more
 | 
| 27 | 
 | 
| 28 | You can also use `bin/osh` indefinitely, in which case you don't need to read
 | 
| 29 | this doc.  [OSH]($xref:osh-language) is a highly compatible Unix shell.
 | 
| 30 | 
 | 
| 31 | ## Syntax Changes
 | 
| 32 | 
 | 
| 33 | Now onto the breakages.  Most of them are **unlikely**, but worth noting.
 | 
| 34 | 
 | 
| 35 | ### `if ( )` and `while ( )` take expressions, not subshell commands
 | 
| 36 | 
 | 
| 37 | Code like `if ( ls /tmp )` is valid shell, but it's almost always a misuse of
 | 
| 38 | the language.  Parentheses mean **subshell**, not grouping as in C or Python.
 | 
| 39 | 
 | 
| 40 | In YSH:
 | 
| 41 | 
 | 
| 42 | - Use `if (x > 0)` for true/false expressions
 | 
| 43 | - Use the `forkwait` builtin for subshells, which are uncommon.  (It's like
 | 
| 44 |   invoking the `fork` builtin, then the `wait` builtin.)
 | 
| 45 | 
 | 
| 46 | No:
 | 
| 47 | 
 | 
| 48 |     ( cd /tmp; rm *.sh )
 | 
| 49 | 
 | 
| 50 | Yes:
 | 
| 51 | 
 | 
| 52 |     forkwait {
 | 
| 53 |       cd /tmp
 | 
| 54 |       rm *.sh
 | 
| 55 |     }
 | 
| 56 | 
 | 
| 57 | Better:
 | 
| 58 | 
 | 
| 59 |     cd /tmp {  # no process created
 | 
| 60 |       rm *.sh
 | 
| 61 |     }
 | 
| 62 |     echo $PWD  # restored
 | 
| 63 | 
 | 
| 64 | 
 | 
| 65 | (Option `parse_paren` is part of group `ysh:upgrade`.)
 | 
| 66 | 
 | 
| 67 | ### `@()` is spliced command sub, not extended glob 
 | 
| 68 | 
 | 
| 69 | YSH doesn't have implicit word splitting, so we want `@(seq 3)` to be
 | 
| 70 | consistent with `$(hostname)`.  They're related in the same way that `@myarray`
 | 
| 71 | and `$mystr` are.
 | 
| 72 | 
 | 
| 73 | This means that `@()` is no longer extended glob, and `,()` is an alias.
 | 
| 74 | 
 | 
| 75 | No:
 | 
| 76 | 
 | 
| 77 |     echo @(*.cc|*.h)
 | 
| 78 | 
 | 
| 79 | Use this YSH alias instead:
 | 
| 80 | 
 | 
| 81 |     echo ,(*.cc|*.h)
 | 
| 82 | 
 | 
| 83 | (Option `parse_at` is part of group `ysh:upgrade`.)
 | 
| 84 | 
 | 
| 85 | ### `r'c:\Users\'` is a raw string, not joined strings
 | 
| 86 | 
 | 
| 87 | The meaning of `\` within string literals can be confusing, so YSH
 | 
| 88 | distinguishes them like this:
 | 
| 89 | 
 | 
| 90 | - `$'foo\n'` 
 | 
| 91 |   - The `$` prefix means that C-style backslash escapes are respected.
 | 
| 92 | - `r'c:\Users\'` 
 | 
| 93 |   - The `r` prefix means the backslashes are literal.
 | 
| 94 |   - In shell this is written `'c:\Users\'`.  YSH accepts this in command mode
 | 
| 95 |     for compatibility, but not expression mode.
 | 
| 96 | 
 | 
| 97 | The prefix **changes** the meaning of commands like:
 | 
| 98 | 
 | 
| 99 |     echo r'foo'
 | 
| 100 |     # => foo in YSH
 | 
| 101 |     # => rfoo in shell, because of implicit joining
 | 
| 102 | 
 | 
| 103 | Instead, write `'rfoo'` if that's what you mean.
 | 
| 104 | 
 | 
| 105 | (Option `parse_raw_string` is part of group `ysh:upgrade`.)
 | 
| 106 | 
 | 
| 107 | ### globs can't start with `[`
 | 
| 108 | 
 | 
| 109 | In a command, the `[` character starts a lazy arg list:
 | 
| 110 | 
 | 
| 111 |     assert [42 === x]
 | 
| 112 | 
 | 
| 113 | In shell, `[` is part of the glob syntax:
 | 
| 114 | 
 | 
| 115 |     echo [ch]  # extremely rare pattern matching c or h
 | 
| 116 | 
 | 
| 117 | This is more common, and still works:
 | 
| 118 | 
 | 
| 119 |     echo *.[ch]
 | 
| 120 | 
 | 
| 121 | You can still express the former by explicitly invoking `glob('[ch]')`.
 | 
| 122 | 
 | 
| 123 | 
 | 
| 124 | (Option `parse_bracket` is part of group `ysh:upgrade`.)
 | 
| 125 | 
 | 
| 126 | ## Unsupported
 | 
| 127 | 
 | 
| 128 | ### Extended Globs in Word Evaluation
 | 
| 129 | 
 | 
| 130 | Like regular globs, the extended glob syntax is used in two ways:
 | 
| 131 | 
 | 
| 132 | 1. Pattern matching 
 | 
| 133 |    - `case` 
 | 
| 134 |    - Bash boolean expressions like `[[ x == !(*.cc|*.h) ]]`
 | 
| 135 | 2. Word Evaluation
 | 
| 136 |    - commands like `cp !(*.cc|*.h) /tmp`
 | 
| 137 |    - arrays like `local -a myarray=( !(*.cc|*.h) )`
 | 
| 138 |    - Shell-style `for` loops
 | 
| 139 | 
 | 
| 140 | Extended globs are **not** supported in [Simple Word
 | 
| 141 | Evaluation](simple-word-eval.html), so you can't use them in the second way
 | 
| 142 | after upgrading.
 | 
| 143 | 
 | 
| 144 | You may want to use the `find` command or [Egg expressions](eggex.html)
 | 
| 145 | instead.
 | 
| 146 | 
 | 
| 147 | (Option `simple_word_eval` is part of group `ysh:upgrade`.)
 | 
| 148 | 
 | 
| 149 | ## More Quotes May Be Needed
 | 
| 150 | 
 | 
| 151 | ### With `ysh:upgrade` Options
 | 
| 152 | 
 | 
| 153 | Option `parse_at`.  In YSH, `@` is used to splice arrays.  To pass a string
 | 
| 154 | `@foo` to a command, quote it like `'@foo'`.
 | 
| 155 | 
 | 
| 156 | Option `parse_brace`.  Braces after commands start block arguments.  To change
 | 
| 157 | to a directory named `{`, quote it like `cd '{'`.
 | 
| 158 | 
 | 
| 159 | Option `parse_equals`.  A statement like `x = 42` is a "bare assignment" or
 | 
| 160 | attribute.  To pass `=` to a command `x`, quote it like `x '='`.
 | 
| 161 | 
 | 
| 162 | ### Unconditionally
 | 
| 163 | 
 | 
| 164 | - To avoid confusion with YSH's `=` operator, a word like `=x` can't be the first word in a command.
 | 
| 165 |   To invoke such commands, quote them like `'=x'`.
 | 
| 166 | - YSH has new keywords like `proc`, `const`, `var`, and `setvar`.  To use them
 | 
| 167 |   as command names, quote them like `'proc'`.
 | 
| 168 | 
 | 
| 169 | There is very little reason to use commands like `'=x'` and `'proc'`, so you
 | 
| 170 | will likely never run into this!
 | 
| 171 | 
 | 
| 172 | ## Summary
 | 
| 173 | 
 | 
| 174 | This concludes the list of features that's broken when you upgrade from OSH to
 | 
| 175 | YSH.  We tried to keep this list as small as possible.
 | 
| 176 | 
 | 
| 177 | There are other features that are **discouraged**, like `$(( x + 1 ))`, `(( i++
 | 
| 178 | ))`, `[[ $s =~ $pat ]]`, and `${s%%prefix}`.  These have better alternatives in
 | 
| 179 | the YSH expression language, but they can still be used.  See [YSH vs. Shell
 | 
| 180 | Idioms](idioms.html).
 | 
| 181 | 
 | 
| 182 | Also related: [Known Differences Between OSH and Other
 | 
| 183 | Shells](known-differences.html).
 | 
| 184 | 
 | 
| 185 | ## Appendix
 | 
| 186 | 
 | 
| 187 | ### Shell Functions vs. Procs
 | 
| 188 | 
 | 
| 189 | Procs have truly local variables like Python and JavaScript.  There's no
 | 
| 190 | [dynamic scope]($xref:dynamic-scope) rule, as with shell functions.
 | 
| 191 | 
 | 
| 192 | This is something to be aware of, but isn't technically a breakage because
 | 
| 193 | shell functions still work the same way in YSH.
 | 
| 194 | 
 | 
| 195 | ### Acknowledgments
 | 
| 196 | 
 | 
| 197 | Thank you to `ca2013` for reviewing this doc.
 | 
| 198 | 
 |