xyzzyのoccurの結果をanythingで選択できるようにした

xyzzyにはcolor-moccurとかないので、anythingで選択できれば便利だと思いました><。

注意

anything.lが必要です。

機能

  • occur
  • moccur
    • 開いているすべてのバッファの中での渡した正規表現を含む行の表示
  • moccur-anything
    • moccurの結果をanythingを使って選択できる
    • (選択した位置に移動する)

コード

(defvar last-occur-word ""
  "履歴が残っているとうれしい")

(defun occur--search (re)
  (let ((result '()))
    (save-excursion
      (goto-char (point-max))
      (while (scan-buffer re :regexp t :no-dup t :tail nil :case-fold t :reverse t)
	(save-excursion
	  (let ((str (progn (goto-char (match-beginning 0))
		       (buffer-substring (progn (goto-bol) (point))
					 (progn (goto-eol) (point))))))
	    (push (cons (current-line-number) str) result)))))
    result))

(defun occur--output (result &optional output-buffer over-write?)
  (let ((buf (or output-buffer "*occur*")))
    (if over-write?
	(with-output-to-buffer ((or (find-buffer buf)
				    (get-buffer-create buf)))
	  (dolist (l result)
	    (print l)))
	(progn
	  (when  (find-buffer buf) (delete-buffer buf))
	  (with-output-to-buffer ((get-buffer-create buf))
	    (dolist (l result)
	      (print l)))))))

(defun occur (re) (interactive"sregexp:" :default0 last-occur-word)
  "渡された正規表現を含む行を『行番号:行の内容』という形で表示する(上から下だと出力の向きが逆さになるので下から上に走査する。)"
  (let ((buf "*occur*"))
  (setq last-occur-word re)
  (occur--output (occur--search re) buf nil)
  (switch-to-buffer-other-window buf)
  (when (equal (buffer-name (selected-buffer)) buf)
    (other-window))))


(defun moccur--search (re &optional) 
  (let ((result '())
	;; result = (buffer . ((ln1 . ct1) (ln2 . ct2) ...) ...)
	)
    (save-excursion
      (dolist (b (buffer-list))
	(set-buffer b)
	(let ((content (occur--search re)))
	  (when content
	    (push (cons b content) result)))))
    result))

(defun moccur (re) (interactive"sregexp:" :default0 last-occur-word)
  (setq last-occur-word re)
  (let ((buf "*moccur*")
	(result (moccur--search re)))
    (dolist (e result)
      (occur--output (cdr e) buf t)
      (with-output-to-buffer ((find-buffer buf))
	(print (car e) )))
    (switch-to-buffer-other-window buf)
    (when (equal (buffer-name (selected-buffer)) buf)
      (other-window))))

(another-anything
    __moccur
  (add-anything-sources
   :name "moccur"
   :candidates (lambda ()
		   (let ((cs '()))
		     (dolist (occurlist (moccur--search last-occur-word))
		       (let ((buf (car occurlist)))
			 (dolist (line (cdr occurlist))
			   (push (prin1-to-string (cons (buffer-name buf) line)) cs))))
		     cs))
  :action (lambda (c) (let ((l (read-from-string c)))
			(switch-to-buffer (car l))
			(goto-line (cadr l))))
;; ;;動かない
;;    :move-action (lambda (c) (let ((l (read-from-string c)))
;;  			     (with-selected-window
;;  			       (other-window)
;;  			       (and (minibuffer-window-p (selected-window))
;;  				    (other-window))
;;  			       (switch-to-buffer (car l))
;; 			       (goto-line (cadr l)))))
  ))

(defun moccur-anything (re) (interactive"sregexp:" :default0 last-occur-word)
  (setq last-occur-word re)
  (__moccur-anything))

(global-set-key '(#\C-c #\C-:) 'moccur-anything)
(global-set-key '(#\C-c #\C-\;) 'occur)

本当は,move-actionを使って候補を選んでいるときにも移動先を表示させたかったのですが、うまく動きませんでした。