running console programs inside emacs

Emacs comes with a nice terminal emulator called ansi-term. Using M-x ansi-term, you can run shells and other terminal programs from within emacs, and the emulation is good enough even for 'graphical' console programs. For example, I am using the mutt mailer and slrn news reader with ansi-term. I could of course use some native emacs program for news and mail (e.g,, gnus), but in this case, I prefer the external ones (I'll discuss that in some later entry). However, I really like these external programs to run inside emacs - it makes my task management easier. YMMV, of course.

Anyway, to easily use these external programs, I want some handy key bindings (shortcuts), and the following behaviour:


  • if the program is not yet running, start it in a new ansi-term-buffer;
  • if the program is already running, switch to that buffer instead.

To do that, I define a functions (disclaimer: I am no elisp-expert; there are probably better ways to do this. But this works-for-me at least): [Update: thanks to Ian and get-buffer (see comments), a shorter solution, using only one function:]
(defun djcb-term-start-or-switch (prg &optional use-existing)
"* run program PRG in a terminal buffer. If USE-EXISTING is non-nil "
" and PRG is already running, switch to that buffer instead of starting"
" a new instance."
(interactive)
(let ((bufname (concat "*" prg "*")))
(when (not (and use-existing
(let ((buf (get-buffer bufname)))
(and buf (buffer-name (switch-to-buffer bufname))))))
(ansi-term prg prg))))

Using this function, it's easy to define key bindings, as explained in the key bindings entry. However, we can make it even easier using a macro:

(defmacro djcb-program-shortcut (name key &optional use-existing)
"* macro to create a key binding KEY to start some terminal program PRG;
if USE-EXISTING is true, try to switch to an existing buffer"

`(global-set-key ,key
'(lambda()
(interactive)
(djcb-term-start-or-switch ,name ,use-existing))))

Using this macro, we can now define these key bindings (shortcuts), for
example like this:
;; terminal programs are under Shift + Function Key
(djcb-program-shortcut "zsh" (kbd "<S-f1>") t) ; the ubershell
(djcb-program-shortcut "mutt" (kbd "<S-f2>") t) ; mail client
(djcb-program-shortcut "slrn" (kbd "<S-f3>") t) ; nttp client
(djcb-program-shortcut "htop" (kbd "<S-f4>") t) ; my processes
(djcb-program-shortcut "mc" (kbd "<S-f5>") t) ; midnight commander
(djcb-program-shortcut "raggle"(kbd "<S-f6>") t) ; rss feed reader
(djcb-program-shortcut "irssi" (kbd "<S-f7>") t) ; irc client

And so on. Now, to summarize, if I press, say, C-f5 (shift-F5), I'll jump to a buffer with the midnight commander. If it's already running, I'll switch to that one, otherwise, a new mc will be started.

Final note: you might want to customize ansi-term a bit for your needs; EmacsWiki has some tips. You also might want to turn off hl-line-mode.

No comments:

Post a Comment

Followers

Popular Posts