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">▲&#xfe0e;</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">▲&#xfe0e;</span>
    43      <span class="key">▼&#xfe0e;</span>
    44      <span class="key">◀&#xfe0e;</span>
    45      <span class="key">▶&#xfe0e;</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">▲&#xfe0e;</span>
    85      <span class="key">▼&#xfe0e;</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.