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

Introduction

       This  document describes the Elvish programming language.  It tries to be both a specification and an ad‐
       vanced tutorial; if it turns out to be impossible to do these two things at the same time, this  document
       will evolve to a formal specification, and more readable tutorials will be created.

       Examples  for  one  construct might use constructs that have not yet been introduced, so some familiarity
       with the language is assumed.  If you are new to Elvish, start with the learning materials (../learn/).

       Note to the reader.  Like Elvish itself, this document is a work in progress.  Some materials  are  miss‐
       ing,  and  some are documented sparingly.  If you have found something that should be improved -- even if
       there is already a "TODO" for it -- please feel free to ask on any of the chat channels advertised on the
       homepage (..).  Some developer will explain to you, and then update the document.  Question-driven  docu‐
       mentation :)

Syntax Convention

       Elvish  source code must be UTF-8-encoded.  In this document, character is a synonym of Unicode codepoint
       (https://en.wikipedia.org/wiki/Code_point) or its UTF-8 encoding.

       Also like most shells, Elvish uses whitespaces -- instead of commas, periods or semicolons -- to separate
       constructs.  In this document, an inline whitespace is any of:

       • A space (ASCII 0x20) or tab (ASCII 0x9, "\t");

       • A comment: starting with # and ending before the next newline or end of file;

       • Line continuation: a backslash followed by a newline.

       A whitespace is either an inline whitespace or a newline ("\n").

       Like most shells, Elvish has a syntax structure that can be divided into two levels:  a  statement  level
       and an expression level.  For instance, on the expression level, "echo" is a quoted string that evaluates
       to echo; but on the statement level, it is a command that outputs an empty line.  This distinction is of‐
       ten clear from the context and sometime the verb used.  A statements executes to produce side effects; an
       expression  evaluates  to  some  values.   (The  traditional  terms for the two levels are "commands" and
       "words", but those terms are quite ambiguous.)

String

       The most common data structure in shells is the string.  String literals can be quoted or unquoted (bare‐
       words).

   Quoted
       There are two types of quoted strings in Elvish, single-quoted strings and double-quoted strings.

       In single-quoted strings, all characters represent themselves, except single quotes,  which  need  to  be
       doubled.  For instance, '*\' evaluates to *\, and 'it''s' evaluates to it's.

       In  double-quoted strings, the backslash \ introduces a escape sequence.  For instance, "\n" evaluates to
       a newline; "\\" evaluates to a backslash; invalid escape sequences like "\*" result in a syntax error.

       TODO: Document the full list of supported escape sequences.

       Unlike most other shells, double-quoted strings do not support interpolation.  For instance, "$USER" sim‐
       ply evaluates to the string $USER.  To get a similar effect, simply concatenate strings: instead  of  "my
       name is $name", write "my name is "$name.  Under the hood this is a compound expression.

   Barewords
       If  a  string only consists of bareword characters, it can be written without any quote; this is called a
       bareword.  Examples are a.txt, long-bareword, and /usr/local/bin.  The set  of  bareword  characters  in‐
       clude:

       • ASCII letters (a-z and A-Z) and numbers (0-9);

       • The symbols -_:%+,./@!;

       • Non-ASCII  codepoints  that are printable, as defined by unicode.IsPrint (https://godoc.org/unicode#Is‐
         Print) in Go's standard library.

       The following are bareword characters depending on their position:

       • The tilde ~, unless it appears at the beginning of a compound expression, in which case it  is  subject
         to tilde expansion;

       • The equal sign =, unless it is used for terminating map keys or option keys, or denoting assignments or
         temporary assignments.

       Unlike traditional shells, an unquoted backslash \ does not escape metacharacters; use quoted strings in‐
       stead.   For  instance, to echo a star, write echo "*" or echo '*', not echo \*.  Unquote backslashes are
       now only used in line continuations; their use elsewhere is reserved will cause a syntax error.

   Notes
       The three syntaxes above all evaluate to strings, and they are interchangeable.  For instance, xyz, 'xyz'
       and "xyz" are different syntaxes for the same string, and they are always equivalent.

       Elvish does have a dedicated float64 number type, but it does not have a literal syntax; instead it needs
       to be constructed using a function call, as in put (float64 42); the argument 42 is a string.  For conve‐
       nience, all Elvish functions that expect number arguments also accept strings that can  be  parsed  as  a
       number, so explicit number constructors are not needed often.

List and Map

       Lists and maps are the basic container types in Elvish.

   List
       Lists are surround by square brackets [ ], with elements separated by whitespaces.  Examples:

              ~> put [lorem ipsum]
              ▶ [lorem ipsum]
              ~> put [lorem
                      ipsum
                      foo
                      bar]
              ▶ [lorem ipsum foo bar]

       Note  that  commas have no special meanings and are valid bareword characters, so don't use them to sepa‐
       rate elements:

              ~> li = [a, b]
              ~> put $li
              ▶ [a, b]
              ~> put $li[0]
              ▶ a,

   Map
       Maps are also surrounded by square brackets; a key/value pair is written &key=value (reminiscent to  HTTP
       query  parameters), and pairs are separated by whitespaces.  Whitespaces are allowed after =, but not be‐
       fore =.  Examples:

              ~> put [&foo=bar &lorem=ipsum]
              ▶ [&foo=bar &lorem=ipsum]
              ~> put [&a=   10
                      &b=   23
                      &sum= (+ 10 23)]
              ▶ [&a=10 &b=23 &sum=33]

       An empty map is written as [&].

Variable

       Variables are named holders of values.  The following characters can be used in variable names (a  subset
       of bareword characters):

       • ASCII letters (a-z and A-Z) and numbers (0-9);

       • The  symbols  -_:~.   The colon : is special; it is normally used for separating namespaces or denoting
         namespace variables;

       • Non-ASCII codepoints that are printable, as defined by  unicode.IsPrint  (https://godoc.org/unicode#Is‐
         Print) in Go's standard library.

       In  most  other  shells,  variables can map directly to environmental variables: $PATH is the same as the
       PATH environment variable.  This is not the case in Elvish.  Instead, environment variables are put in  a
       dedicated  E:  namespace;  the environment variable PATH is known as $E:PATH.  The $PATH variable, on the
       other hand, does not exist initially, and if you have defined it, only lives in a certain  lexical  scope
       within the Elvish interpreter.

       You  will  notice  that variables sometimes have a leading dollar $, and sometimes not.  The tradition is
       that they do when they are used for their values, and do not otherwise (e.g.  in  assignment).   This  is
       consistent with most other shells.

   Assignment
       A  variable can be assigned by writing its name, =, and the value to assign.  There must be inline white‐
       spaces both before and after =.  Example:

              ~> foo = bar

       You can assign multiple values to multiple variables simultaneously, simply by writing  several  variable
       names (separated by inline whitespaces) on the left-hand side, and several values on the right-hand side:

              ~> x y = 3 4

   Referencing
       Use a variable by adding $ before the name:

              ~> foo = bar
              ~> x y = 3 4
              ~> put $foo
              ▶ bar
              ~> put $x
              ▶ 3

       Variables must be assigned before use.  Attempting to use an unassigned variable causes a compilation er‐
       ror:

              ~> echo $x
              Compilation error: variable $x not found
              [tty], line 1: echo $x
              ~> { echo $x }
              Compilation error: variable $x not found
              [tty], line 1: { echo $x }

   Explosion and Rest Variable
       If  a  variable contains a list value, you can add @ before the variable name to get all its element val‐
       ues.  This is called exploding the variable:

              ~> li = [lorem ipsum foo bar]
              ~> put $li
              ▶ [lorem ipsum foo bar]
              ~> put $@li
              ▶ lorem
              ▶ ipsum
              ▶ foo
              ▶ bar

       (This notation is restricted to exploding variables.  To explode arbitrary values, use  the  builtin  ex‐
       plode (builtin.html#explode) command.)

       When  assigning  variables,  if  you prefix the name of the last variable with @, it gets assigned a list
       containing all remaining values.  That variable is called a rest variable.  Example:

              ~> a b @rest = 1 2 3 4 5 6 7
              ~> put $a $b $rest
              ▶ 1
              ▶ 2
              ▶ [3 4 5 6 7]

       Schematically this is a reverse operation to variable explosion, which is why they share the @ sign.

   Temporary Assignment
       You can prepend a command with temporary assignments, which gives variables temporarily values during the
       execution of that command.

       In the following example, $x and $y are temporarily assigned 100 and 200:

              ~> x y = 1 2
              ~> x=100 y=200 + $x $y
              ▶ 300
              ~> echo $x $y
              1 2

       In contrary to normal assignments, there should be no whitespaces around the equal sign =.  To have  mul‐
       tiple variables in the left-hand side, use braces:

              ~> x y = 1 2
              ~> fn f { put 100 200 }
              ~> {x,y}=(f) + $x $y
              ▶ 300

       If  you  use  a  previously undefined variable in a temporary assignment, its value will become the empty
       string after the command finishes.  This behavior will likely change; don't rely on it.

       Since ordinary assignments are also a kind of command, they can also be prepended with temporary  assign‐
       ments:

              ~> x=1
              ~> x=100 y = (+ 133 $x)
              ~> put $x $y
              ▶ 1
              ▶ 233

       Temporary  assignments  must all appear before the command.  As soon as something that is not a temporary
       assignments is parsed, Elvish no longer parses temporary assignments.  For instance, in x=1 echo x=1, the
       second x=1 is not a temporary assignment, but a bareword.

       Note: Elvish's behavior differs from bash (or zsh) in one important place.  In  bash,  temporary  assign‐
       ments to variables do not affect their direct appearance in the command:

              bash-4.4$ x=1
              bash-4.4$ x=100 echo $x
              1

   Scoping rule
       Elvish has lexical scoping.  Scopes are introduced by lambdas or user-defined modules.

       When  you use a variable, Elvish looks for it in the current lexical scope, then its parent lexical scope
       and so forth, until the outermost scope:

              ~> x = 12
              ~> { echo $x } # $x is in the global scope
              12
              ~> { y = bar; { echo $y } } # $y is in the outer scope
              bar

       If a variable is not in any of the lexical scopes, Elvish tries to resolve it in the builtin:  namespace,
       and if that also fails, cause an error:

              ~> echo $pid # builtin
              36613
              ~> echo $nonexistent
              Compilation error: variable $nonexistent not found
                [interactive], line 1:
                  echo $nonexistent

       Note that Elvish resolves all variables in a code chunk before starting to execute any of it; that is why
       the error message above says compilation error.  This can be more clearly observed in the following exam‐
       ple:

              ~> echo pre-error; echo $nonexistent
              Compilation error: variable $nonexistent not found
              [tty], line 1: echo pre-error; echo $nonexistent

       When you assign a variable, Elvish does a similar searching.  If the variable cannot be found, it will be
       created in the current scope:

              ~> x = 12
              ~> { x = 13 } # assigns to x in the global scope
              ~> echo $x
              13
              ~> { z = foo } # creates z in the inner scope
              ~> echo $z
              Compilation error: variable $z not found
              [tty], line 1: echo $z

       One implication of this behavior is that Elvish will not shadow your variable in outer scopes.

       There  is  a  local: namespace that always refers to the current scope, and by using it it is possible to
       force Elvish to shadow variables:

              ~> x = 12
              ~> { local:x = 13; echo $x } # force shadowing
              13
              ~> echo $x
              12

       After force shadowing, you can still access the variable in the outer  scope  using  the  up:  namespace,
       which always skips the innermost scope:

              ~> x = 12
              ~> { local:x = 14; echo $x $up:x }
              14 12

       The  local:  and up: namespaces can also be used on unshadowed variables, although they are not useful in
       those cases:

              ~> foo = a
              ~> { echo $up:foo } # $up:foo is the same as $foo
              a
              ~> { bar = b; echo $local:bar } # $local:bar is the same as $bar
              b

       It is not possible to refer to a specific outer scope.

       You cannot create new variables in the builtin: namespace, although existing variables in it can  be  as‐
       signed new values.

Lambda

       A function literal, or lambda, is a code chunk surrounded by curly braces:

              ~> f = { echo "Inside a lambda" }
              ~> put $f
              ▶ <closure 0x18a1a340>

       One  or  more  whitespace  characters after { is required: Elvish relies on the presence of whitespace to
       disambiguate lambda literals and braced lists.  It is good style to put some whitespace before the  clos‐
       ing } as well, but this is not required by the syntax.

       Functions  are first-class values in Elvish.  They can be kept in variables, used as arguments, output on
       the value channel, and embedded in other data structures.  They can also be used as commands:

              ~> $f
              Inside a lambda
              ~> { echo "Inside a literal lambda" }
              Inside a literal lambda

       The last command resembles a code block in C-like languages in syntax.  But under the hood, it defines  a
       function on the fly and calls it immediately.

       Functions  defined  using  the  basic syntax above do not accept any arguments or options.  To do so, you
       need to write a signature.

   Signature
       A signature specifies the arguments a function can accept:

              ~> f = [a b]{ put $b $a }
              ~> $f lorem ipsum
              ▶ ipsum
              ▶ lorem

       There should be no space between ] and {; otherwise Elvish will parse the signature as a  list,  followed
       by a lambda without signature:

              ~> put [a]{ nop }
              ▶ <closure 0xc420153d80>
              ~> put [a] { nop }
              ▶ [a]
              ▶ <closure 0xc42004a480>

       Like in the left hand of assignments, if you prefix the last argument with @, it becomes a rest argument,
       and its value is a list containing all the remaining arguments:

              ~> f = [a @rest]{ put $a $rest }
              ~> $f lorem
              ▶ lorem
              ▶ []
              ~> $f lorem ipsum dolar sit
              ▶ lorem
              ▶ [ipsum dolar sit]

       You  can also declare options in the signature.  The syntax is &name=default (like a map pair), where de‐
       fault is the default value for the option:

              ~> f = [&opt=default]{ echo "Value of $opt is "$opt }
              ~> $f
              Value of $opt is default
              ~> $f &opt=foobar
              Value of $opt is foobar

       Options must have default values: Options should be optional.

       If you call a function with too few arguments, too many arguments or unknown  options,  an  exception  is
       thrown:

              ~> [a]{ echo $a } foo bar
              Exception: need 1 arguments, got 2
              [tty], line 1: [a]{ echo $a } foo bar
              ~> [a b]{ echo $a $b } foo
              Exception: need 2 arguments, got 1
              [tty], line 1: [a b]{ echo $a $b } foo
              ~> [a b @rest]{ echo $a $b $rest } foo
              Exception: need 2 or more arguments, got 1
              [tty], line 1: [a b @rest]{ echo $a $b $rest } foo
              ~> [&k=v]{ echo $k } &k2=v2
              Exception: unknown option k2
              [tty], line 1: [&k=v]{ echo $k } &k2=v2

   Closure Semantics
       User-defined   functions   are   also   known   as   "closures",  because  they  have  closure  semantics
       (https://en.wikipedia.org/wiki/Closure_(computer_programming)).

       In the following example, the make-adder function outputs two functions, both referring to a local  vari‐
       able $n.  Closure semantics means that:

       1. Both functions can continue to refer to the $n variable after make-adder has returned.

       2. Multiple calls to the make-adder function generates distinct instances of the $n variables.

          ~> fn make-adder {
               n = 0
               put { put $n } { n = (+ $n 1) }
             }
          ~> getter adder = (make-adder)
          ~> $getter # $getter outputs $n
          ▶ 0
          ~> $adder # $adder increments $n
          ~> $getter # $getter and $setter refer to the same $n
          ▶ 1
          ~> getter2 adder2 = (make-adder)
          ~> $getter2 # $getter2 and $getter refer to different $n
          ▶ 0
          ~> $getter
          ▶ 1

       Variables that get "captured" in closures are called upvalues; this is why the pseudo-namespace for vari‐
       ables  in  outer  scopes is called up:.  When capturing upvalues, Elvish only captures the variables that
       are used.  In the following example, $m is not an upvalue of $g because it is not used:

              ~> fn f { m = 2; n = 3; put { put $n } }
              ~> g = (f)

       This effect is not currently observable,  but  will  become  so  when  namespaces  become  introspectable
       (https://github.com/elves/elvish/issues/492).

Indexing

       Indexing is done by putting one or more index expressions in brackets [] after a value.

   List Indexing
       Lists can be indexed with any of the following:

       • A  non-negative integer, an offset counting from the beginning of the list.  For example, $li[0] is the
         first element of $li.

       • A negative integer, an offset counting from the back of the list.  For instance, $li[-1]  is  the  last
         element $li.

       • A  slice $a:$b, where both $a and $b are integers.  The result is sublist of $li[$a] up to, but not in‐
         cluding, $li[$b].  For instance, $li[4:7] equals [$li[4] $li[5] $li[6]], while $li[1:-1]  contains  all
         elements from $li except the first and last one.

         Both  integers  may  be omitted; $a defaults to 0 while $b defaults to the length of the list.  For in‐
         stance, $li[:2] is equivalent to $li[0:2], $li[2:] is equivalent  to  $li[2:(count  $li)],  and  $li[:]
         makes a copy of $li.  The last form is rarely useful, as lists are immutable.

         Note  that  the slice needs to be a single string, so there cannot be any spaces within the slice.  For
         instance, $li[2:10] cannot be written as $li[2: 10]; the latter contains two indicies and is equivalent
         to $li[2:] $li[10] (see Multiple Indicies).

       • Not yet implemented: The string @.  The result is all the values in the list.  Note that  this  is  not
         the  same  as  :: if $li has 10 elements, $li[@] evaluates to 10 values (all the elements in the list),
         while $li[:] evaluates to just one value (a copy of the list).

         When used on a variable like $li, it is equivalent to the explosion construct $li[@].   It  is  useful,
         however, when used on other constructs, like output capture or other

       Examples:

              ~> li = [lorem ipsum foo bar]
              ~> put $li[0]
              ▶ lorem
              ~> put $li[-1]
              ▶ bar
              ~> put $li[0:2]
              ▶ [lorem ipsum]

       (Negative indicies and slicing are borrowed from Python.)

   String indexing
       NOTE: String indexing will likely change.

       Strings  should always be UTF-8, and they can indexed by byte indicies at which codepoints start, and in‐
       dexing results in the codepoint that starts there.  This is best explained with examples:

       • In the string elv, every codepoint is encoded with only one byte, so 0, 1, 2 are all valid indices:

                ~> put elv[0]
                ▶ e
                ~> put elv[1]
                ▶ l
                ~> put elv[2]
                ▶ v

       • In the string 世界, each codepoint is encoded with three bytes.  The first codepoint  occupies  byte  0
         through 2, and the second occupies byte 3 through 5.  Hence valid indicies are 0 and 3:

                ~> put 世界[0]
                ▶ 世
                ~> put 世界[3]
                ▶ 界

       Strings can also be indexed by slices.

       (This idea of indexing codepoints by their byte positions is borrowed from Julia.)

   Map indexing
       Maps  are  simply indexed by their keys.  There is no slice indexing, and : does not have a special mean‐
       ing.  Examples:

              ~> map = [&a=lorem &b=ipsum &a:b=haha]
              ~> echo $map[a]
              lorem
              ~> echo $map[a:b]
              haha

   Multiple Indices
       If you put multiple values in the index, you get multiple values: $li[x y  z]  is  equivalent  to  $li[x]
       $li[y] $li[z].  This applies to all indexable values.  Examples:

              ~> put elv[0 2 0:2]
              ▶ e
              ▶ v
              ▶ el
              ~> put [lorem ipsum foo bar][0 2 0:2]
              ▶ lorem
              ▶ foo
              ▶ [lorem ipsum]
              ~> put [&a=lorem &b=ipsum &a:b=haha][a a:b]
              ▶ lorem
              ▶ haha

Output Capture

       Output  capture  is formed by putting parentheses () around a code chunk.  It redirects the output of the
       chunk into an internal pipe, and evaluates to all the values that have been output.

              ~> + 1 10 100
              ▶ 111
              ~> x = (+ 1 10 100)
              ~> put $x
              ▶ 111
              ~> put lorem ipsum
              ▶ lorem
              ▶ ipsum
              ~> x y = (put lorem ipsum)
              ~> put $x
              ▶ lorem
              ~> put $y
              ▶ ipsum

       If the chunk outputs bytes, Elvish strips the last newline (if any), and split them by newlines, and con‐
       sider each line to be one string value:

              ~> put (echo "a\nb")
              ▶ a
              ▶ b

       Note 1.  Only the last newline is ever removed, so empty lines are preserved; (echo "a\n")  evaluates  to
       two values, "a" and "".

       Note  2.   One consequence of this mechanism is that you can not distinguish outputs that lack a trailing
       newline from outputs that have one; (echo what) evaluates to the same value as (print what).  If  such  a
       distinction is needed, use slurp (builtin.html#slurp) to preserve the original bytes output.

       If  the chunk outputs both values and bytes, the values of output capture will contain both value outputs
       and lines.  However, the ordering between value output and byte output might not agree with the order  in
       which they happened:

              ~> put (put a; echo b) # value order need not be the same as output order
              ▶ b
              ▶ a

Exception Capture

       Exception  capture  is formed by putting ?() around a code chunk.  It runs the chunk and evaluates to the
       exception it throws.

              ~> fail bad
              Exception: bad
              Traceback:
                [interactive], line 1:
                  fail bad
              ~> put ?(fail bad)
              ▶ ?(fail bad)

       If there was no error, it evaluates to the special value $ok:

              ~> nop
              ~> put ?(nop)
              ▶ $ok

       Exceptions are booleanly false and $ok is booleanly true.  This is useful in if (introduced later):

              if ?(test -d ./a) {
                # ./a is a directory
              }

       Exception captures do not affect the output of the code chunk.  You can combine output capture and excep‐
       tion capture:

              output = (error = ?(commands-that-may-fail))

Tilde Expansion

       Tildes are special when they appear at the beginning of an expression (the exact meaning of  "expression"
       will  be  explained later).  The string after it, up to the first / or the end of the word, is taken as a
       user name; and they together evaluate to the home directory of that user.  If the user name is empty, the
       current user is assumed.

       In the following example, the home directory of the current user is /home/xiaq, while that  of  the  root
       user is /root:

              ~> put ~
              ▶ /home/xiaq
              ~> put ~root
              ▶ /root
              ~> put ~/xxx
              ▶ /home/xiaq/xxx
              ~> put ~root/xxx
              ▶ /root/xxx

       Note that tildes are not special when they appear elsewhere in a word:

              ~> put a~root
              ▶ a~root

       If you need them to be, surround them with braces (the reason this works will be explained later):

              ~> put a{~root}
              ▶ a/root

Wildcard Patterns

       Wildcard patterns are patterns containing wildcards, and they evaluate to all filenames they match.

       We will use this directory tree in examples:

              .x.conf
              a.cc
              ax.conf
              foo.cc
              d/
              |__ .x.conf
              |__ ax.conf
              |__ y.cc
              .d2/
              |__ .x.conf
              |__ ax.conf

       Elvish supports the following wildcards:

       • ? matches one arbitrary character except /.  For example, ?.cc matches a.cc;

       • * matches any number of arbitrary characters except /.  For example, *.cc matches a.cc and foo.cc;

       • ** matches any number of arbitrary characters including /.  For example, **.cc matches a.cc, foo.cc and
         b/y.cc.

       The following behaviors are default, although they can be altered by modifiers:

       • When the entire wildcard pattern has no match, an error is thrown.

       • None of the wildcards matches . at the beginning of filenames.  For example:

         • ?x.conf does not match .x.conf;

         • d/*.conf does not match d/.x.conf;

         • **.conf does not match d/.x.conf.

   Modifiers
       Wildcards  can  be  modified  using  the same syntax as indexing.  For instance, in *[match-hidden] the *
       wildcard  is  modified  with  the  match-hidden  modifier.   Multiple  matchers  can  be   chained   like
       *[set:abc][range:0-9].  There are two kinds of modifiers:

       Global modifiers apply to the whole pattern and can be placed after any wildcard:

       • nomatch-ok tells Elvish not to throw an error when there is no match for the pattern.  For instance, in
         the example directory put bad* will be an error, but put bad*[nomatch-ok] does exactly nothing.

       • but:xxx (where xxx is any filename) excludes the filename from the final result.

       Although  global modifiers affect the entire wildcard pattern, you can add it after any wildcard, and the
       effect is the same.  For example, put */*[nomatch-ok].cpp and put *[nomatch-ok]/*.cpp do the same thing.

       On the other hand, you must add it after a wildcard, instead of after the entire pattern: put */*.cpp[no‐
       match-ok] unfortunately does not do the correct thing.  (This will probably be fixed.)

       Local modifiers only apply to the wildcard it immediately follows:

       • match-hidden tells the wildcard to match . at the beginning of  filenames,  e.g.   *[match-hidden].conf
         matches .x.conf and ax.conf.

         Being  a  local  modifier,  it  only  applies  to  the  wildcard it immediately follows.  For instance,
         *[match-hidden]/*.conf matches d/ax.conf and .d2/ax.conf, but not d/.x.conf or .d2/.x.conf.

       • Character matchers restrict the characters to match:

         • Character sets, like set:aeoiu;

         • Character ranges like range:a-z (including z) or range:a~z (excluding z);

         • Character classes: control, digit, graphic, letter, lower, mark, number, print, punct, space, symbol,
           title, and upper.  See the Is* functions here (https://godoc.org/unicode) for their definitions.

         Note the following caveats:

         • Multiple matchers, they are OR'ed.  For instance, ?[set:aeoiu][digit] matches aeoiu and digits.

         • Dots at the beginning of filenames always require an explicit match-hidden, even if the  matcher  in‐
           cludes  ..   For  example,  ?[set:.a]x.conf  does  not match .x.conf; you have to ?[set:.a match-hid‐
           den]x.conf.

         • Likewise, you always need to use ** to match slashes, even if the matcher includes  /.   For  example
           *[set:abc/] is the same as *[set:abc].

Compound Expression and Braced Lists

       Writing several expressions together with no space in between will concatenate them.  This creates a com‐
       pound expression, because it mimics the formation of compound words in natural languages.  Examples:

              ~> put 'a'b"c" # compounding three string literals
              ▶ abc
              ~> v = value
              ~> put '$v is '$v # compounding one string literal with one string variable
              ▶ '$v is value'

       Many  constructs  in  Elvish can generate multiple values, like indexing with multiple indices and output
       captures.  Compounding multiple values with other values generates all possible combinations:

              ~> put (put a b)-(put 1 2)
              ▶ a-1
              ▶ a-2
              ▶ b-1
              ▶ b-2

       Note the order of the generated values.  The value that comes later changes faster.

       NOTE: There is a perhaps a better way to explain the ordering, but you can think of the previous code  as
       equivalent to this:

              for x [a b] {
                for y [1 2] {
                  put $x-$y
                }
              }

   Braced Lists
       In practice, you never have to write (put a b): you can use a braced list {a,b}:

              ~> put {a,b}-{1,2}
              ▶ a-1
              ▶ a-2
              ▶ b-1
              ▶ b-2

       Elements  in  braced  lists  can also be separated with whitespaces, or a combination of comma and white‐
       spaces (the latter not recommended):

              ~> put {a b , c,d}
              ▶ a
              ▶ b
              ▶ c
              ▶ d

       (In future, the syntax might be made more strict.)

       Braced list is merely a syntax for grouping multiple values.  It is not a data structure.

Expression Structure and Precedence

       Braced lists are evaluated before being compounded with other values.  You can use this to affect the or‐
       der of evaluation.  For instance, put *.txt gives you all filenames that end with .txt in the current di‐
       rectory; while put {*}.txt gives you all filenames in the current directory, appended with .txt.

       TODO: document evaluation order regarding tilde and wildcards.

Ordinary Command

       The command is probably the most important syntax construct in shell languages, and Elvish is  no  excep‐
       tion.   The  word  command itself, is overloaded with meanings.  In the terminology of this document, the
       term command include the following:

       • An ordinary assignment, introduced above;

       • An ordinary command, introduced in this section;

       • A special command, introduced in the next section.

       An ordinary command consists of a compulsory head, and any number of arguments, options and redirections.

   Head
       The head must appear first.  It is an arbitrary word that determines what will be run.  Examples:

              ~> ls -l # the string ls is the head
              (output omitted)
              ~> (put [@a]{ ls $@a }) -l
              (same output)

       The head must evaluate to one value.  For instance, the following does not work:

              ~> (put [@a]{ ls $@a } -l)
              Exception: head of command must be a single value; got 2 values
              [tty], line 1: (put [@a]{ ls $@a } -l)

       The definition of barewords is relaxed for the head to include <, >, * and ^.  These are all names of nu‐
       meric builtins:

              ~> < 3 5 # less-than
              ▶ $true
              ~> > 3 5 # greater-than
              ▶ $false
              ~> * 3 5 # multiplication
              ▶ 15
              ~> ^ 3 5 # power
              ▶ 243

   Arguments and Options
       Arguments (args for short) and options (opts for short) can be supplied to commands.  Arguments are arbi‐
       trary words, while options have the same syntax as map pairs.  They are separated by inline whitespaces:

              ~> echo &sep=, a b c # seq=, is an option; a b c are arguments
              a,b,c

   Redirections
       Redirections are used for modifying file descriptors (FD).

       The most common form of redirections opens a file and associates it with an FD.  The form consists of  an
       optional destination FD (like 2), a redirection operator (like >) and a filename (like error.log):

       • The destination fd determines which FD to modify.  It can be given either as a number, or one of stdin,
         stdout  and  stderr.   There  must  be  no space between the FD and the redirection operator; otherwise
         Elvish will parse it as an argument.

         The destination FD can be omitted, in which case it is inferred from the redirection operator.

       • The redirection operator determines the mode to open the file, and the destination FD if it is not  ex‐
         plicitly specified.

       • The filename names the file to open.

       Possible redirection operators and their default FDs are:

       • < for reading.  The default FD is 0 (stdin).

       • > for writing.  The default FD is 1 (stdout).

       • >> for appending.  The default FD is 1 (stdout).

       • <> for reading and writing.  The default FD is 1 (stdout).

       Examples:

              ~> echo haha > log
              ~> cat log
              haha
              ~> cat < log
              haha
              ~> ls --bad-arg 2> error
              Exception: ls exited with 2
              Traceback:
                [interactive], line 1:
                  ls --bad-arg 2> error
              ~> cat error
              /bin/ls: unrecognized option '--bad-arg'
              Try '/bin/ls --help' for more information.

       Redirections  can  also  be  used for closing or duplicating FDs.  Instead of writing a filename, use &fd
       (where fd is a number, or any of stdin, stdout and stderr) for duplicating, or &- for closing.   In  this
       case, the redirection operator only determines the default destination FD (and is totally irrevelant if a
       destination FD is specified).  Examples:

              ~> ls >&- # close stdout
              /bin/ls: write error: Bad file descriptor
              Exception: ls exited with 2
              Traceback:
                [interactive], line 1:
                  ls >&-

       If you have multiple related redirections, they are applied in the order they appear.  For instance:

              ~> fn f { echo out; echo err >&2 } # echoes "out" on stdout, "err" on stderr
              ~> f >log 2>&1 # use file "log" for stdout, then use (changed) stdout for stderr
              ~> cat log
              out
              err

   Ordering
       Elvish does not impose any ordering of arguments, options and redirections: they can intermix each other.
       The  only requirement is that the head must come first.  This is different from POSIX shells, where redi‐
       rections may appear before the head.  For instance, the following two both work in POSIX shell, but  only
       the former works in Elvish:

              echo something > file
              > file echo something # mistaken for the comparison builtin ">" in Elvish

Special Commands

       Special  commands obey the same syntax rules as normal commands (i.e.  syntactically special commands can
       be treated the same as ordinary commands), but have evaluation rules that are custom to each command.  To
       explain this, we use the following example:

              ~> or ?(echo x) ?(echo y) ?(echo z)
              x
              ▶ $ok

       In the example, the or command first evaluates its first argument, which has the value $ok (a truish val‐
       ue) and the side effect of outputting x.  Due to the custom evaluation rule of or, the rest of the  argu‐
       ments are not evaluated.

       If  or  were a normal command, the code above is still syntactically correct.  However, Elvish would then
       evaluate all its arguments, with the side effect of outputting x, y and z, before calling or.

   Deleting variable or element: del
       The del special command can be used to either delete variables or elements of lists and  maps.   Operands
       should be specified without a leading dollar sign, like the left-hand side of assignments.

       Example of deleting variable:

              ~> x = 2
              ~> echo $x
              2
              ~> del x
              ~> echo $x
              Compilation error: variable $x not found
              [tty], line 1: echo $x

       Example of deleting element:

              ~> m = [&k=v &k2=v2]
              ~> del m[k2]
              ~> put $m
              ▶ [&k=v]
              ~> l = [[&k=v &k2=v2]]
              ~> del l[0][k2]
              ~> put $l
              ▶ [[&k=v]]

   Logics: and and or
       The and special command evaluates its arguments from left to right; as soon as a booleanly false value is
       obtained, it outputs the value and stops.  When given no arguments, it outputs $true.

       The  or  special  command is the same except that it stops when a booleanly true value is obtained.  When
       given no arguments, it outpus $false.

   Condition: if
       TODO: Document the syntax notation, and add more examples.

       Syntax:

              if <condition> {
                  <body>
              } elif <condition> {
                  <body>
              } else {
                  <else-body>
              }

       The if special command goes through the conditions one by one: as soon as one evaluates  to  a  booleanly
       true  value,  its  corresponding  body is executed.  If none of conditions are booleanly true and an else
       body is supplied, it is executed.

       The condition part is an expression, not a command like in other shells.  Example:

              fn tell-language [fname]{
                  if (has-suffix $fname .go) {
                      echo $fname" is a Go file!"
                  } elif (has-suffix $fname .c) {
                      echo $fname" is a C file!"
                  } else {
                      echo $fname" is a mysterious file!"
                  }
              }

       The condition part must be syntactically a single expression, but it can evaluate to multiple values,  in
       which case they are and'ed:

              if (put $true $false) {
                  echo "will not be executed"
              }

       If the expression evaluates to 0 values, it is considered true, consistent with how and works.

       Tip: a combination of if and ?() gives you a semantics close to other shells:

              if ?(test -d .git) {
                  # do something
              }

       However,  for Elvish's builtin predicates that output values instead of throw exceptions, the output cap‐
       ture construct () should be used.

   Conditional Loop: while
       Syntax:

              while <condition> {
                  <body>
              } else {
                  <else-body>
              }

       Execute the body as long as the condition evaluates to a booleanly true value.

       The else body, if present, is executed if the body has never been executed (i.e.  the condition evaluates
       to a booleanly false value in the very beginning).

   Iterative Loop: for
       Syntax:

              for <var> <container> {
                  <body>
              } else {
                  <body>
              }

       Iterate the container (e.g.  a list).  In each iteration, assign the variable to an element of  the  con‐
       tainer and execute the body.

       The else body, if present, is executed if the body has never been executed (i.e.  the iteration value has
       no elements).

   Exception Control: try
       (If  you just want to capture the exception, you can use the more concise exception capture construct ?()
       instead.)

       Syntax:

              try {
                  <try-block>
              } except except-varname {
                  <except-block>
              } else {
                  <else-block>
              } finally {
                  <finally-block>
              }

       Only try and try-block are required.  This control structure behaves as follows:

       1. The try-block is always executed first.

       2. If except is present and an exception occurs in try-block, it is caught and stored in  except-varname,
          and except-block is then executed.  Example:

                  ~> try { fail bad } except e { put $e }
                  ▶ ?(fail bad)

           Note  that  if  except is not present, exceptions thrown from try are not caught: for instance, try {
           fail bad } throws bad; it is equivalent to a plain fail bad.

           Note that the word after except names a variable, not a matching condition.   Exception  matching  is
           not  supported  yet.  For instance, you may want to only match exceptions that were created with fail
           bad with except bad, but in fact this creates a variable $bad that contains  whatever  exception  was
           thrown.

       3. If no exception occurs and else is present, else-block is executed.  Example:

                  ~> try { nop } else { echo well }
                  well

       4. If finally-block is present, it is executed.  Examples:

                  ~> try { fail bad } finally { echo final }
                  final
                  Exception: bad
                  Traceback:
                    [tty], line 1:
                      try { fail bad } finally { echo final }
                  ~> try { echo good } finally { echo final }
                  good
                  final

       5. If the exception was not caught (i.e.  except is not present), it is rethrown.

       Exceptions  thrown  in blocks other than try-block are not caught.  If an exception was thrown and either
       except-block or finally-block throws another exception, the original exception is lost.  Examples:

              ~> try { fail bad } except e { fail worse }
              Exception: worse
              Traceback:
                [tty], line 1:
                  try { fail bad } except e { fail worse }
              ~> try { fail bad } except e { fail worse } finally { fail worst }
              Exception: worst
              Traceback:
                [tty], line 1:
                  try { fail bad } except e { fail worse } finally { fail worst }

   Function Definition: fn
       Syntax:

              fn <name> <lambda>

       Define a function with a given name.  The function behaves in the same way to the lambda used  to  define
       it,  except that it "captures" return.  In other words, return will fall through lambdas not defined with
       fn, and continues until it exits a function defined with fn:

              ~> fn f {
                   { echo a; return }
                   echo b # will not execute
                 }
              ~> f
              a
              ~> {
                   f
                   echo c # executed, because f "captures" the return
                 }
              a
              c

       TODO: Find a better way to describe this.  Hopefully the example is illustrative enough, though.

       Under the hood, fn defines a variable with the given name plus ~ (see command resolution).

Command Resolution

       When using a literal string as the head of a command, it is first resolved during the compilation  phase,
       using the following order:

       1. If the name matches any of the special commands, it is treated as so.

       2. Finding a variable with the name of the command plus a ~ suffix.

           For  instance,  given a command f a b, Elvish looks for the variable $f~, using the ordinary variable
           scoping rule, except that resolution failures do not cause errors but fall back to the next step.

           Functions defined with fn as well as builtin functions are actually variables  with  a  ~  suffix  in
           their names.

       3. External commands.

           This  step  always  succeeds  during  compilation, even if the command does not exist.  Later, during
           evaluation, a searching step determines whether the external command exists.

       The entire resolution procedure can be emulated with the resolve (builtin.html#resolve) command.  Search‐
       ing of external commands can be emulated with the search-external (builtin.html#search-builtin) command.

Pipeline

       A pipeline is formed by joining one or more commands together with the pipe sign (|).

   IO Semantics
       For each pair of adjacent commands a | b, the output of a is connected to the input of b.  Both the  byte
       pipe and the value channel are connected, even if one of them is not used.

       Command  redirections  are applied before the connection happens.  For instance, the following writes foo
       to a.txt instead of the output:

              ~> echo foo > a.txt | cat
              ~> cat a.txt
              foo

   Execution Flow
       All of the commands in a pipeline are executed in parallel, and the execution of  the  pipeline  finishes
       when all of its commands finish execution.

       If  one or more command in a pipeline throws an exception, the other commands will continue to execute as
       normal.  After all commands finish execution, an exception is thrown, the value of which depends  on  the
       number of commands that have thrown an exception:

       • If only one command has thrown an exception, that exception is rethrown.

       • If  more  than one commands have thrown exceptions, a "composite exception", containing information all
         exceptions involved, is thrown.

   Background Pipeline
       Adding an ampersand & to the end of a pipeline will cause it to be executed in the background.   In  this
       case,  the  rest  of  the code chunk will continue to execute without waiting for the pipeline to finish.
       Exceptions thrown from the background pipeline do not affect the code chunk that contains it.

       When a background pipeline finishes, a message is printed to the terminal if the shell is interactive.

Code Chunk

       A code chunk is formed by joining zero or more pipelines together, separating them with  either  newlines
       or semicolons.

       Pipelines  in  a code chunk are executed in sequence.  If any pipeline throws an exception, the execution
       of the whole code chunk stops, propagating that exception.

Exception and Flow Commands

       Exceptions have similar semantics to those in  Python  or  Java.   They  can  be  thrown  with  the  fail
       (builtin.html#fail) command and caught with either exception capture ?() or the try special command.

       If an external command exits with a non-zero status, Elvish treats that as an exception.

       Flow  commands  --  break,  continue and return -- are ordinary builtin commands that raise special "flow
       control" exceptions.  The for and while commands capture break and continue, while fn modifies  its  clo‐
       sure to capture return.

       One  interesting  implication  is that since flow commands are just ordinary commands you can build func‐
       tions on top of them.  For instance, this function breaks randomly:

              fn random-break {
                if eq (randint 2) 0 {
                  break
                }
              }

       The function random-break can then be used in for-loops and while-loops.

       Note that the return flow control exception is only captured by functions  defined  with  fn.   It  falls
       through ordinary lambdas:

              fn f {
                {
                  # returns f, falling through the innermost lambda
                  return
                }
              }

Namespaces and Modules

       Namespace in Elvish helps prevent name collisions and is important for building modules.

   Syntax
       Prepend namespace: to command names and variable names to specify the namespace.  The following code

              e:echo $E:PATH

       uses  the  echo  command from the e: namespace and the PATH variable from the E: namespace.  The colon is
       considered part of the namespace name.

       Namespaces may be nested; for example, calling edit:location:start first finds the edit:  namespace,  and
       then the location: namespace inside it, and then call the start function within the nested namespace.

   Special Namespaces
       The following namespaces have special meanings to the language:

       • local: and up: refer to lexical scopes, and have been documented above.

       • e: refers to externals.  For instance, e:ls refers to the external command ls.

         Most  of the time you can rely on the rules of command resolution and do not need to use this explicit‐
         ly, unless a function defined by you (or an Elvish builtin) shadows an external command.

       • E: refers to environment variables.  For instance, $E:USER is the environment variable USER.

         This is always needed, because unlike command resolution, variable resolution does not fall  back  onto
         environment variables.

       • builtin: refers to builtin functions and variables.

         You don't need to use this explicitly unless you have defined names that shadows builtin counterparts.

   Pre-Defined Modules
       Namespaces  that are not special (i,e.  one of the above) are also called modules.  Aside from these spe‐
       cial namespaces, Elvish also comes with the following modules:

       • edit: for accessing the Elvish editor.  This module is available in interactive mode and does not  need
         importing.

         See reference (edit.html).

       • re: for regular expression facilities.  This module is always available.  See reference (re.html).

       • daemon: for manipulating the daemon.  This module is always available.

         This is not yet documented.

   User-Defined Modules
       You  can  define your own modules with Elvishscript by putting them under ~/.elvish/lib and giving them a
       .elv extension.  For instance, to define a module named a, store it in ~/.elvish/lib/a.elv:

              ~> cat ~/.elvish/lib/a.elv
              echo "mod a loading"
              fn f {
                echo "f from mod a"
              }

       To import the module, use use:

              ~> use a
              mod a loading
              ~> a:f
              f from mod a

       Modules in nested directories can also be imported.  For  example,  if  you  have  defined  a  module  in
       ~/.elvish/lib/x/y/z.elv, you can import it by using use x/y/z, and the resulting namespace will be z::

              ~> cat .elvish/lib/x/y/z.elv
              fn f {
                echo "f from x/y/z"
              }
              ~> use x/y/z
              ~> z:f
              f from x/y/z

       In  general,  if you import a module from a nested directory, the resulting namespace will be the same as
       the file name (without the .elv extension).

   Aliasing
       You can import a module as a namespace of your choice by specifying a second argument to use.  For  exam‐
       ple, to import x/y/z as a xyz namespace, you can use use x/y/z xyz:

              ~> use x/y/z xyz
              ~> xyz:f
              f from x/y/z

       This  is  especially useful when you need to import several modules that are in different directories but
       have the same file name.

   Scoping of Imports
       Namespace imports are lexically scoped.  For instance, if you use a module within an inner scope,  it  is
       not available outside that scope:

              {
                  use some-mod
                  some-mod:some-func
              }
              some-mod:some-func # not valid

       The  imported  modules  themselves are also evaluated in a separate scope.  That means that functions and
       variables defined in the module does not pollute the default namespace, and vice versa.  For instance, if
       you define ls as a wrapper function in rc.elv:

              fn ls [@a]{
                  e:ls --color=auto $@a
              }

       That definition is not visible in module files: ls will still refer to the external  command  ls,  unless
       you shadow it in the very same module.

   Re-Importing
       Modules  are  cached  after one import.  Subsequent imports do not re-execute the module; they only serve
       the bring it into the current scope.  Moreover, the cache is keyed by the path of  the  module,  not  the
       name under which it is imported.  For instance, if you have the following in ~/.elvish/lib/a/b.elv:

              echo importing

       The following code only prints one importing:

              { use a/b }
              use a/b # only brings mod into the lexical scope

       As does the following:

              use a/b
              use a/b

Elvish 0.13                                       Oct 10, 2022                                elvish-language(7)