Why Sponsor Oils? | source | all docs for version 0.21.0 | all versions | oilshell.org
This is an essential syntactic concept in YSH.
YSH extends the shell command language with a Python-like expression language.
To implement that, the lexer enters "expression mode".
The key difference is that when lexing commands, unquoted is a string, while
$dollar is a variable:
ls /bin/str $myvar
On the other hand, when lexing expressions, 'quoted' is a string, while
unquoted is a variable:
var s = myfunc('str', myvar)
This doc lists the places where we switch modes.
Everything after = is parsed in expression mode:
var x = 42 + f(x)    # RHS of var/setvar
setvar x += g(y)
setvar x = obj.method()   
This includes bare assignments in Hay blocks:
Rule {
  x = 42 + a[i]
}
= and call keywordsLikewise, everything after = or :: is in expression mode:
= 42 + f(x)
Throw away the value:
call mylist->append(x)
for while if case:Expressions are surrounded by ( ):
for k, v in (mydict) { 
  echo "$k $v"
}
while (x > 0) {
  setvar x -= 1
}
if (x > 0) { 
  echo 'positive'
}
case (len(x)) {
  (1)    { echo one }
  (2)    { echo two }
  (else) { echo other }
}
The $[] construct converts an expression to a string:
echo $[42 + a[i]]
The @[] construct converts a list to an array of strings:
echo @[arrayfunc('three', 'four', f(x))]
Typed arguments are surrounded by ( ):
json write (['three', 'four'])
# =>
[ "three", "four" ]
Lazy arguments:
assert [42 === x]
Parameters aren't expressions, but they're parsed with the same lexer:
proc p(x, y) {    # what's between () is in expression mode
  echo "$x $y"    # back to command mode
}
func f(x) {
  return (x)
}
var myarray = :| /tmp/foo ${var} $(echo hi) @myarray |
Everything in between sigil pairs is in command mode:
var x = $(hostname | tr a-z A-Z) 
var y = @(seq 3)   # Split command sub
This is a command literal:
var b = ^(echo $PWD)
No:
echo '*.py'              # a literal string, not a glob
echo @[glob(*.py)]       # syntax error, * is an operator in 
                         # expression mode
var x = myfunc(*.py)     # ditto, syntax error
Yes:
echo *.py                # expanded as a glob
echo @[glob('*.py')]     # A literal string passed to the builtin
                         # glob function
var x = f('*.py')        # Just a string
var x = f(glob('*.py'))  # Now it's expanded
Another way to say this is that YSH works like Python:
from glob import glob
glob('*.py')             # this is a glob
os.listdir('*.py')       # no glob because it's not how listdir() works
Also note that YSH has a builtin operator that uses glob aka fnmatch()
syntax:
if (x ~~ '*.py') {
  echo 'Python'
}