GNU Screen inside GNU Emacs

The problem

It is difficult to resist the temptation to do everything inside GNU Emacs. And another very useful program for those of us that still use the commandline is GNU Screen. In the X Window System, GNU Screen is usually hosted by a terminal emulator. Unsurprisingly, GNU Emacs has a terminal emulator. Just type M-x term or M-x ansi-term. The function prompts for a program, usually a commandline interpreter like GNU Bash, to run inside a special buffer with full terminal emulation. If we type the path to GNU Screen, say /usr/bin/screen, then Emacs will run it inside the terminal buffer just as expected. However, many users would like to pass some options to GNU Screen so as to reattach to running sessions, if necessary (the famous -d -R flags). Sadly, when we type in the flags following the path to GNU Screen, Emacs gives the following error:

..: 1: [: /usr/bin/screen: unexpected operator
..: 1: exec: /usr/bin/screen -d -R: not found

Process terminal exited abnormally with code 127

And it does not help if we put the path to the comman inside quotes. Since I couldn't find anything on the Web on how to solve this problem, I decided to read the source of the Emacs functions in term.el and came up with a simple solution.

The solution

The function that actually creates the terminal buffer and calls the subprocess is term-ansi-make-term (for ansi-term). This function does support optional arguments for passing flags to the subprocess. So, we just define a function (term-screen, below) to set the context needed by term-ansi-make-term and pass the flags to GNU Screen as optional arguments. Finally, we bind term-screen to some key sequence. The solution works with GNU Emacs 23 and 24.

 1: ;; GNU screen inside GNU Emacs
 2: (defun term-screen ()
 3:   (interactive)
 4:   "Open GNU screen session or reattaches existing one"
 5:   (require 'term)
 6:   (setq term-ansi-buffer-name (concat "*" "terminal" "*"))
 7:   (term-ansi-make-term term-ansi-buffer-name 
 8:                              "/usr/bin/screen" nil "-d" "-R")
 9: 
10:   (set-buffer term-ansi-buffer-name)
11:   (term-mode)
12:   (term-char-mode)
13: 
14:   (term-set-escape-char ?\C-x)
15: 
16:   (switch-to-buffer term-ansi-buffer-name))
17: 
18: (global-set-key (kbd "C-c t") 'term-screen)

After putting the code above in our Emacs initialization file, we just type C-c t to get a terminal. If there is a detached GNU Screen session already running, it reattaches. If not, it creates a new one. Otherwise, if there is already a terminal buffer in the current Emacs session, it switches to that buffer. How cool is that?


Author: Hermógenes Oliveira. Created: 2014-01-15.