Eschewing Zshell for Emacs Shell

2 min read Original article ↗

EShell is a Lisp REPL. The following works as you’d expect from such a REPL:

$ (message "hello world")
"hello world"

However, in a shell, we care more for simplicity and speed of typing that we do for semantic clearness, so we can, in this case, drop the parens with the same results:

$ message "hello world"
"hello world"

Functions that begin with eshell/ are available in Eshell without the prefix, so calling the eshell/echo function makes the shell experience less surprising:

$ echo "hello world"
"hello world"

If you put it in parens, you need to give it the full name:

$ (eshell/echo "hello world")
"hello world"

What about types? In a normal shell, everything is a string, but EShell has a foot in both worlds:

$ echo hello world
("hello" "world")

A list of two strings. However, you can NOT attempt to pass that echo to car… at least not directly:

$ car echo hello world

Returns an error, as does:

$ car (list hello world)

You see, once you bring in parens, you also bring in syntactic specific-ness, so you would need to do this:

$ car (list "hello" "world")

EShell has a listify that converts its arguments to a list of strings:

$ listify hello world
("hello" "world")

But if you want to pass that data to something like car, you need to surround it in curly braces, which is EShell’s way of saying, call some shell-like-goodness, but return it like Lisp:

$ car { listify hello world }
hello

Upon a cursory review, it appears little difference between a simple list and using listify, as under certain circumstance, they have the same behavior:

$ listify hello world
("hello" "world")

$ list hello world
("hello" "world")

$ listify 1 2 3
(1 2 3)

$ list 1 2 3
(1 2 3)

$ list "hello world"
(#("hello world" 0 11
   (escaped t)))

$ listify "hello world"
(#("hello world" 0 11
   (escaped t)))

However, I got the following message from David, who said:

The difference between listify and a ’list’ appears to be that calling listify on a list will not nest it in another list, e.g.

(eshell/listify '(1 2 3)) 
(list '(1 2 3)) 

Seems useful for a context where input may be a list, or not.