Why Sponsor Oils? | blog | oilshell.org
This is the latest version of OSH, a bash-compatible shell:
Please try it on your shell scripts and report bugs! To build and run it, follow the instructions in INSTALL.txt.
If you're new to the project, see Why Create a New Shell?.
In the last post on autocompletion, I hinted at what's new in this release. Read on for details.
This post summarizes the last three releases:
compgen -A function
, which auto-completes
function names.osh-usage
, oshc-deps
and arena
.sh-expr
and shExpr()
.Under the hood:
longjmp()
rather than return codes.alias
and unalias
builtins.
shopt -s expand_aliases
for bash compatibility. Like other
shells, we always expand aliases.until
loop, empty here doc, etc.$IFS
word splitting algorithm so x"y "
is evaluated correctly.source
.$(x
a parse error. Prior to this fix, an actual EOF
character
could close a command substitution.Under the hood:
osh -n
,
though it necessarily ignores aliases. In contrast, the Oil
language won't have aliases and will be entirely statically
parsed. According to the bash
manual:
For almost every purpose, shell functions are preferred over aliases.ParseContext
object throughout the parsing code to handle the
runtime → parse-time feedback.declare -F
to list functions.New metrics on the OPy compiler's bytecode:
Analyzing the bytecode with the R language improved my understanding of the compiler that I cobbled together. Explaining the above metrics metrics would make a good blog post. I discovered some inefficiencies, described in issue #180.
Language features for Completion:
@(*.py|*.sh)
. We use GNU libc to implement this,
so it doesn't work on Alpine Linux or OS X.
declare -A assoc
, ${assoc["foo"]}
COMPREPLY[j++]=foo
.,,
and ^^
for uppercase/lowercase.${!N}
can evaluate to $1
, $2
, etc. when
N
is an integer. Example: ${!OPTIND}
.[[ foo =~ .*\.py ]]
. Quoted parts are
properly regex-escaped.command ls foo
disables function lookup. bash treats this as a
builtin, but it's more like part of the shell language.if ! declare ...
is no longer run in a subshell.
shopt -s lastpipe
was set. (zsh behaves this way by default.)Builtins for completion:
complete
and compgen
builtins.
complete -F myfunc
registers a user-defined completion function.
OSH can now invoke such functions correctly in many cases.compopt
.shopt -q
queries global shell settings.getopts
handles explicit arguments when passed, rather than reading "$@"
.~/.bashrc
set -v
/ set -o verbose
shopt -s progcomp
, shopt -s hostcomplete
COMP_CWORDS
, COMP_LINE
, etc.
COMP_WORDBREAKS
Bug fixes for completion:
getopts
builtin respects dynamic scope when setting
OPTIND
and other output variables. In other words, it looks up the stack
for a variable to mutate.(( i = 0 ))
no longer evaluates i
(as is necessary for (( i += 42 ))
).[
are now stricter
than coercions with [[
.declare -g
to force variables to be global (used by
bash-completion). This matters in this case:f() {
local x=1
# The "globals" in lib.sh are now local! Unless declared with -g.
source lib.sh
}
Dev Tools:
OSH_CRASH_DUMP_DIR
environment variable. It still needs
work, and I will write more about it when it's usable.--debug-file
stream to see internal info and warnings.--xtrace-to-debug-file
so the output of set -o xtrace
doesn't go to
stderr (which is usually a terminal).repr
builtin to inspect the value of variables (not done, may
change).FUNCNAME
, BASH_SOURCE
,
BASH_LINENO
. (Note: I don't like their semantics and would change them if
given a chance.)set -o strict-arith
.)Other:
$ opyc compile -emit-docstring=0 foo.py
To be honest, I'm burnt out on the interactive shell, and it's not done yet. I need help!
Leave a comment or chat with me on oilshell.zulipchat.com if you're experienced with both Python and shell, and want to help.
Here are some blog posts I should write:
--debug-file
flag needs an asciinema demo.find
and xargs
(#85).The new functionality above is reflected in the spec test metrics:
I also mentioned improvements in the OSH-to-Oil translations:
(Many translations are still incorrect, but they no longer fail by crashing!)
I want Oil's source to be compact and easily understandable. All these new features only cost us ~700 significant lines of code!
Including whitespace and comments:
Slight decrease in native code:
which results in a slightly smaller binary:
But the bytecode size went up, since there are more lines of Python:
OSH is at the point where I implement features on demand. I won't go out of my way to implement a feature — a "real" shell script has to motivate it.
The only unhandled exceptions in the spec tests are now
NotImplementedError
for the following features:
<&
redirect: I don't actually understand this operator, e.g. compared with
>&
.|&
to pipe stderr
as well as stdout
. It's analogous
to &>
and &>>
, which were recently implemented.${!a[@]}
to give the keys of associative arrays. (This is completely
distinct from the normal "named reference" behavior.)(1) Python's readline binding silently swallows exceptions in registered callbacks. Like the author of this blog post, I found this out the hard way.
(2) I hit another occurrence of the hardest bug: file descriptors silently getting clobbered, leading to a process that can't even print debug messages.
The underlying cause was that import random
in Python opens /dev/urandom
as
a side effect. I fixed the bug by simply removing it, since it was an
unnecessary transitive dependency caused by cgi.escape()
.
A shell interpreter is unique in that it must know about all file descriptors used by the process it runs in. It can't use libraries and frameworks that open files "behind its back".