Why Sponsor Oils? | source | all docs for version 0.26.0 | all versions | oils.pub
YSH extends the shell command language with a Python-like expression language.
Commands and expressions each have a lexer mode, which is an essential syntactic concept in YSH.
This doc lists the places where YSH switches between modes.
A main difference is whether you write strings like unquoted
or 'quoted'
,
and whether you write variables like $dollar
or unquoted
:
Description | Lexing Mode | String | Variable | Example |
---|---|---|---|---|
Shell-Like | Command | unquoted |
$dollar |
|
Python-like | Expression | 'quoted' |
unquoted |
|
More examples:
ls foo/bar # foo and bar are strings - command
var x = foo / bar # foo and bar are the names of variables - expression
And:
echo $filename.py # $filename is a var - command
var x = filename ++ '.py' # filename is a var - expression
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 call
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'
}