より快適に grep-find する(改)

「よい人生とはよい検索だ。」アキハバラ@DEEP

ということで(?)、以前作ったオレ版 grep-find を改良することにした。

より快適に grep-find する

以前は *grep* バッファを映しているフレーム以外で呼び出すと続けてフレームを作ってしまっていた。これを修正し、どのフレームから呼び出しても *grep* バッファ専用のフレームで処理するように変更する。

1. まず、フレームリストを検索して該当のバッファがあればそのフレームを、なければ nil を返す関数を作成する(該当バッファが複数のフレームに映っていた場合は最初のフレームが返る。ただ my-grep-find の仕様として複数のフレームに映すことは現状ありえない。)

(defun my-find-buffer-from-frame-list (buffer-or-name)
  (interactive)
  (let ((frame-list (frame-list))(frame)(frame-param)(target-frame)(buffer-list)(buffer))
    (while frame-list
      ; car
      (setq frame (car frame-list))
      (setq frame-param (frame-parameters frame))
      (setq buffer-list (cdr (assoc 'buffer-list frame-param)))
      (while buffer-list
        (setq buffer (car buffer-list))
        (if (string= (buffer-name buffer) buffer-or-name)
            (setq target-frame frame))
        (setq buffer-list (cdr buffer-list)))
      ; cdr
      (setq frame-list (cdr frame-list)))
    target-frame))

2. 次に該当フレームを前面に切り替える関数を作成する。

(defun my-raise-frame-on-buffer (buffer-or-name)
  (interactive)
  (let ((target-frame))
    (setq target-frame (my-find-buffer-from-frame-list buffer-or-name))
    (lower-frame)
    (select-frame target-frame)
    (redirect-frame-focus last-event-frame target-frame)
    (raise-frame target-frame)))

3. 最後にこの 2 つの関数を含めて、 my-grep-find 本体を修正する。

(defun my-grep-find (arg)
  (interactive "sInput string:")
  (if (not (my-find-buffer-from-frame-list "*grep*"))
      (progn
        (make-frame)
        (select-frame (next-frame nil t)))
    (my-raise-frame-on-buffer "*grep*"))
  (switch-to-buffer "*grep*")
  (let ((topdir)(command))
    (setq topdir my-grep-find-topdir)
    (cd topdir)
    (setq command "find . -name \"*.c\" -o -name \"*.cpp\" -o -name \"*.h\" | xargs grep -n ")
    (setq command (concat command arg))
    (grep-find command)))

まだ見えないバグはあるかもしれないが、期待どおりの動作をするようになった。以下の grep-find 先を切り替える my-grep-find-select-topdir と併用して使うとなおよろし。

(setq my-grep-find-topdir-alist
      '(("emacs 22" . "/home/kyagi/src/emacs22")
        ("emacs 21" . "/home/kyagi/src/emacs21")
	("rpm 4.4.2" . "/home/kyagi/src/rpm-4.4.2")
        ))

(defun my-grep-find-show-topdir-alist ()
  (split-window-vertically)
  (other-window 1)
  (switch-to-buffer "*my-grep-find-show-topdir-alist*")
  (let ((n 1) (dir) (topdir-alist))
  (setq topdir-alist my-grep-find-topdir-alist)
  (while topdir-alist
    (setq dir (car topdir-alist))
    (insert (format "%d %-16s %-64s\n" n (car dir) (cdr dir)))
    (setq topdir-alist (cdr topdir-alist))
    (setq n (1+ n)))))

(defun my-grep-find-hide-topdir-alist ()
  (kill-buffer "*my-grep-find-show-topdir-alist*")
  (other-window 1)
  (delete-other-windows))

(defun my-grep-find-select-topdir ()
  (interactive)
  (my-grep-find-show-topdir-alist)
  (let ((n 0) (answer) (dir) (topdir-alist))
  (setq topdir-alist my-grep-find-topdir-alist)
  (setq answer (read-from-minibuffer "which directory do you want to use?:"))
  (setq answer (string-to-number answer))
  (while (not (= n answer))
    (setq dir (car topdir-alist))
    (setq topdir-alist (cdr topdir-alist))
    (setq n (1+ n)))
  (setq-default my-grep-find-topdir (cdr dir)))
  (my-grep-find-hide-topdir-alist))

…そろそろオレ版 grep-find のメジャーモードを作る時期なのかもしれない。

アキハバラ@DEEP (文春文庫)

アキハバラ@DEEP (文春文庫)