This article is part of the Beginner’s Guide to Elvish series:
-
Arguments and outputs
1. Arguments and quoting
Let’s take a closer look at some of the commands we’ve run:
Terminal - elvish
~> + 2 10 ▶ (num 12) ~> echo Hello, world! Hello, world!
In the first command, +
is given two arguments, 2
and 10
, separated by
spaces – so far so good.
In the second command, echo
is given Hello, world!
. Following how we read
the first command, this should also be two arguments. But this still achieved
what we want – printing out Hello, World!
– but how?
As it turns out, what’s happening with this simple command is actually not so simple:
-
Elvish recognizes
Hello, World!
as two arguments and passes them toecho
. -
The
echo
command receives two arguments and it joins them with a space before printing.
The consequence of this process can be better observed when you’d like to print multiple spaces:
Terminal - elvish
~> echo Hello, world! Hello, world!
Although we’ve used three spaces, all echo
receives is two arguments Hello,
and world!
, so all it can do is joining them back with a single space.
1.1. Quoting
In order to pass spaces to echo
, we can pass a quoted argument:
Terminal - elvish
~> echo 'Hello, world!' Hello, world!
A pair of single quotes delimits a quoted string, and tells Elvish that the
text inside it is a single argument. In this case, echo
only sees one argument
containing Hello, world
(with three spaces).
You can use quoted arguments wherever you can use an unquoted argument. In fact, you can even quote the command name itself. This applies to all the commands we have seen so far:
Terminal - elvish
~> '+' '2' '10' ▶ (num 12) ~> 'randint' '1' '7' ▶ (num 3)
However, writing commands like this is unnecessary and unreadable. It’s better to reserve quoting to situations when it’s necessary, for example when the argument you’d like to pass has spaces.
1.2. Metacharacters
Another common reason to use quoting is when your argument includes
metacharacters, characters with special meaning to Elvish. Some examples of
metacharacters are #
, which introduces a comment, and (
and )
, which we’ll
encounter soon. Quoting them stops Elvish from treating them as metacharacters:
Terminal - elvish
~> echo '(1) Rule #1' (1) Rule #1
We will learn more metacharacters as we learn more of Elvish’s syntax. As a rule
of thumb, punctuation marks in the
ASCII range tend to be
metacharacters, except those commonly found in file paths, like _
, -
, .
,
/
and \
.
1.3. Double quotes
You can also create quoted strings with double quotes, like "foo"
rather than
'foo'
. It’s useful when the string itself contains single quotes:
Terminal - elvish
~> echo "It's a wonderful world!" It's a wonderful world!
Another difference is that double quotes allow you to write special characters
using escape sequences that start with \
. For example, \n
inside double
quotes represents a newline:
Terminal - elvish
~> echo "old pond\nfrog leaps in\nwater's sound" old pond frog leaps in water's sound
You can read more about single-quoted strings and double-quoted strings in the language reference page.
2. Working with command outputs
Let’s go back to our arithmetic examples:
Terminal - elvish
~> + 2 10 # addition ▶ (num 12) ~> * 2 10 # multiplication ▶ (num 20)
What if we want to calculate something that involves multiple operations, like
3 * (2 + 10)
? Of course, we can simply run multiple commands:
Terminal - elvish
~> + 2 10 ▶ (num 12) ~> * 3 12 ▶ (num 36)
But this makes Elvish a really clumsy calculator! Instead, we can capture
the output of the +
command by placing it inside ()
, and use it as an
argument to the *
command:
Terminal - elvish
~> * (+ 2 10) 3 ▶ (num 36)
Now is also the time to explain the ▶
notation. It indicates that the output
is a value in Elvish’s data type system. In this case, (num ...)
is a
typed number, although for the purpose of passing to *
, (num 12)
and
12
work identically. We will learn more in Value types.
2.1. Concatenating results
Other than using the output of a command as an argument on its own, you can also concatenate it to something else to build a bigger argument. For example, if we want to add some message explaining what the result is:
Terminal - elvish
~> echo 'And the result is... '(* (+ 2 10) 3) And the result is... 36
(For the purpose of string concatenation, (num 36)
becomes just 36
.)
When the output of a command doesn’t start with ▶
, it indicates that the
output is a stream of bytes. For example, echo
produces bytes:
Terminal - elvish
~> echo Hello! Hello!
Among Elvish’s builtin commands, some output values, while some output bytes. On the other hand, external commands can only output bytes; they don’t have direct access to Elvish’s system of data types.
Let’s finish this section by augmenting our “Hello, World!” example with the output of a useful external commands:
Terminal - elvish
~> echo 'Hello World! My name is: '(whoami) Hello World! My name is: elf
3. Command history
We have now worked with quite a few commands, some more simple, some more complex. Inevitably, you’ll want to run some commands that are either the same or similar to something you have run in the past. This is where Elvish’s command history feature is useful.
For example, if we rolled the dice once with randint 1 7
and want to roll it
again, we can press ▲:
Terminal - elvish
~> randint 1 7 elf@host HISTORY #34
We are now in a history walking mode. The basic operations work as follows:
-
Press ▲ to go back further, or ▼ to go forward.
-
If you can’t find your command, press Esc to exit this mode cleanly.
-
Pressing any other key accepts the current entry and do what the key usually does. For example, simply pressing Enter will accept the entry and run it. If you want to edit the command before running it, just start editing by pressing Backspace, Ctrl-W, and so on.
Walking the history like this is the best option if the command is recent. To find a more distant command, you can use the history listing mode instead by pressing Ctrl-R:
Terminal - elvish
~> elf@host HISTORY (dedup on) Ctrl-D dedup 21 echo $pwd │ 22 * (+ 3 4) (- 100 94) │ 31 make │ 32 math:min 3 1 30 33 randint 1 7
This mode works very similarly to location mode we saw in Your first Elvish commands. You can use ▲ and ▼ to select an item, and press Enter to insert to it. Similarly, you can type part of the command to narrow down the list:
Terminal - elvish
~> elf@host HISTORY (dedup on) git Ctrl-D dedup 7 git branch 8 git checkout . 9 git commit 19 git status
4. Conclusion
In this part, we dived into the inner workings of arguments and quoting, and learned how to capture and use the output of commands, and the distinction between value output and byte output. We also learned how to recall command history. These skills will help you build and use more complex commands and use them with ease.
Let’s now move on to the next part, Variables and loops.