isearch を実行した時にその語に一致する行を別ウィンドウに表示する

以下を.emacsに追加すれば、C-s にその機能が備わる。
ソースなげー。
こんなに長いのを.emacsに足したのは初めてだよ。
しかし思っていたより使えます。ニヤリ。

;;; isearch を実行した時にその語に一致する行を別ウィンドウに表示
(defvar my-igrep-buffer
  "*Incremental Grep*") ;; grep 結果を表示する window の名前
(defvar my-igrep-window-height
  10) ;; grep 結果を表示する window の高さ
(defvar my-igrep-window-offset
  3) ;; grep 結果中の、現在行の表示位置
(defvar my-igrep-with-color
  t) ;; マッチした文字列に色をつけて表示
(defvar my-igrep-mark-str
  "=>") ;; mark
(defvar my-igrep-min-length
  3) ;; grep する最短文字数
(defvar my-igrep-delay
  0) ;; grep し始めるまでの delay
(defvar my-igrep-light-mode
  nil) ;; migemo (日本語検索)を grep に使うか
(defvar my-igrep-enable-p
  t) ;; igrep オン・オフのの初期設定
(defface my-igface
  '((t (:background "paleturquoise"))) nil) ;; 色
(defvar my-igrep-match 0)
(defvar my-igrep-overlay nil)
(defvar my-igrep-window-configuration nil)

(defadvice isearch-mode
  (before my-igrep activate)
  (when my-igrep-enable-p
    (get-buffer-create my-igrep-buffer)
    (with-current-buffer my-igrep-buffer
      (make-local-variable
       'window-min-height)
      (setq window-min-height 2
            truncate-lines t))))        ; *1

(add-hook
 'isearch-mode-end-hook
 (lambda ()
   (my-igrep-window-cleanup)
   (when my-igrep-enable-p
     (kill-buffer my-igrep-buffer))))

(defadvice isearch-update
  (after my-igrep activate)
  (if (and
       my-igrep-enable-p
       (>= (length isearch-string) my-igrep-min-length))
      (my-igrep-display)
    (my-igrep-window-cleanup)))

(defun my-igrep-toggle-grep-enable ()
  (interactive)
  (message
   (if (setq my-igrep-enable-p
             (not my-igrep-enable-p)) "t" "nil")))

(defun my-igrep-search (&optional end)
  (if (and
       my-igrep-light-mode
       (featurep 'migemo) migemo-isearch-enable-p)
      (re-search-forward
       (migemo-get-pattern isearch-string) end t)
    (search-forward isearch-string end t)))

(defun my-igrep-colorize (str beg end pos)
  (put-text-property
   (- (match-beginning 0) beg) pos 'face 'my-igface str)
  (if (my-igrep-search end)
      (my-igrep-colorize str beg end (- (point) beg)) str))

(defun my-igrep-window-setup () ;; 検索 window の setup
  (set-window-buffer
   (cond
    ((>= (- (window-height)
            my-igrep-window-height) window-min-height)
     (setq my-igrep-window-configuration
           (current-window-configuration))
     (split-window
      (selected-window)           ; 分割可能な window なら分割して表示
      (- (window-height) (1+ my-igrep-window-height))))
    (t (next-window)))
   (get-buffer my-igrep-buffer)))

(defun my-igrep-window-cleanup () ;; 検索 window の cleanup
  (when (window-configuration-p
         my-igrep-window-configuration)
    (set-window-configuration my-igrep-window-configuration)
    (setq my-igrep-window-configuration nil)))

(defun my-igrep-display ()
  (let ((clinen (count-lines (point-min) (point))))
    (when (sit-for my-igrep-delay) ;; (or (= my-igrep-delay 0)
      (save-excursion
        (goto-char (point-min))
        (unless
            (memq
             this-command       ; 検索文字列が変更されたときのみ再検索
             (list 'isearch-repeat-forward
                   'isearch-repeat-backward))
          (setq my-igrep-match 0)
          (with-current-buffer my-igrep-buffer (erase-buffer))
          (let ((linen 1)
                (ppos (point)))
            (while (my-igrep-search)    ; マッチした行だけ処理
              (setq linen
                    (+ linen (1- (count-lines ppos (setq ppos (point))))))
              (let* ((beg
                      (save-excursion
                        (progn (beginning-of-line) (point))))
                     (end
                      (save-excursion
                        (progn (end-of-line) (point))))
                     (str (buffer-substring beg end))) ;-no-properties
                (setq my-igrep-match (1+ my-igrep-match))
                (when my-igrep-with-color
                  (setq str
                        (my-igrep-colorize
                         str beg end (- (point) beg))))
                (with-current-buffer my-igrep-buffer
                  (insert
                   (concat (format "%7d: " linen))
                   str "\n"))))))
        (cond
         ((= my-igrep-match 0) (my-igrep-window-cleanup))
         ((not (window-configuration-p
                my-igrep-window-configuration))
          (my-igrep-window-setup)))
        (when (and
               (> my-igrep-match 0)
               my-igrep-window-configuration)
          (save-selected-window
            (select-window (get-buffer-window my-igrep-buffer))
            (with-current-buffer my-igrep-buffer
              (goto-char (point-max))
              (let* ((alen (length my-igrep-mark-str))
                     (beg (re-search-backward
                           (format "^ +%d:" clinen) nil t))
                     (end (save-excursion (end-of-line) (point)))
                     (alinen (count-lines (point-min) (point))))
                (when (and beg (> my-igrep-match 0))
                  (setq beg (1+ beg))   ; *2
                  (if my-igrep-overlay
                      (move-overlay
                       my-igrep-overlay beg (+ beg alen))
                    (setq my-igrep-overlay
                          (make-overlay beg (+ beg alen))))
                  (overlay-put
                   my-igrep-overlay 'invisible t) ; *3
                  (overlay-put
                   my-igrep-overlay 'before-string my-igrep-mark-str)
                  (when my-igrep-window-configuration ;; リサイズ
                    (enlarge-window
                     (1+
                      (-
                       (if (> my-igrep-match (window-height))
                           (min my-igrep-window-height my-igrep-match)
                         (max window-min-height my-igrep-match))
                       (window-height)))))
                  (when (> my-igrep-match (window-height))
                    (recenter (- my-igrep-window-offset 1)))
                  (setq mode-line-buffer-identification
                        `("%b" ,(format " - %d:%d matches"
                                        alinen my-igrep-match))))
                (force-mode-line-update)))))))))