github.com/elves/elvish@v0.15.0/website/ref/edit.md (about) 1 <!-- toc --> 2 3 The `edit:` module is the interface to the Elvish editor. 4 5 Function usages are given in the same format as in the 6 [reference for the builtin module](builtin.html). 7 8 _This document is incomplete._ 9 10 # Overview 11 12 ## Modes and Submodules 13 14 The Elvish editor has different **modes**, and exactly one mode is active at the 15 same time. Each mode has its own UI and keybindings. For instance, the default 16 **insert mode** lets you modify the current command. The **completion mode** 17 (triggered by <span class="key">Tab</span> by default) shows you all candidates 18 for completion, and you can use arrow keys to navigate those candidates. 19 20 @ttyshot completion-mode 21 22 Each mode has its own submodule under `edit:`. For instance, builtin functions 23 and configuration variables for the completion mode can be found in the 24 `edit:completion:` module. 25 26 The primary modes supported now are `insert`, `completion`, `navigation`, 27 `history`, `histlist`, `location`, and `lastcmd`. The last 4 are "listing 28 modes", and their particularity is documented below. 29 30 ## Prompts 31 32 Elvish has two prompts: the (normal) left-hand prompt and the right-side prompt 33 (rprompt). Most of this section only documents the left-hand prompt, but API for 34 rprompt is the same other than the variable name: just replace `prompt` with 35 `rprompt`. 36 37 To customize the prompt, assign a function to `edit:prompt`. The function may 38 write value outputs or byte outputs: 39 40 - Value outputs may be either strings or `styled` values; they are joiend with 41 no spaces in between. 42 43 - Byte outputs are output as-is, including any newlines. Any 44 [SGR escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) 45 included in the byte outputs will be parsed, but any other escape sequences 46 or control character will be removed. 47 48 If you mix value and byte outputs, the order in which they appear is 49 non-deterministic. 50 51 Prefer using `styled` to output styled text; the support for SGR escape 52 sequences is mostly for compatibility with external cross-shell prompts. 53 54 The default prompt and rprompt are equivalent to: 55 56 ```elvish 57 edit:prompt = { tilde-abbr $pwd; put '> ' } 58 edit:rprompt = (constantly (styled (whoami)@(hostname) inverse)) 59 ``` 60 61 More prompt functions: 62 63 ```elvish-transcript 64 ~> edit:prompt = { tilde-abbr $pwd; styled '> ' green } 65 ~> # ">" is now green 66 ~> edit:prompt = { echo '$' } 67 $ 68 # Cursor will be on the next line as `echo` outputs a trailing newline 69 ``` 70 71 ### Stale Prompt 72 73 Elvish never waits for the prompt function to finish. Instead, the prompt 74 function is always executed on a separate thread, and Elvish updates the screen 75 when the function finishes. 76 77 However, this can be misleading when the function is slow: this means that the 78 prompt on the screen may not contain the latest information. To deal with this, 79 if the prompt function does not finish within a certain threshold - by default 80 0.2 seconds, Elvish marks the prompt as **stale**: it still shows the old stale 81 prompt content, but transforms it using a **stale transformer**. The default 82 stale transformer applies reverse-video to the whole prompt. 83 84 The threshold is customizable with `$edit:prompt-stale-threshold`; it specifies 85 the threshold in seconds. 86 87 The transformer is customizable with `$edit:prompt-stale-transform`. It is a 88 function; the function is called with one argument, a `styled` text, and the 89 output is interpreted in the same way as prompt functions. Some examples are: 90 91 ```elvish 92 # The following effectively disables marking of stale prompt. 93 edit:prompt-stale-transform = [x]{ put $x } 94 # Show stale prompts in inverse; equivalent to the default. 95 edit:prompt-stale-transform = [x]{ styled $x inverse } 96 # Gray out stale prompts. 97 edit:prompt-stale-transform = [x]{ styled $x bright-black } 98 ``` 99 100 To see the transformer in action, try the following example (assuming default 101 `$edit:prompt-stale-transform`): 102 103 ```elvish 104 n = 0 105 edit:prompt = { sleep 2; put $n; n = (+ $n 1); put ': ' } 106 edit:-prompt-eagerness = 10 # update prompt on each keystroke 107 edit:prompt-stale-threshold = 0.5 108 ``` 109 110 And then start typing. Type one character; the prompt becomes inverse after 0.5 111 second: this is when Elvish starts to consider the prompt as stale. The prompt 112 will return normal after 2 seconds, and the counter in the prompt is updated: 113 this is when the prompt function finishes. 114 115 Another thing you will notice is that, if you type a few characters quickly (in 116 less than 2 seconds, to be precise), the prompt is only updated twice. This is 117 because Elvish never does two prompt updates in parallel: prompt updates are 118 serialized. If a prompt update is required when the prompt function is still 119 running, Elvish simply queues another update. If an update is already queued, 120 Elvish does not queue another update. The reason why exactly two updates happen 121 in this case, and how this algorithm ensures freshness of the prompt is left as 122 an exercise to the reader. 123 124 ### Prompt Eagerness 125 126 The occasions when the prompt should get updated can be controlled with 127 `$edit:-prompt-eagerness`: 128 129 - The prompt is always updated when the editor becomes active -- when Elvish 130 starts, or a command finishes execution, or when the user presses Enter. 131 132 - If `$edit-prompt-eagerness` >= 5, it is updated when the working directory 133 changes. 134 135 - If `$edit-prompt-eagerness` >= 10, it is updated on each keystroke. 136 137 The default value is 5. 138 139 ### RPrompt Persistency 140 141 By default, the rprompt is only shown while the editor is active: as soon as you 142 press Enter, it is erased. If you want to keep it, simply set 143 `$edit:rprompt-persistent` to `$true`: 144 145 ```elvish 146 edit:rprompt-persistent = $true 147 ``` 148 149 ## Keybindings 150 151 Each mode has its own keybinding, accessible as the `binding` variable in its 152 module. For instance, the binding table for insert mode is 153 `$edit:insert:binding`. To see current bindings, simply print the binding table: 154 `pprint $edit:insert:binding` (replace `insert` with any other mode). 155 156 A binding tables is simply a map that maps keys to functions. For instance, to 157 bind `Alt-x` in insert mode to exit Elvish, simply do: 158 159 ```elvish 160 edit:insert:binding[Alt-x] = { exit } 161 ``` 162 163 Outputs from a bound function always appear above the Elvish prompt. You can see 164 this by doing the following: 165 166 ```elvish 167 edit:insert:binding[Alt-x] = { echo 'output from a bound function!' } 168 ``` 169 170 and press <span class="key">Alt-x</span> in insert mode. It allows you to put 171 debugging outputs in bound functions without messing up the terminal. 172 173 Internally, this is implemented by connecting their output to a pipe. This does 174 the correct thing in most cases, but if you are sure you want to do something to 175 the terminal, redirect the output to `/dev/tty`. For instance, the following 176 binds <span class="key">Ctrl-L</span> to clearing the terminal: 177 178 ```elvish 179 edit:insert:binding[Ctrl-L] = { clear > /dev/tty } 180 ``` 181 182 Bound functions have their inputs redirected to /dev/null. 183 184 ### Format of Keys 185 186 Key modifiers and names are case sensitive. This includes single character key 187 names such as `x` and `Y` as well as function key names such as `Enter`. 188 189 Key names have zero or more modifiers from the following symbols: 190 191 ``` 192 A Alt 193 C Ctrl 194 M Meta 195 S Shift 196 ``` 197 198 Modifiers, if present, end with either a `-` or `+`; e.g., `S-F1`, `Ctrl-X` or 199 `Alt+Enter`. You can stack modifiers; e.g., `C+A-X`. 200 201 The key name may be a simple character such as `x` or a function key from these 202 symbols: 203 204 ``` 205 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 206 Up Down Right Left 207 Home Insert Delete End PageUp PageDown 208 Tab Enter Backspace 209 ``` 210 211 **Note:** `Tab` is an alias for `"\t"` (aka `Ctrl-I`), `Enter` for `"\n"` (aka 212 `Ctrl-J`), and `Backspace` for `"\x7F"` (aka `Ctrl-?`). 213 214 **Note:** The `Shift` modifier is only applicable to function keys such as `F1`. 215 You cannot write `Shift-m` as a synonym for `M`. 216 217 **TODO:** Document the behavior of the `Shift` modifier. 218 219 ### Listing Modes 220 221 The modes `histlist`, `loc` and `lastcmd` are all **listing modes**: They all 222 show a list, and you can filter items and accept items. 223 224 Because they are very similar, you may want to change their bindings at the same 225 time. This is made possible by the `$edit:listing:binding` binding table 226 (`listing` is not a "real" mode but an "abstract" mode). These modes still have 227 their own binding tables like `$edit:histlist:binding`, and bindings there have 228 higher precedence over those in the shared `$edit:listing:binding` table. 229 230 Moreover, there are a lot of builtin functions in the `edit:listing` module like 231 `edit:listing:down` (for moving down selection). They always apply to whichever 232 listing mode is active. 233 234 ### Caveat: Bindings to Start Modes 235 236 Note that keybindings to **start** modes live in the binding table of the insert 237 mode, not the target mode. For instance, if you want to be able to use 238 <span class="key">Alt-l</span> to start location mode, you should modify 239 `$edit:insert:binding[Alt-l]`: 240 241 ```elvish 242 edit:insert:binding[Alt-l] = { edit:location:start } 243 ``` 244 245 One tricky case is the history mode. You can press 246 <span class="key">▲︎</span> to start searching for history, and continue 247 pressing it to search further. However, when the first press happens, the editor 248 is in insert mode, while with subsequent presses, the editor is in history mode. 249 Hence this binding actually relies on two entries, `$edit:insert:binding[Up]` 250 and `$edit:history:binding[Up]`. 251 252 So for instance if you want to be able to use <span class="key">Ctrl-P</span> 253 for this, you need to modify both bindings: 254 255 ```elvish 256 edit:insert:binding[Ctrl-P] = { edit:history:start } 257 edit:history:binding[Ctrl-P] = { edit:history:up } 258 ``` 259 260 ## Completion API 261 262 ### Argument Completer 263 264 There are two types of completions in Elvish: completion for internal data and 265 completion for command arguments. The former includes completion for variable 266 names (e.g. `echo $`<span class="key">Tab</span>) and indices (e.g. 267 `echo $edit:insert:binding[`<span class="key">Tab</span>). These are the 268 completions that Elvish can provide itself because they only depend on the 269 internal state of Elvish. 270 271 The latter, in turn, is what happens when you type e.g. `cat`<span 272 class="key">Tab</span>. Elvish cannot provide completions for them without full 273 knowledge of the command. 274 275 Command argument completions are programmable via the 276 `$edit:completion:arg-completer` variable. When Elvish is completing an argument 277 of command `$x`, it will call the value stored in 278 `$edit:completion:arg-completer[$x]`, with all the existing arguments, plus the 279 command name in the front. 280 281 For example, if the user types `man 1`<span class="key">Tab</span>, Elvish will 282 call: 283 284 ```elvish 285 $edit:completion:arg-completer[man] man 1 286 ``` 287 288 If the user is starting a new argument when hitting <span 289 class="key">Tab</span>, Elvish will call the completer with a trailing empty 290 string. For instance, if you do `man 1`<span class="key">Space</span><span 291 class="key">Tab</span>, Elvish will call: 292 293 ```elvish 294 $edit:completion:arg-completer[man] man 1 "" 295 ``` 296 297 The output of this call becomes candidates. There are several ways of outputting 298 candidates: 299 300 - Writing byte output, e.g. "echo cand1; echo cand2". Each line becomes a 301 candidate. This has the drawback that you cannot put newlines in candidates. 302 Only use this if you are sure that you candidates will not contain newlines 303 -- e.g. package names, usernames, but **not** file names, etc.. 304 305 - Write strings to value output, e.g. "put cand1 cand2". Each string output 306 becomes a candidate. 307 308 - Use the `edit:complex-candidate` command: 309 310 ```elvish 311 edit:complex-candidate &code-suffix='' &display-suffix='' &style='' $stem 312 ``` 313 314 **TODO**: Document this. 315 316 After receiving your candidates, Elvish will match your candidates against what 317 the user has typed. Hence, normally you don't need to (and shouldn't) do any 318 matching yourself. 319 320 That means that in many cases you can (and should) simply ignore the last 321 argument to your completer. However, they can be useful for deciding what 322 **kind** of things to complete. For instance, if you are to write a completer 323 for `ls`, you want to see whether the last argument starts with `-` or not: if 324 it does, complete an option; and if not, complete a filename. 325 326 Here is a very basic example of configuring a completer for the `apt` command. 327 It only supports completing the `install` and `remove` command and package names 328 after that: 329 330 ```elvish 331 all-packages = [(apt-cache search '' | eawk [0 1 @rest]{ put $1 })] 332 333 edit:completion:arg-completer[apt] = [@args]{ 334 n = (count $args) 335 if (== $n 2) { 336 # apt x<Tab> -- complete a subcommand name 337 put install uninstall 338 } elif (== $n 3) { 339 put $@all-packages 340 } 341 } 342 ``` 343 344 Here is another slightly more complex example for the `git` command. It supports 345 completing some common subcommands and then branch names after that: 346 347 ```elvish 348 fn all-git-branches { 349 # Note: this assumes a recent version of git that supports the format 350 # string used. 351 git branch -a --format="%(refname:strip=2)" | eawk [0 1 @rest]{ put $1 } 352 } 353 354 common-git-commands = [ 355 add branch checkout clone commit diff init log merge 356 pull push rebase reset revert show stash status 357 ] 358 359 edit:arg-completer[git] = [@args]{ 360 n = (count $args) 361 if (== $n 2) { 362 put $@common-git-commands 363 } elif (>= $n 3) { 364 all-git-branches 365 } 366 } 367 ``` 368 369 ### Matcher 370 371 As stated above, after the completer outputs candidates, Elvish matches them 372 with them with what the user has typed. For clarity, the part of the user input 373 that is relevant to tab completion is called for the **seed** of the completion. 374 For instance, in `echo x`<span class="key">Tab</span>, the seed is `x`. 375 376 Elvish first indexes the matcher table -- `$edit:completion:matcher` -- with the 377 completion type to find a **matcher**. The **completion type** is currently one 378 of `variable`, `index`, `command`, `redir` or `argument`. If the 379 `$edit:completion:matcher` lacks the suitable key, 380 `$edit:completion:matcher['']` is used. 381 382 Elvish then calls the matcher with one argument -- the seed, and feeds the 383 _text_ of all candidates to the input. The mather must output an identical 384 number of booleans, indicating whether the candidate should be kept. 385 386 As an example, the following code configures a prefix matcher for all completion 387 types: 388 389 ```elvish 390 edit:completion:matcher[''] = [seed]{ each [cand]{ has-prefix $cand $seed } } 391 ``` 392 393 Elvish provides three builtin matchers, `edit:match-prefix`, `edit:match-substr` 394 and `edit:match-subseq`. In addition to conforming to the matcher protocol, they 395 accept two options `&ignore-case` and `&smart-case`. For example, if you want 396 completion of arguments to use prefix matching and ignore case, use: 397 398 ```elvish 399 edit:completion:matcher[argument] = [seed]{ edit:match-prefix $seed &ignore-case=$true } 400 ``` 401 402 The default value of `$edit:completion:matcher` is `[&''=$edit:match-prefix~]`, 403 hence that candidates for all completion types are matched by prefix. 404 405 ## Hooks 406 407 Hooks are functions that are executed at certain points in time. In Elvish, this 408 functionality is provided by lists of functions. 409 410 There are current two hooks: 411 412 - `$edit:before-readline`, whose elements are called before the editor reads 413 code, with no arguments. 414 415 - `$edit:after-readline`, whose elements are called, after the editor reads 416 code, with a sole element -- the line just read. 417 418 Example usage: 419 420 ```elvish 421 edit:before-readline = [{ echo 'going to read' }] 422 edit:after-readline = [[line]{ echo 'just read '$line }] 423 ``` 424 425 Then every time you accept a chunk of code (and thus leaving the editor), 426 `just read` followed by the code is printed; and at the very beginning of an 427 Elvish session, or after a chunk of code is executed, `going to read` is 428 printed. 429 430 ## Word types 431 432 The editor supports operating on entire "words". As intuitive as the concept of 433 "word" is, there is actually no single definition for the concept. The editor 434 supports the following three definitions of words: 435 436 - A **big word**, or simply **word**, is a sequence of non-whitespace 437 characters. This definition corresponds to the concept of "WORD" in vi. 438 439 - A **small word** is a sequence of alphanumerical characters ("alnum small 440 word"), or a sequence of non-alphanumerical, non-whitespace characters 441 ("punctuation small word"). This definition corresponds to the concept of 442 "word" in vi and zsh. 443 444 - An **alphanumerical word** is a sequence of alphanumerical characters. This 445 definition corresponds to the concept of "word" in bash. 446 447 Whitespace characters are those with the Unicode 448 [Whitespace](https://en.wikipedia.org/wiki/Whitespace_character#Unicode) 449 property. Alphanumerical characters are those in the Unicode Letter or Number 450 category. 451 452 A **word boundary** is an imaginary zero-length boundary around a word. 453 454 To see the difference between these definitions, consider the following string: 455 `abc++ /* xyz`: 456 457 - It contains three (big) words: `abc++`, `/*` and `xyz`. 458 459 - It contains four small words, `abc`, `++`, `/*` and `xyz`. Among them, `abc` 460 and `xyz` are alnum small words, while `++` and `/*` are punctuation small 461 words. 462 463 - It contains two alnum words, `abc` and `xyz`. 464 465 @elvdoc -ns edit: -dir ../pkg/edit