special-display-*について

Emacsでは特定のバッファの表示させかたを変えることができる。マニュアルでは「特別に表示すべきバッファ」という表現が使わている。以下、引用。

 -- User Option: special-display-buffer-names
     特別に表示すべきバッファのバッファ名のリスト.  バッファ名がこのリ
     ストにあると, `display-buffer'は当該バッファを特別に扱う.

     デフォルトでは, 特別に表示するとは, 専用のフレームにバッファを表
     示することである.

     リストの要素が文字列でなくリストであると, リストのCARがバッファ名
     であり, リストの残りはフレームの作成方法を指定する.  それは, フレー
     ムパラメータを指定する連想リストであるか, 関数とそれに渡す引数で
     ある.  (関数の第1引数はつねに表示すべきバッファである.  そのあと
     にリスト内の引数が続く. )

 -- User Option: special-display-regexps
     特別に表示すべきバッファを指定する正規表現のリスト.  バッファ名が
     このリストのいずれかの正規表現に一致すると, `display-buffer'は当
     該バッファを特別に扱う.

     デフォルトでは, 特別に表示するとは, 専用のフレームにバッファを表
     示することである.

     リストの要素が文字列でなくリストであると, リストのCARが正規表現で
     あり, リストの残りはフレームの作成方法を指定する.  上記の
     `special-display-buffer-names'を参照.

 -- Variable: special-display-function
     この変数は, バッファを特別に表示するために呼び出す関数を保持する. 
     引数としてバッファを受け取り, 当該バッファを表示したウィンドウを
     返すこと.

     この関数のデフォルト値は`special-display-popup-frame'である.

 -- Function: special-display-popup-frame BUFFER
     この関数は, BUFFERをそれ専用のフレームに表示する.  あるフレームの
     ウィンドウにBUFFERがすでに表示されている場合, 当該ウィンドウを使
     うために当該フレームを可視にし手前に持ってくる.  さもなければ,
     BUFFER用にフレームを作成する.

     この関数は, BUFFERを表示している既存のウィンドウのフレームで当該
     バッファだけを表示しているかどうかに関わらず, 既存の当該ウィンド
     ウを使う.  しかし, BUFFERを作るまえに読者の初期化ファイルで上記の
     変数に設定しているときには, 当該ウィンドウは以前にこの関数が作成
     したものであろう.

 -- User Option: special-display-frame-alist
     この変数は, `special-display-popup-frame'がフレームを作るときに使
     用するフレームパラメータを保持する.

special-display-buffer-namesやspecial-display-regexpsはデフォルトではnilだし、専用のフレームにバッファを表示っていったい何のためかと思っていたが、やっと使い道がわかった。

+------------------------------------+---------+
|0                                   |1        |
|                                    |         |
|                                    +---------|
|                                    |2        |
|                                    |         |
|                                    |         |
|                                    |         |
|                                    |         |
|                                    |         |
|                                    |         |
+------------------------------------+---------+
|3                                             |
+------------------------------------+---------+

俺は普段上のような画面構成で作業をしている。0*1EmacsGNU Screenを立ち上げたmlterm。w3mによるブラウジングEmacsによる編集作業は0でやっている。1で現在時刻や負荷などを表示している(procmeter)。2はbelldのログを垂れ流している。3はEmacsのタブ(windows-tab.el。現在非公開)のためのフレームを表示している。belldのログを常に表示する必要性を最近になってあまり感じなくなった。
また、Emacsで作業中にgrepやoccurを実行したとき、結果バッファの表示のために画面が縦分割されて編集中のバッファの表示行数が半減されることにイライラを感じていた。もちろん画面分割状態(window-configuration)を戻すコマンドですぐに戻しているのだが、それでもうざいと感じていた。
そこで画面分割する代わりに2に結果バッファを表示させようかと考えた。そこでspecial-displayの登場となった。


(setq special-display-buffer-names '("*Help*" "*compilation*" "*interpretation*" "*Occur*" ))

こんな設定を加えると作業を邪魔されることなく幸せになった。専用フレームのフォントはやや小さめにしている。狭い領域であまり凝視しない場所なので小さくても構わない。表示情報量は多いに越したことはない。

もちろん、専用フレームの表示場所を指定するとか細々としたことをするにはコードを書かないといけない。ratpoisonのコードなのでratpoison.el依存。応用すればほかのウィンドウマネージャーでも利用可能であろう。以下の設定は専用フレームにemacs-specialというタイトルをつけて、ratpoison側で指定したフレームに表示させている。

(require 'cl)
(defun ratpoison-commands (&rest cmds)
  (apply #'call-process ratpoison-program nil nil nil
         (mapcan (lambda (cmd) (list "-c" cmd)) cmds)))
(when window-system
   (create-fontset-from-fontset-spec "-shinonome-mincho-medium-r-normal-*-12-*-*-*-c-*-*-*,ascii:-shinonome-mincho-medium-r-normal-*-12-*-*-*-c-*-jisx0201.1976-*,japanese-jisx0208:-shinonome-mincho-medium-r-normal-*-12-*-*-*-c-*-jisx0208.1990-*"))

(defvar special-display-frame nil)
(defvar default-frame nil)
(when window-system
  (setq default-frame (selected-frame)
        special-display-frame (create-special-display-frame)))
(defun create-special-display-frame ()
  (ratpoison-command "rudeness 0")
  (prog1
      (make-frame
       '((font . "-shinonome-mincho-medium-r-normal-*-12-*-*-*-c-*-*-*")
         (minibuffer . nil)
         (title . "emacs-special")
         (visibility . icon)))
    (ratpoison-command "rudeness 15")))

(defun my-special-display-function (buf)
  (unless (and special-display-frame (frame-live-p special-display-frame))
    (setq special-display-frame (create-special-display-frame)))
  (unless (eq t (frame-visible-p special-display-frame))
    (ratpoison-commands "fselect 2" "select emacs-special" "fselect 0" "fselect 0"))
  (save-selected-frame
   (select-frame special-display-frame)
   (delete-other-windows)
   (set-window-buffer (selected-window) buf)
   (get-buffer-window buf)))

(when window-system
  (setq special-display-function 'my-special-display-function
        special-display-buffer-names '("*Help*" "*compilation*" "*interpretation*" "*Occur*" )
        special-display-regexps '("^\\*jdic")))

作業用フレームとspecial-display用フレームの関係は太刀と脇差なのかもしれない。

*1:番号はratpoisonのフレーム番号。fselectを実行すれば出てくる。