-- Leo's gemini proxy

-- Connecting to gem.librehacker.com:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Emacs as a Shell: Part 1 (publ. 2024-05-06)


I've been reading various Internet documents lately on this subject, and exploring it in my own processes. So I feel like I want to share my ruminations. When the idea of using Emacs as a shell is discussed, one or more of these ideas are actually meant:


1. Using the bash shell from Emacs

2. Using Emacs as a terminal emulator

3. Using Emacs to interact with the system


With ideas 1 and 2, typically the goal is to get a good terminal emulator running in Emacs and then proceed to interact with the system through the bash shell. More and more, I feel that this approach is misguided. Emacs provides a much nicer and more powerful interface to the system than bash, or any other command line shell, due to the Emacs interface itself — e.g., all the great tools we have for launching commands and completions with keyboard shortcuts — and also the built-in elisp engine.


As far as using Emacs as a terminal emulator, this of course is possible through several different commands and packages, with various levels of frustration involved. But by using Emacs as a terminal emulator, what we really mean is that we want Emacs to behave just like an ANSI terminal, so that external programs like mutt, less, etc. can assume that i/o interface, and look and behave exactly like we are used to seeing in a terminal emulator like Gnome console. Of course that sometimes is useful, but really we are giving up the much nicer 2D Emacs text interface for the inferior ANSI interface.


To enjoy the productivity and liberation that Emacs and Elisp offers us, we should aim rather for idea 3. When we say "interact with the system", what we mean is interacting with our filesystem and external programs. If we can do this in a practical way, then we don't need bash or any of the other shells, except of course to run external programs and scripts that use them.


How to approach this? One helpful tool, but ultimately cheating and inadequate, is to use `shell-command' and `async-shell-command'. We can wrap any command up in a string and pass it to bash via these commands. E.g.:


(defun guix-news ()
  (interactive)
  (async-shell-command "guix pull --news --details" (get-buffer-create "*guix-news*")))

This is certainly convenient and I've done it a lot. We can see how it is easy to make fancy commands by passing in strings and doing some concatenation. But we are still relying on the external shell.


[to be continued...]

-- Response ended

-- Page fetched on Mon May 20 09:15:57 2024