This is still the header! Main site

Emacs Shell Scripts

2022/02/27
This is post no. 86 for Kev Quirk's #100DaysToOffload challenge. The point is to write many things, not to write good ones. Please adjust quality expectations accordingly :)

This is one of those "let's write a post quickly" ones; this time, we'll be looking at threading in Emacs and whether we could use them to convert shell scripts into non-ugly-looking Emacs functions (something that we have already looked at for Common Lisp).

Our problem to solve is the following. Emacs has neat support for running a shell script in a buffer (just start a process for that buffer). It can, obviously, also run elisp code. However, running elisp code that calls into UNIX many times, like shell scripts do, is still not entirely trivial.

You can quickly launch a shell command with shell-command-to-string, however, given something like this:

(shell-command-to-string "sleep 3; echo stuff")
          

will do exactly what you'll want, but will also block the main Emacs thread, and thus is unsuitable for a shell-script-like thing that might be running for a longer time. Meanwhile, things like

(start-process
 "name-of-process-that-prints-stuff"
 "*buffer-that-gets-stuff*"
 "bash" "-c" "sleep 3; echo stuff")
          

... which will open a buffer, redirect the process output to it, and return immediately. We can even specify a sentinel function that gets called once the process exits... or we can process its output on the fly. One thing this is not: simple. You definitely don't want to do this for each line of your "shell script".

Options

Technically, Emacs does have threads since version 26. Apparently, it's a thin abstraction over pthreads, and as such, is prone to random lockups, leading to e.g. this verdict of "nobody should use Emacs threads for any purpose".

This is... not especially encouraging.

Meanwhile though, there seem to be async-await implementations like chuntaro's async-await or skeeto's emacs-aio.

These look like they'd be worth trying out! Looks like neither of them support actual shell commands though (... although neither of them seems too overengineered, so adding support should be relatively easy).

Giving us the next reasonable topic of this article: doing it.

However... keeping up with the general theme of Low Quality Articles, we'll leave this part for a followup one!

... comments welcome, either in email or on the (eventual) Mastodon post on Fosstodon.