Entropic Thoughts

Opening any CLI in Emacs

Opening any CLI in Emacs

Reddit pointed out that there is a much easier way to accomplish what is described in this article: C-u M-x comint-run, then type the executable name in the first prompt, and arguments in the second prompt.

This can also be used from Emacs Lisp:

(comint-run "perl" '("-de" "0")')

I’m keeping the rest of the article anyway because I enjoy public embarassment.


If you want to do it the complicated way, open a new scratch buffer and evaluate

(with-current-buffer (current-buffer)
  (make-comint-in-buffer "perl" (current-buffer)
    "perl" nil "-de" "0"))

But why?


Some cli​s are not built on readline, and they are a pain to use. There’s no support for editing the input, and every keypress inserts characters – even backspace and arrow keys. Interaction with these cli​s might end up looking something like

[user@host ~]$ perl -de 0
Loading DB routines from perl5db.pl version 1.77
...
  DB<1> printf^Ax ^E"d^H2d"^C^C^C^D[user@host ~]$

When faced with a cli like this, people often resort to writing commands in a text editor and then copy–pasting them into the cli. But there’s a better way.

Emacs has something called comint-mode which automatically turns any cli, however bare, into a powerful one. You will find existing support for many common programs, but even if there’s not – as with the Perl debugger – we can improvise it in two steps:

  1. First open a junk buffer. I do this by pressing C-x b and then slamming my forehead onto the keyboard to generate a unique buffer name.
  2. Press M-: to evaluate an Emacs Lisp expression, and paste the Emacs Lisp expression in the code block at the top of this article.

This runs the desired command (in this case perl -de 0) as an inferior interpreter. Any output of the command will be pasted into the Emacs buffer, and if we press return at any point it will send the current line to the cli as input. With this, we can

Much nicer than the cli we are wrapping.


If we find ourselves doing this often with different cli​s, we could wrap the expression at the top into a convenient Emacs command that prompts for the program to run, and executes it with comint in a new buffer. Me, I have mainly encountered this with Perl so far, so I created a Perl-specific function for it instead.