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?