Emacs23 の display-buffer

Emacsでファイル名や関数名などをミニバッファで入力するとき、 マッチするものが複数あるときに一覧を隣のウィンドウに出してくれる。 *Completions* バッファ。Emacs23ではそれを出す関数 display-buffer 関数がCからLisp化されて 仕様が変わった。ダメだこりゃ。

複数のフレームで使っているときに、 find-file とかを呼び出したフレームではない フレームに *Completions* バッファが出る。そしてそのフレームを raiseしてそっちにフォーカスが行ってしまう。 これはミニバッファを分離させているときに発生する。 どのフレームに *Completions* バッファを出すかを決めるのに last-nonminibuffer-frame 関数を使っているが、 これはミニバッファだけのフレーム内から呼ばれると、 最初にみつかる(?)フレームを返してしまうようだ。

てことで、display-buffer 関数の挙動を 完全に置き換えられる display-buffer-function 変数を利用。こんな感じかな。

;;;
;; Completion buffer should appear in original frame.
;;;
(cond
 ((fboundp 'minibuffer-selected-window)
  (setq display-buffer-function
	(function
	 (lambda (buf not-this-win)
	   (let ((f (window-frame (or (minibuffer-selected-window)
				     (selected-window))))
		(sf (selected-frame))
		(sw (selected-window)))
	    (select-frame f)
	    (unwind-protect
		(or (and (not not-this-win) (get-buffer-window buf))
		    (prog1
			(select-window
			 (if (one-window-p 'nomini)
			     (split-window (get-largest-window))
			   (next-window sw)))
		      (switch-to-buffer buf)))
	      (select-frame sf)
	      (select-window sw))))))))