github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/README.md (about) 1 # A novel Unix shell 2 3 [![GoDoc](http://godoc.org/github.com/elves/elvish?status.svg)](http://godoc.org/github.com/elves/elvish) 4 [![Build Status on Travis](https://travis-ci.org/elves/elvish.svg?branch=master)](https://travis-ci.org/elves/elvish) 5 6 This project aims to explore the potentials of the Unix shell. It is a work in 7 progress; things will change without warning. The [issues list](https://github.com/elves/elvish/issues) contains many things I'm working on. 8 9 ## Screenshot 10 11 Elvish looks like this: 12 13 ![syntax highlighting](https://raw.githubusercontent.com/elves/images/master/syntax.png) 14 15 ## Prebuilt binaries 16 17 64-bit Linux: `curl -s https://dl.elvish.io/elvish-linux.tar.gz | sudo tar vxz -C /usr/bin` 18 19 64-bit Mac OS X: `curl -s https://dl.elvish.io/elvish-osx.tar.gz | sudo tar vxz -C /usr/bin` 20 21 See also [Building Elvish](#building-elvish). 22 23 ## Getting Started 24 25 Elvish mimics bash and zsh in a lot of places. The following shows some key differences and highlights, as well as some common tasks: 26 27 * Put your startup script in `~/.elvish/rc.elv`. There is no `alias` yet, but you can achieve the goal by defining a function: 28 29 ```sh 30 fn ls { external:ls --color $@ } 31 ``` 32 33 The `external:` prefix ensures that the external command named `ls` will be called. Otherwise this definition will result in infinite recursion. 34 35 * The left and right prompts and be customized by modifying `le:prompt` and `le:rprompt`. They can be assigned either to a function, in which their outputs are used, or a constant string. The following simulates the default prompts but uses fancy Unicode: 36 37 ```sh 38 # Changes during a session; use function. 39 # "tilde-abbr" abbreviates home directory to a tilde. 40 le:prompt={ put `tilde-abbr $pwd`'❱ ' } 41 # Doesn't change during a session; use constant string. 42 le:rprompt=`whoami`✸`hostname` 43 ``` 44 45 * Press Up to search through history. It uses what you have typed to do prefix match. To cancel, press Escape. 46 47 ![history](https://raw.githubusercontent.com/elves/images/master/history.png) 48 49 * Press Tab to start completion. Use arrow key and Tab to select the candidate; press Enter, or just continue typing to accept. To cancel, press Escape. 50 51 ![tab completion](https://raw.githubusercontent.com/elves/images/master/completion.png) 52 53 * Press Ctrl-N to start navigation mode. Press Ctrl-H to show hidden files; press again to hide. Press tab to append selected filename to your command. Likewise, pressing Escape gets you back to the default (insert) mode. 54 55 ![navigation mode](https://raw.githubusercontent.com/elves/images/master/navigation.png) 56 57 * Try typing `echo [` and press Enter. Elvish knows that the command is unfinished due to the unclosed `[` and inserts a newline instead of accepting the command. Moreover, common errors like syntax errors and missing variables are highlighted in real time. 58 59 * Elvish remembers which directories you have visited. Press Ctrl-L to list visited directories. Like in completion, use Up, Down and Tab to navigate and use Enter to accept (which `cd`s into the selected directory). Press Escape to cancel. 60 61 ![location mode](https://raw.githubusercontent.com/elves/images/master/location.png) 62 63 Type to filter: 64 65 ![location mode, filtering](https://raw.githubusercontent.com/elves/images/master/location-filter.png) 66 67 The filtering algorithm takes your filter and adds `**` to both sides of each path component. So `g/di` becomes pattern `**g**/**di**`, so it matches /home/xiaq/**g**o/elves/elvish/e**di**t. 68 69 * **NOTE**: Default key bindings as listed above are subject to change in the future; but the functionality will not go away. 70 71 * Elvish doesn't support history expansion like `!!`. Instead, it has a "bang mode", triggered by `Alt-,`, that provides the same functionality. For example, if you typed a command but forgot to add `sudo`, you can then type `sudo ` and press `Alt-,` twice to fix it: 72 73 ![bang mode](https://raw.githubusercontent.com/elves/images/master/bang.png) 74 75 * Lists look like `[a b c]`, and maps look like `[&key1=value1 &key2=value2]`. Unlike other shells, a list never expands to multiple words, unless you explicitly splice it by prefixing the variable name with `$@`: 76 ```sh 77 ~> li=[1 2 3] 78 ~> for x in $li; do echo $x; done 79 [1 2 3] 80 ~> for x in $@li; do echo $x; done 81 1 82 2 83 3 84 ``` 85 86 * You can manipulate search paths through the special list `$paths`: 87 ```sh 88 ~> echo $paths 89 [/bin /sbin] 90 ~> paths=[/opt/bin $@paths /usr/bin] 91 ~> echo $paths 92 [/opt/bin /bin /sbin /usr/bin] 93 ~> echo $env:PATH 94 /opt/bin:/bin:/sbin:/usr/bin 95 ``` 96 97 * You can manipulate the keybinding through the map `$le:binding`. For example, this binds Ctrl-L to clearing the terminal: `le:binding[insert][Ctrl-L]={ clear > /dev/tty }`. The first index is the mode and the second is the key. (Yes, the braces enclose a lambda.) 98 99 Use `pprint $le:binding` to get a nice (albeit long) view of the current keybinding. 100 101 * Environment variables live in a separate `env:` namespace and must be explicitly qualified: 102 ```sh 103 ~> put $env:HOME 104 ▶ /home/xiaq 105 ~> env:PATH=$env:PATH":/bin" 106 ``` 107 108 * There is no interpolation inside double quotes (yet). Use implicit string concatenation: 109 ```sh 110 ~> name=xiaq 111 ~> echo "My name is "$name"." 112 My name is xiaq. 113 ``` 114 115 * Elementary floating-point arithmetics as well as comparisons are builtin. Unfortunately, you have to use prefix notation: 116 ```sh 117 ~> + 1 2 118 ▶ 3 119 ~> / `* 2 3` 4 120 ▶ 1.5 121 ~> / (* 2 3) 4 # parentheses are equivalent to backquotes, but look nicer in arithmetics 122 ▶ 1.5 123 ~> > 1 2 # ">" may be used as a command name 124 false 125 ~> < 1 2 # "<" may also be used as a command name; silence means "true" 126 ``` 127 128 * Functions are defined with `fn`. You can name arguments: 129 ```sh 130 ~> fn square [x]{ 131 * $x $x 132 } 133 ~> square 4 134 ▶ 16 135 ``` 136 137 * Output of some builtin commands start with a funny "▶". It is not part of the output itself, but shows that such commands output a stream of values instead of bytes. As such, their internal structures as well as boundaries between values are preserved. This allows us to manipulate structured data in the shell; more on this later. 138 139 140 ## Building Elvish 141 142 Go >= 1.5 is required. Linux is fully supported. It is likely to work on BSDs and Mac OS X. Windows is **not** supported yet. 143 144 The main binary can be installed using `go get github.com/elves/elvish`. There is also an auxiliary program called elvish-stub; install it with `make stub`. Elvish is functional without the stub, but job control features depend on it. 145 146 If you are lazy and use `bash` or `zsh` now, here is something you can copy-paste into your terminal: 147 148 ```sh 149 export GOPATH=$HOME/go 150 export PATH=$PATH:$GOPATH/bin 151 mkdir -p $GOPATH 152 153 go get github.com/elves/elvish 154 make -C $GOPATH/src/github.com/elves/elvish stub 155 156 for f in ~/.bashrc ~/.zshrc; do 157 printf 'export %s=%s\n' GOPATH '$HOME/go' PATH '$PATH:$GOPATH/bin' >> $f 158 done 159 ``` 160 161 [How To Write Go Code](http://golang.org/doc/code.html) explains how `$GOPATH` works. 162 163 164 ## Name 165 166 In [roguelikes](https://en.wikipedia.org/wiki/Roguelike), items made by the elves have a reputation of high quality. These are usually called **elven** items, but I chose **elvish** for an obvious reason. 167 168 The adjective for elvish is also "elvish", not "elvishy" and definitely not "elvishish".