Provided by: elvish_0.13+ds1-2ubuntu0.1_amd64 bug

Overview

   Modes and Submodules
       The Elvish editor has different modes, and exactly one mode is active at  the  same  time.
       Each  mode has its own UI and keybindings.  For instance, the default insert mode lets you
       modify the current command.  The completion mode (triggered by Tab by default)  shows  you
       all candidates for completion, and you can use arrow keys to navigate those candidates.

       @ttyshot completion-mode

       Each  mode  has  its  own  submodule  under  edit:.   For  instance, builtin functions and
       configuration variables for the completion mode  can  be  found  in  the  edit:completion:
       module.

       The  primary  modes  supported  now are insert, completion, navigation, history, histlist,
       location, and lastcmd.  The last  4  are  "listing  modes",  and  their  particularity  is
       documented below.

Prompts

       Elvish has two prompts: the (normal) left-hand prompt and the right-side prompt (rprompt).
       Most of this section only documents the left-hand prompt, but API for rprompt is the  same
       other than the variable name: just replace prompt with rprompt.

       To  customize  the prompt, assign a function to edit:prompt.  The function may write value
       outputs or byte outputs.  Value outputs may be either strings or styled values;  they  are
       joiend  with no spaces in between.  Byte outputs are output as-is, including any newlines,
       but control characters will be escaped: you should use styled to output styled  text.   If
       you mix value and byte outputs, the order in which they appear is non-deterministic.

       The default prompt and rprompt are equivalent to:

              edit:prompt = { tilde-abbr $pwd; put '> ' }
              edit:rprompt = (constantly (styled (whoami)@(hostname) inverse))

       More prompt functions:

              ~> edit:prompt = { tilde-abbr $pwd; styled '> ' green }
              ~> # ">" is now green
              ~> edit:prompt = { echo '$' }
              $
              # Cursor will be on the next line as `echo` outputs a trailing newline

   Stale Prompt
       Elvish  never  waits  for  the prompt function to finish.  Instead, the prompt function is
       always executed on a separate thread, and Elvish updates  the  screen  when  the  function
       finishes.

       However,  this  can be misleading when the function is slow: this means that the prompt on
       the screen may not contain the latest information.  To  deal  with  this,  if  the  prompt
       function does not finish within a certain threshold - by default 0.2 seconds, Elvish marks
       the prompt as stale: it still shows the old stale prompt content, but transforms it  using
       a  stale  transformer.   The  default stale transformer applies reverse-video to the whole
       prompt.

       The  threshold  is  customizable  with  $edit:prompt-stale-threshold;  it  specifies   the
       threshold in seconds.

       The  transformer is customizable with $edit:prompt-stale-transform.  It is a function; the
       function is called with no arguments, and styled values  as  inputs,  and  the  output  is
       interpreted  in  the  same  way  as  prompt functions.  Since styled values can be used as
       outputs in prompt functions, a function that simply passes all the input values through as
       outputs is a valid stale transformer.

       As an example, try running following code:

              n = 0
              edit:prompt = { sleep 2; put $n; n = (+ $n 1); put ': ' }
              edit:-prompt-eagerness = 10 # update prompt on each keystroke
              edit:prompt-stale-threshold = 0.5

       And  then  start typing.  Type one character; the prompt becomes inverse after 0.5 second:
       this is when Elvish starts to consider the prompt as stale.  The prompt will return normal
       after  2  seconds,  and  the  counter  in  the  prompt is updated: this is when the prompt
       function finishes.

       Another thing you will notice is that, if you type a few characters quickly (in less  than
       2 seconds, to be precise), the prompt is only updated twice.  This is because Elvish never
       does two prompt updates in parallel: prompt updates are serialized.  If a prompt update is
       required  when  the prompt function is still running, Elvish simply queues another update.
       If an update is already queued, Elvish does not queue  another  update.   The  reason  why
       exactly  two  updates happen in this case, and how this algorithm ensures freshness of the
       prompt is left as an exercise to the reader.

   Prompt Eagerness
       The  occassions  when  the  prompt   should   get   updated   can   be   controlled   with
       $edit:-prompt-eagerness:

       • The  prompt is always updated when the editor becomes active -- when Elvish starts, or a
         command finishes execution, or when the user presses Enter.

       • If $edit-prompt-eagerness >= 5, it is updated when the working directory changes.

       • If $edit-prompt-eagerness >= 10, it is updated on each keystroke.

       The default value is 5.

   RPrompt Persistency
       By default, the rprompt is only shown while the editor is active: as  soon  as  you  press
       Enter,  it  is  erased.   If  you  want to keep it, simply set $edit:rprompt-persistent to
       $true:

              edit:rprompt-persistent = $true

Keybindings

       Each mode has its own keybinding, accessible as the binding variable in its  module.   For
       instance,  the  binding  table  for  insert  mode is $edit:insert:binding.  To see current
       bindings, simply print the binding table: pprint $edit:insert:binding (replace insert with
       any other mode).

       A binding tables is simply a map that maps keys to functions.  For instance, to bind Alt-x
       in insert mode to exit Elvish, simply do:

              edit:insert:binding[Alt-x] = { exit }

       Outputs from a bound function always appear above the Elvish prompt.  You can see this  by
       doing the following:

              edit:insert:binding[Alt-x] = { echo 'output from a bound function!' }

       and press Alt-x in insert mode.  It allows you to put debugging outputs in bound functions
       without messing up the terminal.

       Internally, this is implemented by connecting their output  to  a  pipe.   This  does  the
       correct thing in most cases, but if you are sure you want to do something to the terminal,
       redirect the output to /dev/tty.  For instance, the following binds Ctrl-L to clearing the
       terminal:

              edit:insert:binding[Ctrl-L] = { clear > /dev/tty }

       Bound functions have their inputs redirected to /dev/null.

   Format of Keys
       TBD

   Listing Modes
       The  modes  histlist, loc and lastcmd are all listing modes: They all show a list, and you
       can filter items and accept items.

       Because they are very similar, you may want to change their bindings  at  the  same  time.
       This  is made possible by the $edit:listing:binding binding table (listing is not a "real"
       mode but an "abstract" mode).  These modes  still  have  their  own  binding  tables  like
       $edit:histlist:binding,  and  bindings  there  have  highter  precedence over those in the
       shared $edit:listing:binding table.

       Moreover,  there  are  a  lot  of  builtin  functions  in  the  edit:listing  module  like
       edit:listing:down  (for  moving  down  selection).  They always apply to whichever listing
       mode is active.

   Caveat: Bindings to Start Modes
       Note that keybindings to start modes live in the binding table of the insert mode, not the
       target  mode.   For  instance, if you want to be able to use Alt-l to start location mode,
       you should modify $edit:insert:binding[Alt-l]:

              edit:insert:binding[Alt-l] = { edit:location:start }

       One tricky case is the history mode.  You can press ▲︎ to start searching for history, and
       continue pressing it to search further.  However, when the first press happens, the editor
       is in insert mode, while with subsequent presses, the editor is in  history  mode.   Hence
       this    binding   actually   relies   on   two   entries,   $edit:insert:binding[Up]   and
       $edit:history:binding[Up].

       So for instance if you want to be able to use Ctrl-P for this, you  need  to  modify  both
       bindings:

              edit:insert:binding[Ctrl-P] =  { edit:history:start }
              edit:history:binding[Ctrl-P] = { edit:history:up }

Completion API

   Argument Completer
       There  are two types of completions in Elvish: completion for internal data and completion
       for command arguments.  The former includes completion  for  variable  names  (e.g.   echo
       $Tab)  and indicies (e.g.  echo $edit:insert:binding[Tab).  These are the completions that
       Elvish can provide itself because they only depend on the internal state of Elvish.

       The latter, in turn, is what happens when you type e.g.  catTab.   Elvish  cannot  provide
       completions for them without full knowledge of the command.

       Command  argument  completions  are  programmable  via  the $edit:completion:arg-completer
       variable.  When Elvish is completing an argument of command $x, it  will  call  the  value
       stored  in  $edit:completion:arg-completer[$x],  with all the existing arguments, plus the
       command name in the front.

       For example, if the user types man 1Tab, Elvish will call:

              $edit:completion:arg-completer[man] man 1

       If the user is starting a new argument when hitting Tab, Elvish will  call  the  completer
       with a trailing empty string.  For instance, if you do man 1SpaceTab, Elvish will call:

              $edit:completion:arg-completer[man] man 1 ""

       The  output  of  this  call  becomes  candidates.   There  are  several ways of outputting
       candidates:

       • Writing byte output, e.g.  "echo cand1; echo cand2".  Each  line  becomes  a  candidate.
         This  has the drawback that you cannot put newlines in candidates.  Only use this if you
         are sure that  you  candidates  will  not  contain  newlines  --  e.g.   package  names,
         usernames, but not file names, etc..

       • Write  strings  to  value output, e.g.  "put cand1 cand2".  Each string output becomes a
         candidate.

       • Use the edit:complex-candidate command:

                edit:complex-candidate &code-suffix='' &display-suffix='' &style='' $stem

         TODO: Document this.

       After receiving your candidates, Elvish will match your candidates against what  the  user
       has typed.  Hence, normally you don't need to (and shouldn't) do any matching yourself.

       That  means that in many cases you can (and should) simpy ignore the last argument to your
       completer.  However, they can be useful for deciding what kind of things to complete.  For
       instance,  if  you  are  to  write  a  completer  for ls, you want to see whether the last
       argument starts with - or not: if it does, complete an option;  and  if  not,  complete  a
       filename.

       Here  is  a  very  basic  example of configuring a completer for the apt command.  It only
       supports completing the install and remove command and package names after that:

              all-packages = [(apt-cache search '' | eawk [0 1 @rest]{ put $1 })]

              edit:completion:arg-completer[apt] = [@args]{
                  n = (count $args)
                  if (== $n 2) {
                      # apt x<Tab> -- complete a subcommand name
                      put install uninstall
                  } elif (== $n 3) {
                      put $@all-packages
                  }
              }

       Here is another slightly more complex example for the git command.  It supports completing
       some common subcommands and then branch names after that:

              fn all-git-branches {
                  # Note: this assumes a recent version of git that supports the format
                  # string used.
                  git branch -a --format="%(refname:strip=2)" | eawk [0 1 @rest]{ put $1 }
              }

              common-git-commands = [
                add branch checkout clone commit diff init log merge
                pull push rebase reset revert show stash status
              ]

              edit:arg-completer[git] = [@args]{
                  n = (count $args)
                  if (== $n 2) {
                      put $@common-git-commands
                  } elif (>= $n 3) {
                      all-git-branches
                  }
              }

   Matcher
       As  stated  above,  after  the completer outputs candidates, Elvish matches them with them
       with what the user has typed.  For clarity, the part of the user input that is relevant to
       tab  completion is called for the seed of the completion.  For instance, in echo xTab, the
       seed is x.

       Elvish first indexes the matcher table -- $edit:completion:matcher -- with the  completion
       type to find a matcher.  The completion type is currently one of variable, index, command,
       redir  or  argument.   If   the   $edit:completion:matcher   lacks   the   suitable   key,
       $edit:completion:matcher[''] is used.

       Elvish  then  calls  the  matcher with one argument -- the seed, and feeds the text of all
       candidates to the input.   The  mather  must  output  an  identical  number  of  booleans,
       indicating whether the candidate should be kept.

       As an example, the following code configures a prefix matcher for all completion types:

              edit:completion:matcher[''] = [seed]{ each [cand]{ has-prefix $cand $seed } }

       Elvish   provides   three   builtin  matchers,  edit:match-prefix,  edit:match-substr  and
       edit:match-subseq.  In addition to conforming to the matcher  protocol,  they  accept  two
       options &ignore-case and &smart-case.  For example, if you want completion of arguments to
       use prefix matching and ignore case, use:

              edit:completion:matcher[argument] = [seed]{ edit:match-prefix $seed &ignore-case=$true }

       The default value of $edit:completion:matcher  is  [&''=$edit:match-prefix~],  hence  that
       candidates for all completion types are matched by prefix.

Hooks

       Hooks  are  functions  that  are  executed  at  certain  points  in time.  In Elvish, this
       functionality is provided by lists of functions.

       There are current two hooks:

       • $edit:before-readline, whose elements are called before the editor reads code,  with  no
         arguments.

       • $edit:after-readline,  whose  elements  are  called, after the editor reads code, with a
         sole element -- the line just read.

       Example usage:

              edit:before-readline = [{ echo 'going to read' }]
              edit:after-readline = [[line]{ echo 'just read '$line }]

       Then every time you accept a chunk of code  (and  thus  leaving  the  editor),  just  read
       followed  by the code is printed; and at the very beginning of an Elvish session, or after
       a chunk of code is executed, going to read is printed.

       @elvdoc -ns edit: -dir ../pkg/edit