2013-10-06 15:35:27 +08:00
|
|
|
An experimental Unix shell
|
|
|
|
==========================
|
2013-06-16 16:45:22 +08:00
|
|
|
|
2013-09-21 21:05:27 +08:00
|
|
|
This is a work in progress. Things may change and/or break without notice. You
|
|
|
|
have been warned...
|
|
|
|
|
2013-12-29 15:04:37 +08:00
|
|
|
The Editor
|
|
|
|
----------
|
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
Those marked with :white_check_mark: are implemeneted (but could be broken from time to
|
|
|
|
time).
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
Like fish:
|
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
* Syntax highlighting :white_check_mark:
|
2013-12-29 15:04:37 +08:00
|
|
|
* Auto-suggestion
|
|
|
|
|
|
|
|
Like zsh:
|
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
* Right-hand-side prompt :white_check_mark:
|
|
|
|
* Dropdown menu completion :white_check_mark:
|
2013-12-29 15:04:37 +08:00
|
|
|
* Programmable line editor
|
|
|
|
|
|
|
|
And:
|
|
|
|
|
|
|
|
* A vi keybinding that makes sense
|
|
|
|
* More intuive multiline editing
|
|
|
|
* An intuive method to save typed snippets into a script
|
|
|
|
|
|
|
|
The Language
|
|
|
|
------------
|
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
(Like the previous section, only those marked with :white_check_mark: have been implemented.)
|
2013-12-29 15:20:49 +08:00
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
* Running external programs and pipelines, of course: :white_check_mark:
|
2013-12-29 15:12:01 +08:00
|
|
|
```
|
|
|
|
> vim README.md
|
2013-12-29 15:20:49 +08:00
|
|
|
...
|
2013-12-29 15:12:01 +08:00
|
|
|
> cat -v /dev/random
|
2013-12-29 15:20:49 +08:00
|
|
|
...
|
|
|
|
> dmesg | grep bar
|
|
|
|
...
|
2013-12-29 15:12:01 +08:00
|
|
|
```
|
|
|
|
|
2013-12-29 15:04:37 +08:00
|
|
|
* Basically prefix syntax without the outmost pair of parentheses (`>`
|
|
|
|
represents the prompt):
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> + 1 2
|
|
|
|
3
|
|
|
|
> * (+ 1 2) 3
|
|
|
|
9
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
* Use backquote for literal string (so that you can write both single and
|
2014-01-08 18:52:09 +08:00
|
|
|
double quotes inside), double backquotes for a literal backquote: :white_check_mark:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> echo `"He's dead, Jim."`
|
|
|
|
"He's dead, Jim."
|
|
|
|
> echo ```He's dead, Jim."`
|
|
|
|
``He's dead, Jim."
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
* Barewords are string literals:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> = a `a`
|
|
|
|
true
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
* Tables are a hybrid of array and hash (a la Lua); tables are first-class
|
2014-01-08 18:52:09 +08:00
|
|
|
values: :white_check_mark:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
2014-01-08 18:52:09 +08:00
|
|
|
> println [a b c &key value]
|
2013-12-29 15:07:29 +08:00
|
|
|
[a b c &key value]
|
2014-01-08 18:52:09 +08:00
|
|
|
> println [a b c &key value][0]
|
2013-12-29 15:07:29 +08:00
|
|
|
a
|
2014-01-08 18:52:09 +08:00
|
|
|
> println [a b c &key value][key]
|
2013-12-29 15:07:29 +08:00
|
|
|
value
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
* Declare variable with `var`, set value with `set`; `var` also serve as a
|
|
|
|
shorthand of var-set combo: :white_check_mark:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> var v
|
|
|
|
> set v = [foo bar]
|
2014-01-08 18:52:09 +08:00
|
|
|
> var u = [foo bar] # equivalent
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
* First-class closures, lisp-like functional programming:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> map {|x| * 2 $x} [1 2 3]
|
|
|
|
[2 4 6]
|
2013-12-30 16:23:22 +08:00
|
|
|
> filter {|x| > $x 2} [1 2 3 4 5]
|
2013-12-29 15:07:29 +08:00
|
|
|
[3 4 5]
|
2013-12-30 16:23:22 +08:00
|
|
|
> map {|x| * 2 $x} (filter {|x| > $x 2} [1 2 3 4 5])
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
2014-01-08 18:52:09 +08:00
|
|
|
* Get rid of lots of irritating superfluous parentheses with pipelines (`put`
|
|
|
|
is the builtin for outputting compound data):
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
2013-12-30 16:23:22 +08:00
|
|
|
> put [1 2 3 4 5] | filter {|x| > $x 2} | map {|x| * 2 $x}
|
2013-12-29 15:07:29 +08:00
|
|
|
[6 8 10]
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
* Use the table `$env` for environmental variables:
|
2013-12-29 15:07:29 +08:00
|
|
|
```
|
|
|
|
> put $env[HOME]
|
|
|
|
/home/xiaq
|
|
|
|
> set env[PATH] = $env[PATH]:/bin
|
|
|
|
```
|
2013-12-29 15:04:37 +08:00
|
|
|
|
|
|
|
There are many parts of the language that is not yet decided. See TODO.md for
|
|
|
|
a list of things I'm currently thinking about.
|
|
|
|
|
2013-10-06 15:36:41 +08:00
|
|
|
Motivation
|
2013-09-22 18:49:07 +08:00
|
|
|
----------
|
|
|
|
|
|
|
|
The basic idea is to have a shell that is also a decant programming language.
|
|
|
|
Shells have long rejected such things as data structure beyond text arrays.
|
|
|
|
Some support associative arrays, which may be assigned to variables but not
|
|
|
|
passed as arguments to builtins or shell functions, making the use of them
|
|
|
|
very tedious.
|
|
|
|
|
|
|
|
The lesson of Tcl has taught us the "everything is (unstructured) text"
|
|
|
|
philosophy, which is also the idea underpinning classical Unix pipelines, is
|
|
|
|
too limited for proper programming. Indeed, the power of Tcl often lies in the
|
|
|
|
dynamic interpretation of text, assuming some predefined structure in it. Yet
|
2013-10-06 15:35:27 +08:00
|
|
|
with shells, where such facilities are basically nonexistent, it requires
|
|
|
|
great discipline to build maintainable software. Traditional initscripts,
|
|
|
|
program wrapper scripts and some of the more tricky tab-completion scripts are
|
|
|
|
notable examples.
|
2013-09-22 18:49:07 +08:00
|
|
|
|
|
|
|
However, the shell does come with a very powerful abstraction - the pipeline.
|
|
|
|
It is basically a facility for concatenative programming. Consider the
|
|
|
|
following code in lisp:
|
|
|
|
|
|
|
|
```
|
|
|
|
(set coll' (map f (filter pred coll)))
|
|
|
|
```
|
|
|
|
|
|
|
|
Written concatenatively, this can be - assuming `put` puts the argument to
|
|
|
|
output (akin to `echo`), and `set` can take data from input in place of in the
|
|
|
|
argument list:
|
|
|
|
|
|
|
|
```
|
|
|
|
put $coll | filter pred | map f | set coll2
|
|
|
|
```
|
|
|
|
|
|
|
|
The concatenative approach is much more natural (try reading both versions
|
|
|
|
aloud).
|
|
|
|
|
2013-10-06 15:35:27 +08:00
|
|
|
Another defining character of shells is the easiness to invoke external
|
|
|
|
programs; comparing `subprocess.call(['ls', '-l'])` with `ls -l` - the
|
|
|
|
difference is clear. Being easy to invoking external programs is what makes
|
|
|
|
shells shells *in its original sense*, i.e. user interface to the operating
|
|
|
|
system.
|
|
|
|
|
|
|
|
Putting together, the idea of this new Unix shell is starting from pipelines
|
|
|
|
and external program interaction, adding in programming-language-ish flavors,
|
|
|
|
towards building a decant programming language with a friendly (command line)
|
2013-11-16 19:30:04 +08:00
|
|
|
user interface, suitable for both *back-of-the-envolope* computation **and**
|
|
|
|
building more complex (but maybe not too complex!) software.
|
2013-10-06 15:35:27 +08:00
|
|
|
|
|
|
|
This is not exactly an ambitious goal, but it's something I have always
|
|
|
|
dreamed of.
|
2013-09-22 18:49:07 +08:00
|
|
|
|
2013-09-18 16:45:18 +08:00
|
|
|
Building
|
|
|
|
--------
|
|
|
|
|
2013-09-21 21:05:27 +08:00
|
|
|
You need go >= 1.1 to build this. Just run `make`. The resulting binary is
|
|
|
|
called `das`.
|
|
|
|
|
|
|
|
Name
|
|
|
|
----
|
|
|
|
|
2013-09-21 21:08:54 +08:00
|
|
|
Indeed, **das** is not a very good name for a Unix shell. The name is actually
|
|
|
|
a corrupted form of **dash**, which also happens to be the German definite
|
|
|
|
neuter article.
|
|
|
|
|
2013-11-16 19:30:04 +08:00
|
|
|
I have some other ideas in mind. One of them is **elv**, since I found
|
|
|
|
"elvish" to be a great adjective - I can't use "elf" though, since it's
|
|
|
|
already [taken](http://www.cs.cmu.edu/~fp/elf.html) and may be confused with
|
|
|
|
the well known [file
|
2013-09-21 21:05:27 +08:00
|
|
|
format](http://en.wikipedia.org/wiki/Executable_and_Linkable_Format).
|
|
|
|
|
|
|
|
Another possible source of names is the names of actual seashells; but my
|
|
|
|
English vocabulary is too small for me to recall any beyond "nautilus", which
|
|
|
|
is both too long and already taken.
|
|
|
|
|
|
|
|
I'm not avoiding names ending in "sh" though; but I do find "bash" to be a
|
2013-11-16 19:30:04 +08:00
|
|
|
terrible name. "fish" is clever, but it has a quite [unpleasant
|
|
|
|
adjective](https://en.wiktionary.org/wiki/fishy). I find "dash" really good
|
|
|
|
though, which is why it came to my mind :).
|
2013-09-18 16:45:18 +08:00
|
|
|
|
2013-07-26 14:46:24 +08:00
|
|
|
License
|
|
|
|
-------
|
|
|
|
|
|
|
|
BSD 2-clause license. See LICENSE for a copy.
|