What Breaks When You Upgrade to YSH

Only a few things break when you put this at the top of a shell script:

shopt --set ysh:upgrade

This doc enumerates and explains them.

Table of Contents
Reasons for Upgrading
Syntax Changes
if ( ) and while ( ) take expressions, not subshell commands
@() is spliced command sub, not extended glob
r'c:\Users\' is a raw string, not joined strings
globs can't start with [
Unsupported
Extended Globs in Word Evaluation
More Quotes May Be Needed
With ysh:upgrade Options
Unconditionally
Summary
Appendix
Shell Functions vs. Procs
$EDITOR vs. ENV.EDITOR
Acknowledgments

Reasons for Upgrading

First, let's emphasize the good things that happen when you upgrade:

You can also use bin/osh indefinitely, in which case you don't need to read this doc. OSH is a highly compatible Unix shell.

Syntax Changes

Now onto the breakages. Most of them are unlikely, but worth noting.

if ( ) and while ( ) take expressions, not subshell commands

Code like if ( ls /tmp ) is valid shell, but it's almost always a misuse of the language. Parentheses mean subshell, not grouping as in C or Python.

In YSH:

No:

( cd /tmp; rm *.sh )

Yes:

forkwait {
  cd /tmp
  rm *.sh
}

Better:

cd /tmp {  # no process created
  rm *.sh
}
echo $PWD  # restored

(Option parse_paren is part of group ysh:upgrade.)

@() is spliced command sub, not extended glob

YSH doesn't have implicit word splitting, so we want @(seq 3) to be consistent with $(hostname). They're related in the same way that @myarray and $mystr are.

This means that @() is no longer extended glob, and ,() is an alias.

No:

echo @(*.cc|*.h)

Use this YSH alias instead:

echo ,(*.cc|*.h)

(Option parse_at is part of group ysh:upgrade.)

r'c:\Users\' is a raw string, not joined strings

The meaning of \ within string literals can be confusing, so YSH distinguishes them like this:

The prefix changes the meaning of commands like:

echo r'foo'
# => foo in YSH
# => rfoo in shell, because of implicit joining

Instead, write 'rfoo' if that's what you mean.

(Option parse_raw_string is part of group ysh:upgrade.)

globs can't start with [

In a command, the [ character starts a lazy arg list:

assert [42 === x]

In shell, [ is part of the glob syntax:

echo [ch]  # extremely rare pattern matching c or h

This is more common, and still works:

echo *.[ch]

You can still express the former by explicitly invoking glob('[ch]').

(Option parse_bracket is part of group ysh:upgrade.)

Unsupported

Extended Globs in Word Evaluation

Like regular globs, the extended glob syntax is used in two ways:

  1. Pattern matching
  2. Word Evaluation

Extended globs are not supported in Simple Word Evaluation, so you can't use them in the second way after upgrading.

You may want to use the find command or Egg expressions instead.

(Option simple_word_eval is part of group ysh:upgrade.)

More Quotes May Be Needed

With ysh:upgrade Options

Option parse_at. In YSH, @ is used to splice arrays. To pass a string @foo to a command, quote it like '@foo'.

Option parse_brace. Braces after commands start block arguments. To change to a directory named {, quote it like cd '{'.

Option parse_equals. A statement like x = 42 is a "bare assignment" or attribute. To pass = to a command x, quote it like x '='.

Unconditionally

There is very little reason to use commands like '=x' and 'proc', so you will likely never run into this!

Summary

This concludes the list of features that's broken when you upgrade from OSH to YSH. We tried to keep this list as small as possible.

There are other features that are discouraged, like $(( x + 1 )), (( i++ )), [[ $s =~ $pat ]], and ${s%%prefix}. These have better alternatives in the YSH expression language, but they can still be used. See YSH vs. Shell Idioms.

Also related: Known Differences Between OSH and Other Shells.

Appendix

Here are some notable non-breaking changes.

Shell Functions vs. Procs

Procs have truly local variables like Python and JavaScript. There's no dynamic scope rule, as with shell functions.

This is something to be aware of, but isn't technically a breakage because shell functions still work the same way in YSH.

$EDITOR vs. ENV.EDITOR

In YSH, env vars live in the ENV dict. So instead of $EDITOR, you should use $[ENV.EDITOR].

But doesn't break when you shopt --set ysh:upgrade, only when you use bin/ysh.

Acknowledgments

Thank you to ca2013 for reviewing this doc.

Generated on Wed, 20 Nov 2024 00:36:23 +0000