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">▲&#xfe0e;</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