Emacs でシェルを好きな時に呼び出す

追記:より使いやすいように修正しました。こちらが最終版です。

エディタで文章を編集している時は、それに意識を集中させ分散させたくないものだ。とはいえその最中でも何らかの用事をシェルに頼まなくてはいけないことがある。shell-mode や term-mode に切り替えてコマンドを打つのはいいのだけれど、バッファ切り替えによる集中力のオーバーヘッドをなるべく減らせないかと思った。

■要求

  • - 文章を編集している時にはウィンドウを他のことに使いたくない。画面リソースは貴重だ。
  • - 時折シェルは打つ必要があるんだけど、集中は切らせたくない。簡単に切り替えたい。

ということで、この要求を満たすような機能を作成し、インタフェイスとして CapsLock キーをホットキーにしてトグルで呼び出せるようにしてみた。好きな時に *shell* バッファを呼び出してコマンドが打てるようになり、用事が済んだらまたすぐ引っ込めることができるので便利。(^-^;

■実装(emacs-lisp)

(defvar my-shell-buffer "*shell*")
(defvar my-last-buffer nil)
(defvar my-last-window nil)
(defvar my-shell-buffer-height 10) ; percentage for shell-buffer window height

(defun my-search-buffer (buffer)
  (if (catch 'found
        (dolist (b (buffer-list))
          (if (string-match buffer (buffer-name b))
              (throw 'found t))))
      t
    nil))

(defun my-toggle-shell-buffer ()
  (interactive)
    (let *1
        (progn
          ; save my-last-buffer and my-last-window to return
            (setq my-last-buffer (buffer-name))
            (setq my-last-window (selected-window))
            (split-window (selected-window)
                          (* (/ (window-height) 10)
                             (/ (- 100 my-shell-buffer-height) 10)))
            (other-window 1)
            (if (not (my-search-buffer my-shell-buffer))
                (shell)
              (switch-to-buffer my-shell-buffer))))))

; CapsLock キーでトグルする
(global-set-key [eisu-toggle] 'my-toggle-shell-buffer)

; シェルモードで上下矢印キーで履歴を辿る
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
(add-hook 'shell-mode-hook
  '(lambda ()
    (define-key shell-mode-map [up] 'comint-previous-input)
    (define-key shell-mode-map [down] 'comint-next-input)))

■設定(.bashrc - CapsLock キーのロックを外す)

xmodmap -e 'remove lock = Eisu_toggle'

スクリーンショット

1. CapsLock キーを叩いて *shell* を呼び出してコマンドを叩く。

2. 用事が済んだらまた叩いて引っ込ませる。

*1:cb (buffer-name))) ;cb = current-buffer (if (equal cb my-shell-buffer) (progn (delete-window) (select-window my-last-window) (switch-to-buffer my-last-buffer