Oh is a Unix shell written in Go. The following commands behave as expected:
date
cat /usr/share/dict/words
who >user.names
who >>user.names
wc <file
echo [a-f]*.c
who | wc
who; date
cc *.c &
mkdir junk && cd junk
cd ..
rm -r junk || echo "rm failed!"
Oh uses the same syntax for code and data. This enables it to be easily extended:
# The short-circuit and operator is defined using the syntax command.
define and: syntax e (: lst) as {
define r False
while (not: is-null: car lst) {
set r: e::eval: car lst
if (not r): return r
set lst: cdr lst
}
return r
}
Oh is properly tail-recursive and exposes continuations as first-class values:
define label: method () as: return return
define continue: method (label) as: label label
# Print 1 to 100 using the continuation (return) returned by label.
define count: integer 0
define loop: label
if (lt count (integer 100)) {
set count: add count 1
write count
continue loop
}
Oh exposes pipes, which are implicit in other shells, as first-class values:
define p: pipe
spawn {
# Save code to create a continuation-based while command.
define code '(syntax e (condition: body) as {
define label: method () as: return return
define continue: method (label) as: label label
set body: cons 'block body
define loop: label
if (not (e::eval condition)): return '()
e::eval body
continue loop
})
# Now send this code through the pipe.
p::write @code
}
# Create the new command by evaluating what was sent through the pipe.
define while2: eval: p::read
# Now use the new 'while2' command.
define count: integer 0
while2 (lt count (integer 100)) {
set count: add count 1
write count
}
Oh's environments are first-class and form the basis for its prototype-based object system:
# Create a point prototype.
define point: object {
# Private members are created with the define command.
define x: integer 0
define y: integer 0
# Public members are created with the public command.
public move: method self (a b) as {
set self::x: add self::x a
set self::y: add self::y b
}
public show: method self () as {
echo self::x self::y
}
}
# Create a new point by cloning the point prototype:
define o: point::clone
To go get oh:
go get github.com/michaelmacinnis/oh
Oh is released under an MIT-style license.
Despite multiple attempts to improve the Unix shell, its essential character has remained largely unchanged. Popular Unix shells have retained the look and feel established by the Bourne shell and so share a strong family resemblance. The most successful shells in this family (bash, ksh, zsh) are backward compatible with the Bourne shell. Unfortunately, this backward compatibility results in shells that are "inconsistent and confusing command languages."[18]
If you squint hard enough, the Unix shell looks very similar to other existing languages. So similar that many have attempted embedding the Unix shell in an existing language. The problem with this approach is that the result is either "an uglier, and confusing, language"[21] or a language that is more cumbersome when used as an interactive shell.[23]
Like es, fish and rc, oh retains the look and feel of the Unix shell but does not aim for strict backward compatibility. Oh makes substantial improvements to the programming language features of the Unix shell by borrowing heavily from the Scheme dialect of Lisp. Rather than attempting to embed a Unix shell in scheme, oh was designed from scratch.
Oh was motivated by the belief that many of the flaws in current Unix shells are not inherent but rather historical. Design choices that are clearly unfortunate in retrospect have been carried forward in the name of backward compatibility. As a re-imagining of the Unix shell, oh revisits these design choices while adding support for concurrent, functional and object-based programming.
Fexprs:
1. Fexprs as the Basis of Lisp Function Application or $vau : The Ultimate Abstraction
First-class Environments:
2. First-class environments. Discuss. ;)
Unix Shells (Bourne Shell Family):
Unix Shells (C Shell Family):
7. An Introduction to the C shell
Unix Shells (Other):
9. Es: A shell with higher-order functions
Alternative Shells:
12. A High-Level Programming and Command Language
13. Chris S. McDonald. fsh - A Functional UNIX Command Interpreter. Software - Practice & Experience 17(10): 685-700, 1987
Embedding the Unix Shell in an Existing Language:
14. L. M. Campbell and M. D. Campbell. An Overview of the Ada Shell. In USENIX Winter: 302-313, 1986
17. J. R. Ellis. A Lisp Shell. SIGPLAN Notices, 15(5):24-34, 1980
18. Using ML as a Command Language
19. Zoidberg - A Modular Perl Shell
Shell History: