[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
isearch multiple buffers
From: |
Juri Linkov |
Subject: |
isearch multiple buffers |
Date: |
Sat, 06 Oct 2007 22:52:46 +0300 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/23.0.50 (gnu/linux) |
Below is a patch that implements a feature allowing isearch to search
multiple files/buffers. I wrote documentation strings and comments
in every new function, so for details please look there.
This general feature is implemented in isearch.el and can be used by other
packages. add-log.el is the first package that uses it, and below is also
a patch for add-log.el that allows C-s to search through a set of all
ChangeLog files in one directory:
Index: lisp/add-log.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/add-log.el,v
retrieving revision 1.196
diff -c -r1.196 add-log.el
*** lisp/add-log.el 20 Sep 2007 14:06:13 -0000 1.196
--- lisp/add-log.el 6 Oct 2007 19:43:40 -0000
***************
*** 760,766 ****
'change-log-resolve-conflict)
(set (make-local-variable 'adaptive-fill-regexp) "\\s *")
(set (make-local-variable 'font-lock-defaults)
! '(change-log-font-lock-keywords t nil nil backward-paragraph)))
;; It might be nice to have a general feature to replace this. The idea I
;; have is a variable giving a regexp matching text which should not be
--- 760,792 ----
'change-log-resolve-conflict)
(set (make-local-variable 'adaptive-fill-regexp) "\\s *")
(set (make-local-variable 'font-lock-defaults)
! '(change-log-font-lock-keywords t nil nil backward-paragraph))
! (add-hook 'isearch-mode-hook 'isearch-buffers-init nil t)
! (set (make-local-variable 'isearch-search-fun-function)
! 'isearch-buffers-search-fun)
! (set (make-local-variable 'isearch-wrap-function)
! 'isearch-buffers-wrap)
! (set (make-local-variable 'isearch-push-state-function)
! 'isearch-buffers-push-state)
! (set (make-local-variable 'isearch-buffers-next-buffer-function)
! 'change-log-isearch-next-buffer))
!
! (defun change-log-isearch-next-buffer (&optional buffer wrap)
! "Return the next buffer for multiple buffers isearch.
! A sequence of buffers is formed by ChangeLog files with decreasing
! numeric file name suffixes in the directory of the initial ChangeLog
! file were isearch was started."
! (let* ((name (change-log-name))
! (files (cons name (sort (file-expand-wildcards (concat name
"[-.][0-9]*"))
! (lambda (a b)
! (version< (substring b (length name))
! (substring a (length name)))))))
! (files (if isearch-forward files (reverse files))))
! (find-file-noselect
! (if wrap
! (car files)
! (cadr (member (file-name-nondirectory (buffer-file-name buffer))
! files))))))
;; It might be nice to have a general feature to replace this. The idea I
;; have is a variable giving a regexp matching text which should not be
Index: lisp/isearch.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.303
diff -c -r1.303 isearch.el
*** lisp/isearch.el 29 Aug 2007 05:28:05 -0000 1.303
--- lisp/isearch.el 6 Oct 2007 19:48:51 -0000
***************
*** 2035,2042 ****
(if isearch-forward (< pos2 pos1) (> pos2 pos1))))
(setq pos1 pos2)
(set-match-data match-data)))))
! (if pos1
! (goto-char pos1))
pos1))
(defun isearch-search ()
--- 2035,2046 ----
(if isearch-forward (< pos2 pos1) (> pos2 pos1))))
(setq pos1 pos2)
(set-match-data match-data)))))
! (when pos1
! ;; When using multiple buffers isearch, switch to the new buffer here,
! ;; because `save-excursion' above doesn't allow doing it inside funcall.
! (if isearch-buffers-current-buffer
! (switch-to-buffer isearch-buffers-current-buffer))
! (goto-char pos1))
pos1))
(defun isearch-search ()
***************
*** 2243,2248 ****
--- 2247,2344 ----
(setq isearch-hidden t)))))))
+ ;; Search multiple buffers
+
+ (defvar isearch-buffers-current-buffer nil
+ "The buffer where the search currently stays.
+ The value is nil when the search still is in the initial buffer.")
+
+ (defvar isearch-buffers-next-buffer-function nil
+ "Function to call to get the next buffer to search.
+ The first argument of this function is the CURRENT-BUFFER that defined
+ the base buffer relative to which to find the next buffer. When the
+ isearch direction is backward (when isearch-forward is nil), this
+ function should return the previous buffer.
+
+ If the second argument of this function WRAP is non-nil, then it
+ should return the first buffer in a buffer sequence; and for the
+ backward search, it should return the last buffer in a sequence.")
+
+ (defun isearch-buffers-init ()
+ "Set up isearch to search multiple buffers.
+ Intended to be added to `isearch-mode-hook'."
+ (setq isearch-buffers-current-buffer nil))
+
+ (defun isearch-buffers-search-fun ()
+ "Return the proper search function, for isearch in multiple buffers."
+ (lambda (string bound noerror)
+ (let ((search-fun
+ ;; Use standard functions to search within one buffer
+ (cond
+ (isearch-word
+ (if isearch-forward 'word-search-forward 'word-search-backward))
+ (isearch-regexp
+ (if isearch-forward 're-search-forward 're-search-backward))
+ (t
+ (if isearch-forward 'search-forward 'search-backward))))
+ found buffer)
+ (or
+ ;; 1. First try searching in the initial buffer
+ (funcall search-fun string bound noerror)
+ ;; 2. If the above search fails, start visiting next/prev buffers
+ ;; successively, and search the string in them. Do this only
+ ;; when bound is nil (i.e. not while lazy-highlighting search
+ ;; strings in the current buffer).
+ (unless bound
+ (if isearch-buffers-current-buffer
+ (condition-case nil
+ (progn
+ (while (not found)
+ (setq buffer (funcall isearch-buffers-next-buffer-function
buffer))
+ (with-current-buffer buffer
+ (goto-char (if isearch-forward (point-min) (point-max)))
+ (setq isearch-barrier (point) isearch-opoint (point))
+ ;; After visiting the next/prev buffer search the
+ ;; string in them again, until the function in
+ ;; isearch-buffers-next-buffer-function raises an error
+ ;; at the beginning/end of the buffer list.
+ (setq found (funcall search-fun string bound noerror))))
+ (if buffer (setq isearch-buffers-current-buffer buffer))
+ ;; Return point of the new search result
+ found)
+ ;; Return nil when isearch-buffers-next-buffer-function fails
+ (error nil))
+ (signal 'search-failed (list string "initial buffer"))))))))
+
+ (defun isearch-buffers-wrap ()
+ "Wrap the multiple buffers search when search is failed.
+ Switch buffer to the first buffer for a forward search,
+ or to the last buffer for a backward search.
+ Set `isearch-buffers-current-buffer' to the current buffer to display
+ the isearch suffix message [initial buffer] only when isearch leaves
+ the initial buffer."
+ (if isearch-buffers-current-buffer
+ (progn
+ (switch-to-buffer
+ (funcall isearch-buffers-next-buffer-function (current-buffer) t))
+ (goto-char (if isearch-forward (point-min) (point-max))))
+ (setq isearch-buffers-current-buffer (current-buffer))
+ (setq isearch-wrapped nil)))
+
+ (defun isearch-buffers-push-state ()
+ "Save a function restoring the state of multiple buffers search.
+ Save the current buffer to the additional state parameter in the
+ search status stack."
+ `(lambda (cmd)
+ (isearch-buffers-pop-state cmd ,(current-buffer))))
+
+ (defun isearch-buffers-pop-state (cmd buffer)
+ "Restore the multiple buffers search state.
+ Switch to the buffer restored from the search status stack."
+ (unless (equal buffer (current-buffer))
+ (switch-to-buffer (setq isearch-buffers-current-buffer buffer))))
+
+
;; General utilities
(defun isearch-no-upper-case-p (string regexp-flag)
--
Juri Linkov
http://www.jurta.org/emacs/
- isearch multiple buffers,
Juri Linkov <=
- Re: isearch multiple buffers, Dan Nicolaescu, 2007/10/07
- Re: isearch multiple buffers, Richard Stallman, 2007/10/08
- Re: isearch multiple buffers, Juri Linkov, 2007/10/08
- Re: isearch multiple buffers, Eric Hanchrow, 2007/10/08
- Re: isearch multiple buffers, Juri Linkov, 2007/10/08
- Re: isearch multiple buffers, Johan Bockgård, 2007/10/11
- Re: isearch multiple buffers, Juri Linkov, 2007/10/11
- Re: isearch multiple buffers, Stefan Monnier, 2007/10/11
- Re: isearch multiple buffers, Juri Linkov, 2007/10/11
- Re: isearch multiple buffers, Richard Stallman, 2007/10/11