tl;dr
- 修正パッチを当てたelscreenを使えばOK
環境
- Xubuntu Linux 14.04
- Emacs 24.3+1-2ubuntu1 (Ubuntuレポジトリのもの)
- elscreen
- 1.4.6-5.1 (Ubuntuレポジトリのもの)
- emacs-jpのこのバージョン https://github.com/emacs-jp/elscreen/tree/d67ded50eb84580b7ad21d018111176ab8f3e120
問題
例えば、以下のようなスクリーン構成だったとする。現在開いているスクリーンは1番。
[0- *scratch*]
[1+ a.txt]
で、スクリーン1でb.txt
を開く。
[0- *scratch*]
[1+ b.txt]
ここで、kill-buffer
コマンドでカレントバッファ(b.txt
)を閉じる。この時、a.txt
が代わりに表示されることを期待するが、結果は
[0- *scratch*]
[1+ *scratch*]
こうなってしまう。
スクリーン0で*scratch*
ではなく別のバッファを開いている場合、そのバッファに切り替わる。
また、スクリーンが1枚しかない場合、期待通りa.txt
が表示される。
原因
elscreenは現在のスクリーン表示状況に合わせてタブやメニューを表示している。その表示を随時更新しているのが、post-command-hook
に仕掛けられたelscreen-run-screen-update-hook
関数である。
この関数が実行する関数の中でも、elscreen-tab-update
関数およびelscreen-menu-bar-update
関数が悪さをしているせいで、上記の問題が発生している。
具体的には、上記の関数が中で呼び出しているelscreen-get-screen-to-name-alist
関数が"Window History"を書き換えるという副作用を持っているせいで、上記の問題が引き起こされたようだ。
最近のEmacsはウィンドウ毎に表示したバッファの履歴を管理しているらしい。これをWindow Historyという。
kill-buffer
やbury-buffer
でカレントバッファを非表示にした場合、次に表示するバッファはWindow Historyを元に決定されるとのこと。 なので、elscreen-get-screen-to-name-alist
がWindow Historyを書き換えるとkill-buffer
時の挙動が変化してしまう。
elscreen-get-screen-to-name-alist
関数は中でelscreen-save-screen-excursion
マクロを使って副作用をキャンセルしようとしている。 そこで、このマクロを書き換えて、Window Historyを復元してやればよい。