source | all docs for version 0.8.0 | all versions | oilshell.org
Warning: Work in progress! Leave feedback on Zulip or Github if you'd like this doc to be updated.
This doc describes every aspect of Oil briefly. It underlies the help
builtin, and is indexed by keywords.
Navigate it with the index of Oil help topics.
This section describes how to use the Oil binary.
bin/oil
UsageUsage: oil [OPTION]... SCRIPT [ARG]...
oil [OPTION]... -c COMMAND [ARG]...
bin/oil
is the same as bin/osh
with a the oil:all
option group set. So
bin/oil
also accepts shell flags.
oil -c 'echo hi'
oil myscript.oil
echo 'echo hi' | oil
Usage: oil.ovm MAIN_NAME [ARG]...
MAIN_NAME [ARG]...
oil.ovm behaves like busybox. If it's invoked through a symlink, e.g. 'osh', then it behaves like that binary. Otherwise the binary name can be passed as the first argument, e.g.:
oil.ovm osh -c 'echo hi'
The %%% prefix Starts a Single Command Over Multiple Lines (?)
This special lexer mode has several use cases:
Long command lines without trailing \
%%% chromium-browser
--no-proxy-server
# comments allowed
--incognito
Long pipelines or and-or chains without trailing \
%%% find .
# exclude tests
| grep -v '_test.py'
| xargs wc -l
| sort -n
%%% ls /
&& ls /bin
&& ls /lib
|| error "oops"
TODO
Procs are shell-like functions, but with named parameters, and without dynamic scope (TODO):
proc copy(src, dest) {
cp --verbose --verbose $src $dest
}
Compare with sh-func.
The =
keyword shows the expression to its right:
oil$ = 1 + 2*3
(Int) 7
Blocks can be passed to builtins (and procs eventually):
cd /tmp {
echo $PWD # prints /tmp
}
echo $PWD
Compare with sh-block.
Initializes a constant name to the Oil expression on the right.
const c = 'mystr' # equivalent to readonly c=mystr
const pat = / digit+ / # an eggex, with no shell equivalent
It's either a global constant or scoped to the current function.
Initializes a name to the Oil expression on the right.
var s = 'mystr' # equivalent to declare s=mystr
var pat = / digit+ / # an eggex, with no shell equivalent
It's either a global or scoped to the current function.
Like shell's x=1
, setvar x = 1
either:
var
)It's meant for interactive use and to easily convert existing shell scripts.
New Oil programs should use set
, setglobal
, or setref
instead of
setvar
.
Mutates a global variable. If it doesn't exist, the shell exits with a fatal error.
Mutates a variable through a named reference. TODO: Show example.
Mutates an existing variable in the current scope. If it doesn't exist, the shell exits with a fatal error.
set
is an alias for setlocal
in the Oil language. Requires shopt -s parse_set
, because otherwise it would conflict with the set
builtin. Use
builtin set -- 1 2 3
to get the builtin, or shopt -o
to change options.
Oil strings appear in expression contexts, and look like shell strings:
var s = 'foo'
var double = "hello $world and $(hostname)"
However, strings with backslashes are forced to specify whether they're raw strings or C-style strings:
var s = 'line\n' # parse error: ambiguous
var s = c'line\n' # C-style string
var s = $'line\n' # also accepted for compatibility
var s = r'[a-z]\n' # raw strings are useful for regexes (not eggexes)
Like shell arays, Oil arrays accept anything that can appear in a command:
ls $mystr @ARGV *.py
# Put it in an array
var a = %(ls $mystr @ARGV *.py)
myint = 42
myfloat = 3.14
float2 = 1e100
Capital letters to avoid confusions with the builtin commands true
and
false
:
True T False F
And the value that's unequal to any other:
null
It's preferable to use the empty string in many cases. The null
value can't
be interpolated into words.
mystr ++ otherstr
"$mystr$otherstr" # equivalent
= mylist ++ otherlist
setvar mydict = %{a: 1, b: 2}
setvar otherdict = %{a: 10, c: 20}
= mydict ++ otherdict
setvar mystr ++= suffiX # ???
setvar mylist ++= %[item]
setvar mydict ++= otherdict # ???
== <= in
not and or
+ - * / div mod
div
is for integer math, while /
is for floating point math.
~ & | xor
Like Python:
display = 'yes' if len(s) else 'empty'
Like Python:
myarray[3]
mystr[3]
TODO: Does string indexing give you an integer back?
Like Python:
myarray[1 : -1]
mystr[1 : -1]
Like Python:
f(x, y)
Not implemented.
Not implemented.
~~ !~~
Failed tilde expansions cause hard errors (like zsh) rather than silently
evaluating to ~
or ~bad
.
TODO
When strict_nameref
is set, undefined references produce fatal errors:
declare -n ref
echo $ref # fatal error, not empty string
ref=x # fatal error instead of decaying to non-reference
References that don't contain variables also produce hard errors:
declare -n ref='not a var'
echo $ref # fatal
ref=x # fatal
For compatibility, Oil will parse some constructs it doesn't execute, like:
return 0 2>&1 # redirect on control flow
When this option is disabled, that statement is a syntax error.
TODO:
Replacement for "$@"
TODO: Do we need this in expression mode?
if ($? == 0) {
}
if (STATUS == 0) {
}
TODO: The match
The version of Oil that is being run, e.g. 0.9.0
.
TODO: comparison algorithm.
len(mystr)
is its length in byteslen(myarray)
is the number of elementslen(assocarray)
is the number of pairscopy()
:
var d = {name: value}
var alias = d # illegal, because it can create ownership problems
# reference cycles
var new = copy(d) # valid
regmatch(/d+/, s)
returns a match objectfnmatch('*.py', s)
returns a booleanThese functions give better syntax to existing shell constructs.
shquote()
for printf %q
and ${x@Q}
lstrip()
for ${x#prefix}
and ${x##prefix}
rstrip()
for ${x%suffix}
and ${x%%suffix}
lstripglob()
and rstripglob()
for slow, legacy globupper()
for ${x^^}
lower()
for ${x,,}
strftime()
: hidden in printf
index(A, item)
is like the awk function@names()
values()
. Problem: these aren't all strings?Useful for logging callbacks. NOTE: bash has this with the obscure printf '%(...)' syntax.
TODO