github.com/xiaq/elvish@v0.12.0/website/src/learn/cookbook.md (about) 1 <!-- toc --> 2 3 If you come from other shells, hopefully the following recipes will get you started quickly: 4 5 # UI Recipes 6 7 * Put your startup script in `~/.elvish/rc.elv`. There is no `alias` yet, 8 but you can achieve the goal by defining a function: 9 10 ```elvish 11 fn ls [@a]{ e:ls --color $@a } 12 ``` 13 14 The `e:` prefix (for "external") ensures that the external command named 15 `ls` will be called. Otherwise this definition will result in infinite 16 recursion. 17 18 * The left and right prompts can be customized by assigning functions to 19 `edit:prompt` and `edit:rprompt`. Their outputs are concatenated (with no 20 spaces in between) before being used as the respective prompts. The 21 following simulates the default prompts but uses fancy Unicode: 22 23 ```elvish 24 # "tilde-abbr" abbreviates home directory to a tilde. 25 edit:prompt = { tilde-abbr $pwd; put '❱ ' } 26 # "constantly" returns a function that always writes the same value(s) to 27 # output; "edit:styled" writes styled output. 28 edit:rprompt = (constantly (edit:styled (whoami)✸(hostname) inverse)) 29 ``` 30 31 Here is a terminalshot of the alternative prompts: 32 33 $ttyshot unicode-prompts 34 35 * Press <span class="key">▲︎</span> to search through history. It 36 uses what you have typed to do prefix match. To cancel, press <span 37 class="key">Escape</span>. 38 39 $ttyshot history-mode 40 41 * Press <span class="key">Tab</span> to start completion. Use arrow keys 42 <span class="key">▲︎</span> 43 <span class="key">▼︎</span> 44 <span class="key">◀︎</span> 45 <span class="key">▶︎</span> 46 or <span class="key">Tab</span> and <span class="key">Shift-Tab</span> 47 to select the candidate. Press <span class="key">Enter</span>, or just 48 continue typing to accept. To cancel, press <span 49 class="key">Escape.</span> It even comes with a scrollbar! :) In fact, 50 all interactive modes show a scrollbar when there is more output to see. 51 52 $ttyshot completion-mode 53 54 * You can make completion case-insensitive with the following code: 55 56 ```elvish 57 edit:-matcher[''] = [p]{ edit:match-prefix &ignore-case $p } 58 ``` 59 60 You can also make the completion use "smart case" by changing 61 `&ignore-case` to `&smart-case`. This means that if your pattern 62 is entirely lower case it ignores case, otherwise it's case 63 sensitive. 64 65 * <a name="navigation-mode"></a>Press <span class="key">Ctrl-N</span> to start the builtin filesystem 66 navigator, aptly named "navigation mode." Use arrow keys to navigate. 67 <span class="key">Enter</span> inserts the selected filename to your 68 command line. If you want to insert the filename and stay in the mode 69 (e.g. when you want to insert several filenames), use <span 70 class="key">Alt-Enter</span>. 71 72 You can continue typing your command when you are in navigation mode. 73 Press <span class="key">Ctrl-H</span> to toggle hidden files; and like in 74 other modes, <span class="key">Escape</span> gets you back to the default 75 (insert) mode. 76 77 $ttyshot navigation-mode 78 79 * Try typing `echo [` and press <span class="key">Enter</span>. 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. 80 81 * Elvish remembers which directories you have visited. Press <span 82 class="key">Ctrl-L</span> to list visited directories. Like in completion, 83 use arrow keys 84 <span class="key">▲︎</span> 85 <span class="key">▼︎</span> 86 or <span class="key">Tab</span> and <span class="key">Shift-Tab</span> to 87 select a directory and use Enter to `cd` into it. Press <span 88 class="key">Escape</span> to cancel. 89 90 $ttyshot location-mode 91 92 Type to filter: 93 94 $ttyshot location-mode-filter 95 96 The filtering algorithm is tailored for matching paths; you need only type 97 a prefix of each component. In the screenshot, x/p/v matches 98 **x**iaq/**p**ersistent/**v**ector. 99 100 * Elvish doesn't support history expansion like `!!`. Instead, it has a 101 "last command mode" offering the same functionality, triggered by <span 102 class="key">Alt-1</span> by default (resembling how you type `!` using 103 <span class="key">Shift-1</span>). In this mode, you can pick individual 104 arguments from the last command using numbers, or the entire command by 105 typing <span class="key">Alt-1</span> again. 106 107 This is showing me trying to fix a forgotten `sudo`: 108 109 $ttyshot lastcmd 110 111 # Language Recipes 112 113 * Lists look like `[a b c]`, and maps look like `[&key1=value1 114 &key2=value2]`. Unlike other shells, a list never expands to multiple 115 words, unless you explicitly explode it by prefixing the variable name 116 with `@`: 117 118 ```elvish-transcript 119 ~> li = [1 2 3] 120 ~> put $li 121 ▶ [1 2 3] 122 ~> put $@li 123 ▶ 1 124 ▶ 2 125 ▶ 3 126 ~> map = [&k1=v1 &k2=v2] 127 ~> echo $map[k1] 128 v1 129 ``` 130 131 * Environment variables live in a separate `E:` (for "environment") namespace and must be explicitly qualified: 132 133 ```elvish-transcript 134 ~> put $E:HOME 135 ▶ /home/xiaq 136 ~> E:PATH = $E:PATH":/bin" 137 ``` 138 139 * You can manipulate search paths through the special list `$paths`, which is synced with `$E:PATH`: 140 141 ```elvish-transcript 142 ~> echo $paths 143 [/bin /sbin] 144 ~> paths = [/opt/bin $@paths /usr/bin] 145 ~> echo $paths 146 [/opt/bin /bin /sbin /usr/bin] 147 ~> echo $E:PATH 148 /opt/bin:/bin:/sbin:/usr/bin 149 ``` 150 151 * You can manipulate the keybinding in the default insert mode through the 152 map `$edit:insert:binding`. For example, this binds 153 <span class="key">Ctrl-L</span> to clearing the terminal: 154 155 ```elvish 156 edit:insert:binding[Ctrl-L] = { clear > /dev/tty } 157 ``` 158 159 Use `pprint $edit:insert:binding` to get a nice (albeit long) view of the 160 current keybinding. 161 162 **NOTE**: Bindings for letters modified by Alt are case-sensitive. For 163 instance, `Alt-a` means pressing `Alt` and `A`, while `Alt-A` means 164 pressing `Alt`, `Shift` and `A`. This will probably change in the future. 165 166 * There is no interpolation inside double quotes (yet). For example, the 167 output of `echo "$user"` is simply the string `$user`. Use implicit string 168 concatenation to build strings: 169 170 ```elvish-transcript 171 ~> name = xiaq 172 ~> echo "My name is "$name"." 173 My name is xiaq. 174 ``` 175 176 Sometimes string concatenation will force you to use string literals 177 instead of barewords: 178 179 ```elvish-transcript 180 ~> noun = language 181 ~> echo $noun's' 182 languages 183 ``` 184 185 You cannot write `s` as a bareword because Elvish would think you are 186 trying to write the variable `$nouns`. It's hard to make such mistakes 187 when working interactively, as Elvish highlights variables and complains 188 about nonexistent variables as you type. 189 190 * Double quotes support C-like escape sequences (``\n`` for newline, 191 etc.): 192 193 ```elvish-transcript 194 ~> echo "a\nb" 195 a 196 b 197 ``` 198 199 **NOTE**: If you run `echo "a\nb"` in bash or zsh, you might get the same 200 result (depending on the value of some options), and this might lead you 201 to believe that they support C-like escape sequences in double quotes as 202 well. This is not the case; bash and zsh preserve the backslash in double 203 quotes, and it is the `echo` builtin command that interpret the escape 204 sequences. This difference becomes apparent if you change `echo` to 205 `touch`: In Elvish, `touch "a\nb"` creates a file whose name has a 206 newline; while in bash or zsh, it creates a file whose name contains a 207 backslash followed by `n`. 208 209 * Elementary floating-point arithmetics as well as comparisons are builtin, 210 with a prefix syntax: 211 212 ```elvish-transcript 213 ~> + 1 2 214 ▶ 3 215 ~> / (* 2 3) 4 216 ▶ 1.5 217 ~> > 1 2 218 ▶ $false 219 ~> < 1 2 220 ▶ $true 221 ``` 222 223 **NOTE**: Elvish has special parsing rules to recognize `<` and `>` as 224 command names. That means that you cannot put redirections in the 225 beginning; bash and zsh allows `< input cat`, which is equivalent to 226 `cat < input`; in Elvish, you can only use the latter syntax. 227 228 * Functions are defined with `fn`. You can name arguments: 229 230 ```elvish-transcript 231 ~> fn square [x]{ 232 * $x $x 233 } 234 ~> square 4 235 ▶ 16 236 ``` 237 238 * Output of some builtin commands start with a funny `▶`. It is not part of 239 the output itself, but shows that such commands output a stream of values 240 instead of bytes. As such, their internal structures as well as boundaries 241 between values are preserved. This allows us to manipulate structured data 242 in the shell. 243 244 Read [semantics highlights](/learn/semantics-highlights.html) for details. 245 246 * When calling Elvish commands, options use the special `&option=value` 247 syntax. For instance, the `echo` builtin command supports a `sep` option 248 for specifying an alternative separator: 249 250 ```elvish-transcript 251 ~> echo &sep="," a b c 252 a,b,c 253 ``` 254 255 The mixture of options and arguments is a classical problem in traditional 256 shell programming. For instance, if you want to print a file whose name is 257 in `$x`, `cat $x` is the obvious thing to do, but it does not do this 258 reliably -- if `$x` starts with `-` (e.g. `-v`), `cat` thinks that it is 259 an option. The correct way is `cat -- $x`. 260 261 Elvish commands are free from this problem. However, the option facility 262 is only available to builtin commands and user-defined functions, not 263 external commands, meaning that you still need to do `cat -- $x`. 264 265 In principle, it is possible to write safe wrapper 266 for external commands and there is a 267 [plan](https://github.com/elves/elvish/issues/371) for this.