Mercurial > hg > xemacs-beta
diff lisp/isearch-mode.el @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 11054d720c21 |
line wrap: on
line diff
--- a/lisp/isearch-mode.el Mon Aug 13 11:19:22 2007 +0200 +++ b/lisp/isearch-mode.el Mon Aug 13 11:20:41 2007 +0200 @@ -1,6 +1,6 @@ ;;; isearch-mode.el --- Incremental search minor mode. -;; Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc. +;; Copyright (C) 1992, 1993, 1997 Free Software Foundation, Inc. ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu> ;; Maintainer: XEmacs Development Team @@ -19,29 +19,35 @@ ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with XEmacs; see the file COPYING. If not, write to the +;; along with XEmacs; see the file COPYING. If not, write to the ;; Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. -;;; Synched up with: FSF 20.4. +;;; Synched up with: Not synched with FSF. ;;; Commentary: +;; LCD Archive Entry: +;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu +;; |A minor mode replacement for isearch.el. + +;;==================================================================== ;; Instructions -;; Searching with isearch-mode.el should work just like isearch.el -;; [the one from Emacs 18], except it is done in a temporary minor -;; mode that terminates when you finish searching. +;; Searching with isearch-mode.el should work just like isearch.el, +;; except it is done in a temporary minor mode that terminates when +;; you finish searching. -;; For programmed use of isearch-mode, e.g. calling (isearch-forward), -;; isearch-mode behaves modally and does not return until the search -;; is completed. It uses a recursive-edit to behave this way. In -;; that case, you should still be able switch buffers, so be careful -;; not to get things confused. +;; Semi-modal searching is supported, using a recursive edit. If +;; isearching is started non-interactively by calling one of the +;; isearch commands (e.g. (isearch-forward), but not like gnus does +;; it: (call-interactively 'isearch-forward)), isearch-mode does not +;; return until the search is completed. You should still be able +;; switch buffers, so be careful not to get things confused. ;; The key bindings active within isearch-mode are defined below in ;; `isearch-mode-map' which is given bindings close to the default -;; characters of the original isearch.el. With `isearch-mode', +;; characters of isearch.el for version 19. With `isearch-mode', ;; however, you can bind multi-character keys and it should be easier ;; to add new commands. One bug though: keys with meta-prefix cannot ;; be longer than two chars. Also see minibuffer-local-isearch-map @@ -57,18 +63,16 @@ ;; Exiting immediately from isearch uses isearch-edit-string instead ;; of nonincremental-search, if search-nonincremental-instead is non-nil. ;; The name of this option should probably be changed if we decide to -;; keep the behavior. No point in forcing nonincremental search until -;; the last possible moment. +;; keep the behavior. One difference is that isearch-edit-string does +;; not support word search yet; perhaps isearch-mode should support it +;; even for incremental searches, but how? -;; TODO -;; - Integrate generalized command history to isearch-edit-string. -;; - Think about incorporating query-replace. -;; - Hooks and options for failed search. +;;==================================================================== +;;; Change History: -;;; Change Log: - -;; Changes before those recorded in ChangeLog: - +;; Header: /import/kaplan/kaplan/liberte/Isearch/RCS/isearch-mode.el,v 1.3 92/06/29 13:10:08 liberte Exp Locker: liberte +;; Log: isearch-mode.el,v +;; ;; 20-aug-92 Hacked by jwz for Lucid Emacs 19.3. ;; ;; Revision 1.3 92/06/29 13:10:08 liberte @@ -79,7 +83,7 @@ ;; Renamed all regex to regexp. ;; Got rid of found-start and found-point globals. ;; Generalized handling of upper-case chars. - + ;; Revision 1.2 92/05/27 11:33:57 liberte ;; Emacs version 19 has a search ring, which is supported here. ;; Other fixes found in the version 19 isearch are included here. @@ -96,20 +100,38 @@ ;;; Code: +(defgroup isearch nil + "Incremental search" + :prefix "search-" + :group 'matching) + + +(defun isearch-char-to-string (c) + (if (eventp c) + (make-string 1 (event-to-character c nil nil t)) + (make-string 1 c))) + +;(defun isearch-text-char-description (c) +; (isearch-char-to-string c)) + +(define-function 'isearch-text-char-description 'text-char-description) + ;;;========================================================================= ;;; User-accessible variables -(defgroup isearch nil - "Incremental search minor mode." - :prefix "search-" - :group 'matching) +(defvar search-last-string "" + "Last string search for by a search command. +This does not include direct calls to the primitive search functions, +and does not include searches that are aborted.") +(defvar search-last-regexp "" + "Last string searched for by a regexp search command. +This does not include direct calls to the primitive search functions, +and does not include searches that are aborted.") -(defcustom search-exit-option t - "*Non-nil means random control characters terminate incremental search." - :type 'boolean - :group 'isearch) +(defconst search-exit-option t + "Non-nil means random control characters terminate incremental search.") (defcustom search-slow-window-lines 1 "*Number of lines in slow search display windows. @@ -126,70 +148,16 @@ :type 'integer :group 'isearch) -;; We have `search-caps-disable-folding'. -;(defcustom search-upper-case 'not-yanks -; "*If non-nil, upper case chars disable case fold searching. -;That is, upper and lower case chars must match exactly. -;This applies no matter where the chars come from, but does not -;apply to chars in regexps that are prefixed with `\\'. -;If this value is `not-yanks', yanked text is always downcased." -; :type '(choice (const :tag "off" nil) -; (const not-yanks) -; (other :tag "on" t)) -; :group 'isearch) - (defcustom search-nonincremental-instead t - "*If non-nil, do a nonincremental search instead if exiting immediately. -Actually, `isearch-edit-string' is called to let you enter the search -string, and RET terminates editing and does a nonincremental search." + "*If non-nil, do a nonincremental search instead if exiting immediately." :type 'boolean :group 'isearch) - -;; FSF default is "\\s-+", but I think our default is better so I'm -;; leaving it. -(defcustom search-whitespace-regexp "\\(\\s-\\|[\n\r]\\)+" + +(defcustom search-whitespace-regexp "\\(\\s \\|[\n\r]\\)+" "*If non-nil, regular expression to match a sequence of whitespace chars." :type 'regexp :group 'isearch) -(defcustom search-highlight t - "*Whether incremental search and query-replace should highlight -the text that currently matches the search string." - :type 'boolean - :group 'isearch) - -;; I think the name `search-highlight' makes more sense, both because -;; of consistency with other search-* variables above, and because it -;; also applies to query-replace. -(define-obsolete-variable-alias 'isearch-highlight 'search-highlight) - -(defcustom search-invisible 'open - "If t incremental search can match hidden text. -nil means don't match invisible text. -If the value is `open', if the text matched is made invisible by -an overlay having an `invisible' property and that overlay has a property -`isearch-open-invisible', then incremental search will show the contents. -\(This applies when using `outline.el' and `hideshow.el'.)" - :type '(choice (const :tag "Match hidden text" t) - (const :tag "Open overlays" open) - (const :tag "Don't match hidden text" nil)) - :group 'isearch) - -(defcustom isearch-hide-immediately t - "If non-nil, re-hide an invisible match right away. -This variable makes a difference when `search-invisible' is set to `open'. -It means that after search makes some invisible text visible -to show the match, it makes the text invisible again when the match moves. -Ordinarily the text becomes invisible again at the end of the search." - :type 'boolean - :group 'isearch) - -(defvar isearch-mode-hook nil - "Function(s) to call after starting up an incremental search.") - -(defvar isearch-mode-end-hook nil - "Function(s) to call after terminating an incremental search.") - ;;;================================================================== ;;; Search ring. @@ -207,34 +175,22 @@ :type 'integer :group 'isearch) -;; The important difference between pre-20.4-merge yank-pointers and -;; current code is that the yank pointers positions used to be -;; preserved across the isearch sessions. I changed this because I -;; think the FSF code is closer to how the feature is supposed to -;; behave (read: to minibuffer histories.) (defvar search-ring-yank-pointer nil - "Index in `search-ring' of last string reused. -nil if none yet.") + "The tail of the search ring whose car is the last thing searched for.") (defvar regexp-search-ring-yank-pointer nil - "Index in `regexp-search-ring' of last string reused. -nil if none yet.") - -(defcustom search-ring-update nil - "*Non-nil if advancing or retreating in the search ring should cause search. -Default nil means edit the string from the search ring first." - :type 'boolean - :group 'isearch) + "The tail of the regular expression search ring whose car is the last +thing searched for.") ;;;==================================================== ;;; Define isearch-mode keymap. -(defvar isearch-mode-map +(defvar isearch-mode-map (let ((map (make-keymap))) (set-keymap-name map 'isearch-mode-map) ;; Bind all printing characters to `isearch-printing-char'. - ;; This isn't normally necessary, but if a printing character were - ;; bound to something other than self-insert-command in global-map, + ;; This isn't normally necessary, but if a printing character were + ;; bound to something other than self-insert-command in global-map, ;; then it would terminate the search and be executed without this. (let ((i 32) (str (make-string 1 0))) @@ -242,10 +198,7 @@ (aset str 0 i) (define-key map str 'isearch-printing-char) (setq i (1+ i)))) - - ;; Here FSF sets up various kludges to handle local bindings with - ;; meta char prefix keys. We don't need isearch-other-meta-char - ;; because we handle things differently (via pre-command-hook). + (define-key map "\t" 'isearch-printing-char) ;; Several non-printing chars change the searching behavior. ;; @@ -254,29 +207,26 @@ (define-key map "\C-r" 'isearch-repeat-backward) (define-key map "\C-g" 'isearch-abort) - ;; I wish this worked... - ;(define-key map [escape escape escape] 'isearch-cancel) - (define-key map [(meta escape) escape] 'isearch-cancel) - (define-key map "\C-q" 'isearch-quote-char) (define-key map "\C-m" 'isearch-exit) (define-key map "\C-j" 'isearch-printing-char) (define-key map "\t" 'isearch-printing-char) - ;; I prefer our default. - ;(define-key map " " 'isearch-whitespace-chars) - (define-key map "\M- " 'isearch-whitespace-chars) (define-key map "\C-w" 'isearch-yank-word) (define-key map "\C-y" 'isearch-yank-line) (define-key map "\M-y" 'isearch-yank-kill) - ;; Define keys for regexp chars * ? |. - ;; Nothing special for + because it matches at least once. + ;; Define keys for regexp chars * ? | (define-key map "*" 'isearch-*-char) (define-key map "?" 'isearch-*-char) (define-key map "|" 'isearch-|-char) + ;; Some bindings you may want to put in your isearch-mode-hook. + ;; Suggest some alternates... + ;; (define-key map "\C-t" 'isearch-toggle-regexp) + ;; (define-key map "\C-^" 'isearch-edit-string) + ;; delete and backspace delete backward, f1 is help, and C-h can be either (define-key map 'delete 'isearch-delete-char) (define-key map 'backspace 'isearch-delete-char) @@ -286,23 +236,15 @@ (define-key map "\M-n" 'isearch-ring-advance) (define-key map "\M-p" 'isearch-ring-retreat) + (define-key map "\M- " 'isearch-whitespace-chars) (define-key map "\M-\t" 'isearch-complete) - ;; I find this binding somewhat unintuitive, because it doesn't - ;; work if the mouse pointer is over the echo area -- it has to be - ;; over the search window. - (define-key map 'button2 'isearch-yank-selection) + (define-key map 'button2 'isearch-yank-x-selection) map) "Keymap for isearch-mode.") -;; Some bindings you may want to put in your isearch-mode-hook. -;; Suggest some alternates... -;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-case-fold) -;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp) -;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string) - -(defvar minibuffer-local-isearch-map +(defvar minibuffer-local-isearch-map (let ((map (make-sparse-keymap))) ;; #### - this should also be minor-mode-ified (set-keymap-parents map (list minibuffer-local-map)) @@ -312,8 +254,6 @@ (define-key map "\r" 'isearch-nonincremental-exit-minibuffer) (define-key map "\M-n" 'isearch-ring-advance-edit) (define-key map "\M-p" 'isearch-ring-retreat-edit) - (define-key map 'down 'isearch-ring-advance-edit) - (define-key map 'up 'isearch-ring-retreat-edit) (define-key map "\M-\t" 'isearch-complete-edit) (define-key map "\C-s" 'isearch-forward-exit-minibuffer) (define-key map "\C-r" 'isearch-reverse-exit-minibuffer) @@ -322,8 +262,7 @@ ;;;======================================================== ;; Internal variables declared globally for byte-compiler. -;; These are all set with setq while isearching -;; and bound locally while editing the search string. +;; These are all bound locally while editing the search string. (defvar isearch-forward nil) ; Searching in the forward direction. (defvar isearch-regexp nil) ; Searching for a regexp. @@ -335,7 +274,6 @@ (defvar isearch-success t) ; Searching is currently successful. (defvar isearch-invalid-regexp nil) ; Regexp not well formed. -(defvar isearch-within-brackets nil) ; Regexp has unclosed [. (defvar isearch-other-end nil) ; Start (end) of match if forward (backward). (defvar isearch-wrapped nil) ; Searching restarted from the top (bottom). (defvar isearch-barrier 0) @@ -344,12 +282,6 @@ (defvar isearch-case-fold-search nil) -;; Need this for toggling case in isearch-toggle-case-fold. When this -;; is non-nil, the case-sensitiveness of the search is set by the -;; user, and is may no longer be dynamically changed as per -;; search-caps-disable-folding. -(defvar isearch-fixed-case nil) - (defvar isearch-adjusted nil) (defvar isearch-slow-terminal-mode nil) ;;; If t, using a small window. @@ -376,9 +308,12 @@ ;; New value of isearch-forward after isearch-edit-string. (defvar isearch-new-forward nil) -;; Accumulate here the extents unhidden during searching. -(defvar isearch-unhidden-extents nil) ; in FSF: isearch-opened-overlays +(defvar isearch-mode-hook nil + "Function(s) to call after starting up an incremental search.") + +(defvar isearch-mode-end-hook nil + "Function(s) to call after terminating an incremental search.") ;;;============================================================== ;; Minor-mode-alist changes - kind of redundant with the @@ -386,28 +321,21 @@ (add-minor-mode 'isearch-mode 'isearch-mode) -(defvar isearch-mode nil) ;; Name of the minor mode, if non-nil. +(defvar isearch-mode nil) (make-variable-buffer-local 'isearch-mode) -;; We bind these in keydefs.el. -;(define-key global-map "\C-s" 'isearch-forward) -;(define-key global-map "\C-r" 'isearch-backward) -;(define-key global-map "\M-\C-s" 'isearch-forward-regexp) -;(define-key global-map "\M-\C-r" 'isearch-backward-regexp) - ;;;=============================================================== ;;; Entry points to isearch-mode. ;;; These four functions should replace those in loaddefs.el -;;; An alternative is to defalias isearch-forward etc to isearch-mode, -;;; and look at this-command to set the options accordingly. +;;; An alternative is to fset isearch-forward etc to isearch-mode, +;;; and look at the last command to set the options accordingly. -(defun isearch-forward (&optional regexp-p no-recursive-edit) - "\ -Do incremental search forward. +(defun isearch-forward (&optional regexp-p) + "Do incremental search forward. With a prefix argument, do an incremental regular expression search instead. \\<isearch-mode-map> As you type characters, they add to the search string and are found. -The following non-printing keys are bound in `isearch-mode-map'. +The following non-printing keys are bound in `isearch-mode-map'. Type \\[isearch-delete-char] to cancel characters from end of search string. Type \\[isearch-exit] to exit, leaving point at location found. @@ -418,8 +346,6 @@ string and search for it. Type \\[isearch-yank-line] to yank rest of line onto end of search string\ and search for it. -Type \\[isearch-yank-kill] to yank last killed text onto end of search string\ - and search for it. Type \\[isearch-quote-char] to quote control character to search for it. Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp. \\[isearch-abort] while searching or when search has failed cancels input\ @@ -451,38 +377,36 @@ ;; Type \\[isearch-edit-string] to edit the search string in the minibuffer. ;; Terminate editing and return to incremental searching with CR. - (interactive "_P\np") - (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit))) + (interactive "_P") + (isearch-mode t (not (null regexp-p)) nil (not (interactive-p)))) -(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit) +(defun isearch-forward-regexp () "\ Do incremental search forward for regular expression. -With a prefix argument, do a regular string search instead. Like ordinary incremental search except that your input is treated as a regexp. See \\[isearch-forward] for more info." - (interactive "_P\np") - (isearch-mode t (null not-regexp) nil (not no-recursive-edit))) + (interactive "_") + (isearch-mode t t nil (not (interactive-p)))) -(defun isearch-backward (&optional regexp-p no-recursive-edit) +(defun isearch-backward (&optional regexp-p) "\ Do incremental search backward. -With a prefix argument, do a regular expression search instead. +With a prefix argument, do an incremental regular expression search instead. See \\[isearch-forward] for more information." - (interactive "_P\np") - (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit))) + (interactive "_P") + (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p)))) -(defun isearch-backward-regexp (&optional not-regexp no-recursive-edit) +(defun isearch-backward-regexp () "\ Do incremental search backward for regular expression. -With a prefix argument, do a regular string search instead. Like ordinary incremental search except that your input is treated as a regexp. See \\[isearch-forward] for more info." - (interactive "_P\np") - (isearch-mode nil (null not-regexp) nil (not no-recursive-edit))) + (interactive "_") + (isearch-mode nil t nil (not (interactive-p)))) -;; The problem here is that you can't scroll the help screen; as soon -;; as you press a key, it's gone. I don't know of a good way to fix -;; it, though. -hniksic +;; This function is way wrong, because you can't scroll the help +;; screen; as soon as you press a key, it's gone. I don't know of a +;; good way to fix it, though. -hniksic (defun isearch-mode-help () (interactive "_") (let ((w (selected-window))) @@ -496,9 +420,7 @@ ;; All the work is done by the isearch-mode commands. (defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p) - "Start isearch minor mode. Called by `isearch-forward', etc. - -\\{isearch-mode-map}" + "Start isearch minor mode. Called by isearch-forward, etc." (if executing-kbd-macro (setq recursive-edit nil)) @@ -511,7 +433,6 @@ isearch-word word-p isearch-op-fun op-fun isearch-case-fold-search case-fold-search - isearch-fixed-case nil isearch-string "" isearch-message "" isearch-cmds nil @@ -521,7 +442,6 @@ isearch-adjusted nil isearch-yank-flag nil isearch-invalid-regexp nil - isearch-within-brackets nil isearch-slow-terminal-mode (and (<= (device-baud-rate) search-slow-speed) (> (window-height) @@ -531,14 +451,10 @@ isearch-just-started t isearch-opoint (point) - search-ring-yank-pointer nil - regexp-search-ring-yank-pointer nil - isearch-unhidden-extents nil isearch-window-configuration (current-window-configuration) - ;; #### What we really need is a buffer-local - ;; overriding-local-map. See isearch-pre-command-hook for - ;; more details. + ;; #### Should we remember the old value of + ;; overriding-local-map? overriding-local-map (progn (set-keymap-parents isearch-mode-map (nconc (current-minor-mode-maps) @@ -547,6 +463,7 @@ isearch-mode-map) isearch-selected-frame (selected-frame) + isearch-mode (gettext " Isearch") ) ;; XEmacs change: without clearing the match data, sometimes old values @@ -554,10 +471,7 @@ (store-match-data nil) (add-hook 'pre-command-hook 'isearch-pre-command-hook) - - (setq isearch-mode (gettext " Isearch")) - (redraw-modeline) - + (set-buffer-modified-p (buffer-modified-p)) ; update modeline (isearch-push-state) ) ; inhibit-quit is t before here @@ -565,26 +479,26 @@ (isearch-update) (run-hooks 'isearch-mode-hook) - ;; isearch-mode can be made modal (in the sense of not returning to - ;; the calling function until searching is completed) by entering + ;; isearch-mode can be made modal (in the sense of not returning to + ;; the calling function until searching is completed) by entering ;; a recursive-edit and exiting it when done isearching. (if recursive-edit (let ((isearch-recursive-edit t)) (recursive-edit))) - isearch-success) + ) ;;;==================================================== ;; Some high level utilities. Others below. (defun isearch-update () - ;; Called after each command to update the display. - (if (null unread-command-events) + ;; Called after each command to update the display. + (if (null unread-command-event) (progn (if (not (input-pending-p)) (isearch-message)) (if (and isearch-slow-terminal-mode - (not (or isearch-small-window + (not (or isearch-small-window (pos-visible-in-window-p)))) (let ((found-point (point))) (setq isearch-small-window t) @@ -606,24 +520,27 @@ (if (< isearch-other-end (point)) (isearch-highlight isearch-other-end (point)) (isearch-highlight (point) isearch-other-end)) - (isearch-dehighlight)) + (if (extentp isearch-extent) + (isearch-dehighlight nil))) )) (setq ;; quit-flag nil not for isearch-mode isearch-adjusted nil isearch-yank-flag nil) - (isearch-highlight-all-update) ) -(defun isearch-done (&optional nopush edit) +(defun isearch-done () ;; Called by all commands that terminate isearch-mode. (let ((inhibit-quit t)) ; danger danger! (if (and isearch-buffer (buffer-live-p isearch-buffer)) - ;; Some loser process filter might have switched the window's - ;; buffer, so be sure to set these variables back in the - ;; buffer we frobbed them in. But only if the buffer is still - ;; alive. - (with-current-buffer isearch-buffer + (save-excursion + ;; Some loser process filter might have switched the + ;; window's buffer, so be sure to set these variables back + ;; in the buffer we frobbed them in. But only if the buffer + ;; is still alive. + (set-buffer isearch-buffer) + ;; #### Should we restore the old value of + ;; overriding-local-map? (setq overriding-local-map nil) ;; Use remove-hook instead of just setting it to our saved value ;; in case some process filter has created a buffer and modified @@ -632,11 +549,8 @@ (remove-hook 'pre-command-hook 'isearch-pre-command-hook) (set-keymap-parents isearch-mode-map nil) (setq isearch-mode nil) - (redraw-modeline) - (isearch-dehighlight) - (isearch-highlight-all-cleanup) - (isearch-restore-invisible-extents nil nil) - )) + (set-buffer-modified-p (buffer-modified-p));; update modeline + (isearch-dehighlight t))) ;; it's not critical that this be inside inhibit-quit, but leaving ;; things in small-window-mode would be bad. @@ -654,41 +568,37 @@ ;; Maybe should test difference between and set mark iff > threshold. (if (and (buffer-live-p isearch-buffer) (/= (point isearch-buffer) isearch-opoint)) - ;; #### FSF doesn't do this if the region is active. Should - ;; we do the same? (progn (push-mark isearch-opoint t nil isearch-buffer) (or executing-kbd-macro (> (minibuffer-depth) 0) - (display-message 'command "Mark saved where search started"))))) + (display-message 'command "Mark saved where search started")))) + ) (setq isearch-buffer nil) ) ; inhibit-quit is t before here - (if (and (> (length isearch-string) 0) (not nopush)) + (if (> (length isearch-string) 0) ;; Update the ring data. - (isearch-update-ring isearch-string isearch-regexp)) + (if isearch-regexp + (if (not (setq regexp-search-ring-yank-pointer + (member isearch-string regexp-search-ring))) + (progn + (setq regexp-search-ring + (cons isearch-string regexp-search-ring) + regexp-search-ring-yank-pointer regexp-search-ring) + (if (> (length regexp-search-ring) regexp-search-ring-max) + (setcdr (nthcdr (1- regexp-search-ring-max) regexp-search-ring) + nil)))) + (if (not (setq search-ring-yank-pointer + ;; really need equal test instead of eq. + (member isearch-string search-ring))) + (progn + (setq search-ring (cons isearch-string search-ring) + search-ring-yank-pointer search-ring) + (if (> (length search-ring) search-ring-max) + (setcdr (nthcdr (1- search-ring-max) search-ring) nil)))))) (run-hooks 'isearch-mode-end-hook) - - (and (not edit) isearch-recursive-edit (exit-recursive-edit))) - -(defun isearch-update-ring (string &optional regexp) - "Add STRING to the beginning of the search ring. -REGEXP says which ring to use." - (if regexp - (if (or (null regexp-search-ring) - (not (string= string (car regexp-search-ring)))) - (progn - (setq regexp-search-ring - (cons string regexp-search-ring)) - (if (> (length regexp-search-ring) regexp-search-ring-max) - (setcdr (nthcdr (1- search-ring-max) regexp-search-ring) - nil)))) - (if (or (null search-ring) - (not (string= string (car search-ring)))) - (progn - (setq search-ring (cons string search-ring)) - (if (> (length search-ring) search-ring-max) - (setcdr (nthcdr (1- search-ring-max) search-ring) nil)))))) + (if isearch-recursive-edit (exit-recursive-edit))) ;;;==================================================== @@ -697,16 +607,12 @@ (defun isearch-exit () "Exit search normally. However, if this is the first command after starting incremental -search and `search-nonincremental-instead' is non-nil, do a -nonincremental search instead via `isearch-edit-string'." +search and `search-nonincremental-instead' is non-nil, do an +incremental search via `isearch-edit-string'." (interactive) - (if (and search-nonincremental-instead + (if (and search-nonincremental-instead (= 0 (length isearch-string))) - (let ((isearch-nonincremental t) - ;; Highlighting only gets in the way of nonincremental - ;; search. - (search-highlight nil) - (isearch-highlight-all-matches nil)) + (let ((isearch-nonincremental t)) (isearch-edit-string)) (isearch-done))) @@ -715,112 +621,115 @@ "Edit the search string in the minibuffer. The following additional command keys are active while editing. \\<minibuffer-local-isearch-map> -\\[exit-minibuffer] to resume incremental searching with the edited string. -\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search. +\\[exit-minibuffer] to exit editing and resume incremental searching. \\[isearch-forward-exit-minibuffer] to resume isearching forward. -\\[isearch-reverse-exit-minibuffer] to resume isearching backward. -\\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring. -\\[isearch-ring-retreat-edit] to replace the search string with the previous item in the search ring. -\\[isearch-complete-edit] to complete the search string using the search ring. -\\<isearch-mode-map> -If first char entered is \\[isearch-yank-word], then do word search instead." +\\[isearch-backward-exit-minibuffer] to resume isearching backward. +\\[isearch-ring-advance-edit] to replace the search string with the next\ + item in the search ring. +\\[isearch-ring-retreat-edit] to replace the search string with the next\ + item in the search ring. +\\[isearch-complete-edit] to complete the search string from the search ring." - ;; This code is very hairy for several reasons, explained in the code. - ;; Mainly, isearch-mode must be terminated while editing and then restarted. - ;; If there were a way to catch any change of buffer from the minibuffer, - ;; this could be simplified greatly. ;; Editing doesn't back up the search point. Should it? (interactive) (condition-case nil - (progn - (let ((isearch-nonincremental isearch-nonincremental) + (let ((minibuffer-local-map minibuffer-local-isearch-map) + isearch-nonincremental ; should search nonincrementally? + isearch-new-string + isearch-new-message + (isearch-new-forward isearch-forward) - ;; Locally bind all isearch global variables to protect them - ;; from recursive isearching. - ;; isearch-string -message and -forward are not bound - ;; so they may be changed. Instead, save the values. - (isearch-new-string isearch-string) - (isearch-new-message isearch-message) - (isearch-new-forward isearch-forward) - (isearch-new-word isearch-word) + ;; Locally bind all isearch global variables to protect them + ;; from recursive isearching. + (isearch-string isearch-string) + (isearch-message isearch-message) + (isearch-forward isearch-forward) ; set by commands below. - (isearch-regexp isearch-regexp) - (isearch-op-fun isearch-op-fun) - (isearch-cmds isearch-cmds) - (isearch-success isearch-success) - (isearch-wrapped isearch-wrapped) - (isearch-barrier isearch-barrier) - (isearch-adjusted isearch-adjusted) - (isearch-fixed-case isearch-fixed-case) - (isearch-yank-flag isearch-yank-flag) - (isearch-invalid-regexp isearch-invalid-regexp) - (isearch-within-brackets isearch-within-brackets) - ;;; Don't bind this. We want isearch-search, below, to set it. - ;;; And the old value won't matter after that. - ;;; (isearch-other-end isearch-other-end) - (isearch-opoint isearch-opoint) - (isearch-slow-terminal-mode isearch-slow-terminal-mode) - (isearch-small-window isearch-small-window) - (isearch-recursive-edit isearch-recursive-edit) - (isearch-window-configuration (current-window-configuration)) - (isearch-selected-frame (selected-frame)) - ) - ;; Actually terminate isearching until editing is done. - ;; This is so that the user can do anything without failure, - ;; like switch buffers and start another isearch, and return. + (isearch-forward isearch-forward) + (isearch-regexp isearch-regexp) + (isearch-word isearch-word) + (isearch-op-fun isearch-op-fun) + (isearch-cmds isearch-cmds) + (isearch-success isearch-success) + (isearch-wrapped isearch-wrapped) + (isearch-barrier isearch-barrier) + (isearch-adjusted isearch-adjusted) + (isearch-yank-flag isearch-yank-flag) + (isearch-invalid-regexp isearch-invalid-regexp) + (isearch-other-end isearch-other-end) + (isearch-opoint isearch-opoint) + (isearch-slow-terminal-mode isearch-slow-terminal-mode) + (isearch-small-window isearch-small-window) + (isearch-recursive-edit isearch-recursive-edit) + (isearch-window-configuration (current-window-configuration)) + (isearch-selected-frame (selected-frame)) + ) + ;; Actually terminate isearching until editing is done. + ;; This is so that the user can do anything without failure, + ;; like switch buffers and start another isearch, and return. ;; (condition-case nil - (isearch-done t t) + (isearch-done) ;;#### What does this mean? There is no such condition! -;; (exit nil)) ; was recursive editing +;; (exit nil)) ; was recursive editing - (unwind-protect - (progn - ;; Fake the prompt message for the sake of - ;; next-command-event below. - (isearch-message) - ;; If the first character the user types when we - ;; prompt them for a string is the yank-word - ;; character, then go into word-search mode. - ;; Otherwise unread that character and read a string - ;; the normal way. - (let* ((cursor-in-echo-area t) - (event (next-command-event))) - (if (eq 'isearch-yank-word - (lookup-key isearch-mode-map (vector event))) - (setq isearch-word t;; so message-prefix is right - isearch-new-word t) - (setq unread-command-event event))) - (setq isearch-new-string - (read-from-minibuffer - (isearch-message-prefix nil isearch-nonincremental) - isearch-string - minibuffer-local-isearch-map - nil - 't ;does its own history (but shouldn't) + (unwind-protect + (let ((prompt (isearch-message-prefix nil t)) + event) + ;; If the first character the user types when we prompt them + ;; for a string is the yank-word character, then go into + ;; word-search mode. Otherwise unread that character and + ;; read a string the normal way. + (let ((cursor-in-echo-area t)) + (display-message 'prompt prompt) + (setq event (next-command-event)) + (if (eq 'isearch-yank-word + (lookup-key isearch-mode-map (vector event))) + (setq isearch-word t) + (setq unread-command-event event))) + (setq isearch-new-string +;; (if (fboundp 'gmhist-old-read-from-minibuffer) +;; ;; Eschew gmhist crockery +;; (gmhist-old-read-from-minibuffer prompt isearch-string) + (read-string + prompt isearch-string + 't ;does its own history (but shouldn't) +;; (if isearch-regexp +;; ;; The search-rings aren't exactly minibuffer +;; ;; histories, but they are close enough +;; (cons 'regexp-search-ring +;; (- (length regexp-search-ring-yank-pointer) +;; (length regexp-search-ring))) +;; (cons 'search-ring +;; (- (length search-ring-yank-pointer) +;; (length search-ring)))) ) - isearch-new-message (mapconcat - 'isearch-text-char-description - isearch-new-string ""))) - ;; Always resume isearching by restarting it. - (isearch-mode isearch-forward - isearch-regexp - isearch-op-fun - isearch-recursive-edit - isearch-word) +;; ) + isearch-new-message (mapconcat + 'isearch-text-char-description + isearch-new-string "")) + ) + ;; Always resume isearching by restarting it. + (isearch-mode isearch-forward + isearch-regexp + isearch-op-fun + isearch-recursive-edit + isearch-word) + ) - ;; Copy new values in outer locals to isearch globals - (setq isearch-string isearch-new-string - isearch-message isearch-new-message - isearch-forward isearch-new-forward - isearch-word isearch-new-word)) + ;; Copy new values in outer locals to isearch globals + (setq isearch-string isearch-new-string + isearch-message isearch-new-message + isearch-forward isearch-new-forward) - ;; Empty isearch-string means use default. - (if (= 0 (length isearch-string)) - (setq isearch-string (or (car (if isearch-regexp - regexp-search-ring - search-ring)) - "")))) + ;; Empty isearch-string means use default. + (if (= 0 (length isearch-string)) + (setq isearch-string (if isearch-regexp search-last-regexp + search-last-string)) + ;; Set last search string now so it is set even if we fail. + (if search-last-regexp + (setq search-last-regexp isearch-string) + (setq search-last-string isearch-string))) ;; Reinvoke the pending search. (isearch-push-state) @@ -847,33 +756,25 @@ (setq isearch-new-forward nil) (exit-minibuffer)) -(defun isearch-cancel () - "Terminate the search and go back to the starting point." - (interactive) - (goto-char isearch-opoint) - (isearch-done t) - (signal 'quit '(isearch))) ; and pass on quit signal (defun isearch-abort () - "Abort incremental search mode if searching is successful, signaling quit. + "Quit incremental search mode if searching is successful, signalling quit. Otherwise, revert to previous successful search and continue searching. -Use `isearch-exit' to quit without signaling." +Use `isearch-exit' to quit without signalling." (interactive) -;; (ding) signal instead below, if quitting +;; (ding) signal instead below, if quiting (discard-input) (if isearch-success ;; If search is successful, move back to starting point ;; and really do quit. (progn (goto-char isearch-opoint) - (setq isearch-success nil) - (isearch-done t) ; exit isearch + (isearch-done) ; exit isearch (signal 'quit '(isearch))) ; and pass on quit signal - ;; If search is failing, or has an incomplete regexp, - ;; rub out until it is once more successful. - (while (or (not isearch-success) isearch-invalid-regexp) - (isearch-pop-state)) + ;; If search is failing, rub out until it is once more successful. + (while (not isearch-success) (isearch-pop-state)) (isearch-update))) + (defun isearch-repeat (direction) ;; Utility for isearch-repeat-forward and -backward. (if (eq isearch-forward (eq direction 'forward)) @@ -882,30 +783,35 @@ ;; If search string is empty, use last one. (setq isearch-string (or (if isearch-regexp - (car regexp-search-ring) - (car search-ring)) + (if regexp-search-ring-yank-pointer + (car regexp-search-ring-yank-pointer) + (car regexp-search-ring)) + (if search-ring-yank-pointer + (car search-ring-yank-pointer) + (car search-ring))) "") isearch-message (mapconcat 'isearch-text-char-description isearch-string "")) ;; If already have what to search for, repeat it. (or isearch-success - (progn + (progn + (goto-char (if isearch-forward (point-min) (point-max))) (setq isearch-wrapped t)))) ;; C-s in reverse or C-r in forward, change direction. (setq isearch-forward (not isearch-forward))) (setq isearch-barrier (point)) ; For subsequent \| if regexp. - (if (equal isearch-string "") (setq isearch-success t) - (if (and isearch-success (equal (match-end 0) (match-beginning 0)) + (if (and (equal (match-end 0) (match-beginning 0)) + isearch-success (not isearch-just-started)) ;; If repeating a search that found ;; an empty string, ensure we advance. (if (if isearch-forward (eobp) (bobp)) - ;; If there's nowhere to advance to, fail (and wrap next time). + ;; nowhere to advance to, so fail (and wrap next time) (progn (setq isearch-success nil) (and executing-kbd-macro @@ -915,7 +821,6 @@ (forward-char (if isearch-forward 1 -1)) (isearch-search)) (isearch-search))) - (isearch-push-state) (isearch-update)) @@ -940,21 +845,18 @@ (defun isearch-toggle-case-fold () "Toggle case folding in searching on or off." (interactive) - (setq isearch-case-fold-search (if isearch-case-fold-search nil 'yes) - isearch-fixed-case t) - (lmessage 'progress "%s%s [case %ssensitive]" - (isearch-message-prefix) - isearch-message - (if isearch-case-fold-search "in" "")) + (setq isearch-case-fold-search + (if isearch-case-fold-search nil 'yes)) + (message "%s%s [case %ssensitive]" + (isearch-message-prefix) + isearch-message + (if isearch-case-fold-search "in" "")) (setq isearch-adjusted t) - ;; Update the highlighting here so that it gets done before the - ;; one-second pause. - (isearch-highlight-all-update) (sit-for 1) (isearch-update)) (defun isearch-delete-char () - "Discard last input item and move point back. + "Discard last input item and move point back. If no previous match was done, just beep." (interactive) (if (null (cdr isearch-cmds)) @@ -974,7 +876,6 @@ (isearch-delete-char) (isearch-mode-help))) -;; This is similar to FSF isearch-yank-string, but more general. (defun isearch-yank (chunk) ;; Helper for isearch-yank-* functions. CHUNK can be a string or a ;; function. @@ -985,7 +886,7 @@ (goto-char isearch-other-end)) (buffer-substring (point) - (progn + (save-excursion (funcall chunk) (point))))))) ;; if configured so that typing upper-case characters turns off case @@ -1003,6 +904,7 @@ isearch-yank-flag t)) (isearch-search-and-update)) + (defun isearch-yank-word () "Pull next word from buffer into search string." (interactive) @@ -1023,34 +925,30 @@ (interactive) (isearch-yank 'forward-sexp)) -(defun isearch-yank-selection () - "Pull the current selection into the search string." +(defun isearch-yank-x-selection () + "Pull the current X selection into the search string." (interactive) - (isearch-yank (get-selection))) + (isearch-yank (x-get-selection))) -(defun isearch-yank-clipboard () - "Pull the current clipboard selection into the search string." +(defun isearch-yank-x-clipboard () + "Pull the current X clipboard selection into the search string." (interactive) - (isearch-yank (get-clipboard))) + (isearch-yank (x-get-clipboard))) (defun isearch-fix-case () - ;; The commented-out (and ...) form implies that, once - ;; isearch-case-fold-search becomes nil due to a capital letter - ;; typed in, it can never be restored to the original value. In - ;; that case, it's impossible to revert a case-sensitive search back - ;; to case-insensitive. - (if ;(and isearch-case-fold-search search-caps-disable-folding) - (and case-fold-search - ;; Make sure isearch-toggle-case-fold works. - (not isearch-fixed-case) - search-caps-disable-folding) - (setq isearch-case-fold-search + (if (and isearch-case-fold-search search-caps-disable-folding) + (setq isearch-case-fold-search (no-upper-case-p isearch-string isearch-regexp))) (setq isearch-mode (if case-fold-search (if isearch-case-fold-search " Isearch" ;As God Intended Mode " ISeARch") ;Warn about evil case via StuDLYcAps. - " Isearch"))) + "Isearch" +; (if isearch-case-fold-search +; " isearch" ;Presumably case-sensitive losers +; ;will notice this 1-char difference. +; " Isearch") ;Weenie mode. + ))) (defun isearch-search-and-update () ;; Do the search and update the display. @@ -1074,17 +972,16 @@ (regexp-quote isearch-string))))) (error nil)) (or isearch-yank-flag - (<= (match-end 0) + (<= (match-end 0) (min isearch-opoint isearch-barrier)))) - (setq isearch-success t + (setq isearch-success t isearch-invalid-regexp nil - isearch-within-brackets nil isearch-other-end (match-end 0)) ;; Not regexp, not reverse, or no match at point. (if (and isearch-other-end (not isearch-adjusted)) (goto-char (if isearch-forward isearch-other-end - (min isearch-opoint - isearch-barrier + (min isearch-opoint + isearch-barrier (1+ isearch-other-end))))) (isearch-search) )) @@ -1094,34 +991,31 @@ ;; *, ?, and | chars can make a regexp more liberal. -;; They can make a regexp match sooner or make it succeed instead of failing. +;; They can make a regexp match sooner +;; or make it succeed instead of failing. ;; So go back to place last successful search started ;; or to the last ^S/^R (barrier), whichever is nearer. -;; + needs no special handling because the string must match at least once. (defun isearch-*-char () "Handle * and ? specially in regexps." (interactive) - (if isearch-regexp - (let ((idx (length isearch-string))) - (while (and (> idx 0) - (eq (aref isearch-string (1- idx)) ?\\)) - (setq idx (1- idx))) - (when (= (mod (- (length isearch-string) idx) 2) 0) - (setq isearch-adjusted t) - ;; Get the isearch-other-end from before the last search. - ;; We want to start from there, - ;; so that we don't retreat farther than that. + (if isearch-regexp + + (progn + (setq isearch-adjusted t) + (let ((cs (nth (if isearch-forward + 5 ; isearch-other-end + 2) ; saved (point) + (car (cdr isearch-cmds))))) ;; (car isearch-cmds) is after last search; ;; (car (cdr isearch-cmds)) is from before it. - (let ((cs (nth 5 (car (cdr isearch-cmds))))) - (setq cs (or cs isearch-barrier)) - (goto-char - (if isearch-forward - (max cs isearch-barrier) - (min cs isearch-barrier))))))) + (setq cs (or cs isearch-barrier)) + (goto-char + (if isearch-forward + (max cs isearch-barrier) + (min cs isearch-barrier)))))) (isearch-process-search-char last-command-event)) - + (defun isearch-|-char () @@ -1133,59 +1027,42 @@ (goto-char isearch-barrier))) (isearch-process-search-char last-command-event)) -;; FSF: -;(defalias 'isearch-other-control-char 'isearch-other-meta-char) -; -;(defun isearch-other-meta-char () -;... -; - (defun isearch-quote-char () "Quote special characters for incremental search." (interactive) - ;; #### Here FSF does some special conversion of chars in 0200-0377 - ;; range. Maybe we should do the same. (isearch-process-search-char (read-quoted-char (isearch-message t)))) + (defun isearch-return-char () "Convert return into newline for incremental search. Obsolete." (interactive) (isearch-process-search-char ?\n)) + (defun isearch-printing-char () - "Add this ordinary printing character to the search string and search." + "Any other printing character => add it to the search string and search." (interactive) - (let ((event last-command-event)) - ;; If we are called by isearch-whitespace-chars because the - ;; context disallows whitespace search (e.g. within brackets), - ;; replace M-SPC with a space. FSF has similar code. - (and (eq this-command 'isearch-whitespace-chars) - (null (event-to-character event)) - (setq event (character-to-event ?\ ))) - (isearch-process-search-char event))) + (isearch-process-search-char last-command-event)) + (defun isearch-whitespace-chars () "Match all whitespace chars, if in regexp mode." - ;; FSF docstring adds: "If you want to search for just a space, type - ;; C-q SPC." But we don't need the addition because we have a - ;; different (better) default for the variable. (interactive) - (if isearch-regexp - (if (and search-whitespace-regexp (not isearch-within-brackets) - (not isearch-invalid-regexp)) - (isearch-process-search-string search-whitespace-regexp " ") - (isearch-printing-char)) - (progn - ;; This way of doing word search doesn't correctly extend current search. - ;; (setq isearch-word t) - ;; (setq isearch-adjusted t) - ;; (goto-char isearch-barrier) - (isearch-printing-char)))) + (if (and isearch-regexp search-whitespace-regexp) + (isearch-process-search-string search-whitespace-regexp " ") + (beep) + (isearch-process-search-char ?\ ) +; (if isearch-word +; nil +; (setq isearch-word t) +; (goto-char isearch-other-end) +; (isearch-process-search-char ?\ )) + )) (defun isearch-process-search-char (char) ;; Append the char to the search string, update the message and re-search. - (isearch-process-search-string (isearch-char-to-string char) + (isearch-process-search-string (isearch-char-to-string char) (isearch-text-char-description char))) (defun isearch-process-search-string (string message) @@ -1197,6 +1074,12 @@ ;;=========================================================== ;; Search Ring +(defcustom search-ring-update nil + "*Non-nil if advancing or retreating in the search ring should cause search. +Default nil means edit the string from the search ring first." + :type 'boolean + :group 'isearch) + (defun isearch-ring-adjust1 (advance) ;; Helper for isearch-ring-adjust (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) @@ -1209,25 +1092,25 @@ () (set yank-pointer-name (setq yank-pointer - (mod (+ (or yank-pointer 0) - (if advance -1 1)) - length))) - (setq isearch-string (nth yank-pointer ring) + (nthcdr (% (+ (- length (length yank-pointer)) + (if advance (1- length) 1)) + length) ring))) + (setq isearch-string (car yank-pointer) isearch-message (mapconcat 'isearch-text-char-description isearch-string ""))))) (defun isearch-ring-adjust (advance) ;; Helper for isearch-ring-advance and isearch-ring-retreat -; (if (cdr isearch-cmds) ;; is there more than one thing on stack? -; (isearch-pop-state)) + (if (cdr isearch-cmds) ;; is there more than one thing on stack? + (isearch-pop-state)) (isearch-ring-adjust1 advance) + (isearch-push-state) (if search-ring-update (progn (isearch-search) (isearch-update)) (isearch-edit-string) - ) - (isearch-push-state)) + )) (defun isearch-ring-advance () "Advance to the next search string in the ring." @@ -1240,59 +1123,30 @@ (interactive) (isearch-ring-adjust nil)) -(defun isearch-ring-advance-edit (n) - "Insert the next element of the search history into the minibuffer." - (interactive "p") - (let* ((yank-pointer-name (if isearch-regexp - 'regexp-search-ring-yank-pointer - 'search-ring-yank-pointer)) - (yank-pointer (eval yank-pointer-name)) - (ring (if isearch-regexp regexp-search-ring search-ring)) - (length (length ring))) - (if (zerop length) - () - (set yank-pointer-name - (setq yank-pointer - (mod (- (or yank-pointer 0) n) - length))) - - (erase-buffer) - (insert (nth yank-pointer ring)) - (goto-char (point-max))))) +(defun isearch-ring-adjust-edit (advance) + "Use the next or previous search string in the ring while in minibuffer." + (isearch-ring-adjust1 advance) + (erase-buffer) + (insert isearch-string)) -(defun isearch-ring-retreat-edit (n) - "Inserts the previous element of the search history into the minibuffer." - (interactive "p") - (isearch-ring-advance-edit (- n))) - -;; Merging note: FSF comments out these functions and implements them -;; differently (see above), presumably because the versions below mess -;; with isearch-string, while what we really want them to do is simply -;; to insert the correct string to the minibuffer. +(defun isearch-ring-advance-edit () + (interactive) + (isearch-ring-adjust-edit 'advance)) -;;(defun isearch-ring-adjust-edit (advance) -;; "Use the next or previous search string in the ring while in minibuffer." -;; (isearch-ring-adjust1 advance) -;; (erase-buffer) -;; (insert isearch-string)) - -;;(defun isearch-ring-advance-edit () -;; (interactive) -;; (isearch-ring-adjust-edit 'advance)) - -;;(defun isearch-ring-retreat-edit () -;; "Retreat to the previous search string in the ring while in the minibuffer." -;; (interactive) -;; (isearch-ring-adjust-edit nil)) +(defun isearch-ring-retreat-edit () + "Retreat to the previous search string in the ring while in the minibuffer." + (interactive) + (isearch-ring-adjust-edit nil)) (defun isearch-complete1 () ;; Helper for isearch-complete and isearch-complete-edit - ;; Return t if completion OK, nil if no completion exists. + ;; Return t if completion OK, (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) (alist (mapcar (function (lambda (string) (list string))) ring)) (completion-ignore-case case-fold-search) - (completion (try-completion isearch-string alist))) + (completion (try-completion isearch-string alist)) + ) (cond ((eq completion t) ;; isearch-string stays the same @@ -1300,14 +1154,12 @@ ((or completion ; not nil, must be a string (= 0 (length isearch-string))) ; shouldn't have to say this (if (equal completion isearch-string) ;; no extension? - (progn - (if completion-auto-help - (with-output-to-temp-buffer "*Isearch completions*" - (display-completion-list - (all-completions isearch-string alist)))) - t) - (and completion - (setq isearch-string completion)))) + (if completion-auto-help + (with-output-to-temp-buffer "*Isearch completions*" + (display-completion-list + (all-completions isearch-string alist)))) + (setq isearch-string completion)) + t) (t (temp-minibuffer-message "No completion") nil)))) @@ -1334,61 +1186,32 @@ ;;;============================================================== -;; The search status stack. +;; The search status stack (and isearch window-local variables, not used). (defun isearch-top-state () +;; (fetch-window-local-variables) (let ((cmd (car isearch-cmds))) - ;; #### Grr, this is so error-prone. If you add something to - ;; isearch-push-state, don't forget to update this. I thought I'd - ;; make a list of variables, and just do (mapcar* #'set vars - ;; values), but the (point) thing would spoil it, leaving to more - ;; complication. (setq isearch-string (car cmd) isearch-message (car (cdr cmd)) isearch-success (nth 3 cmd) isearch-forward (nth 4 cmd) isearch-other-end (nth 5 cmd) - isearch-word (nth 6 cmd) - isearch-invalid-regexp (nth 7 cmd) - isearch-wrapped (nth 8 cmd) - isearch-barrier (nth 9 cmd) - isearch-within-brackets (nth 10 cmd)) + isearch-invalid-regexp (nth 6 cmd) + isearch-wrapped (nth 7 cmd) + isearch-barrier (nth 8 cmd)) (goto-char (car (cdr (cdr cmd)))))) (defun isearch-pop-state () - (pop isearch-cmds) +;; (fetch-window-local-variables) + (setq isearch-cmds (cdr isearch-cmds)) (isearch-top-state) - - ;; Make sure isearch-case-fold-search gets the correct value. FSF - ;; simply stores isearch-case-fold-search to isearch-cmds. We - ;; should probably do the same. - (isearch-fix-case) - - ;; Here, as well as in isearch-search we must deal with the point - ;; landing at an invisible area which may need unhiding. - (if (or (not (eq search-invisible 'open)) - (not isearch-hide-immediately)) - ;; If search-invisible is t, invisible text is just like any - ;; other text. If it is nil, it is always skipped and we can't - ;; land inside. In both cases, we don't need to do anything. - ;; - ;; Similarly, if isearch-hide-immediately is nil, needn't - ;; re-hide the area here, and neither can we land back into a - ;; hidden one. - nil - (when isearch-other-end - ;; This will unhide the extents. - (isearch-range-invisible (point) isearch-other-end)) - (isearch-restore-invisible-extents (point) - (or isearch-other-end (point))))) + ) (defun isearch-push-state () - (setq isearch-cmds + (setq isearch-cmds (cons (list isearch-string isearch-message (point) - isearch-success isearch-forward isearch-other-end - isearch-word - isearch-invalid-regexp isearch-wrapped isearch-barrier - isearch-within-brackets) + isearch-success isearch-forward isearch-other-end + isearch-invalid-regexp isearch-wrapped isearch-barrier) isearch-cmds))) @@ -1399,41 +1222,27 @@ ;; Generate and print the message string. (let ((cursor-in-echo-area ellipsis) (m (concat - (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental) + (isearch-message-prefix c-q-hack) isearch-message - (isearch-message-suffix c-q-hack ellipsis) + (isearch-message-suffix c-q-hack) ))) - (if c-q-hack - m - (display-message 'progress (format "%s" m))))) + (if c-q-hack m (display-message 'progress (format "%s" m))))) -(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental) +(defun isearch-message-prefix (&optional c-q-hack nonincremental) ;; If about to search, and previous search regexp was invalid, ;; check that it still is. If it is valid now, ;; let the message we display while searching say that it is valid. - (and isearch-invalid-regexp ellipsis + (and isearch-invalid-regexp (condition-case () (progn (re-search-forward isearch-string (point) t) - (setq isearch-invalid-regexp nil - isearch-within-brackets nil)) + (setq isearch-invalid-regexp nil)) (error nil))) - ;; If currently failing, display no ellipsis. - (or isearch-success (setq ellipsis nil)) - ;; #### - ! Emacs assembles strings all over the place, they can't - ;; all be internationalized in the manner proposed below... Add an - ;; explicit call to `gettext' and have the string snarfer pluck the - ;; english strings out of the comment below. XEmacs is on a - ;; purespace diet! -Stig - - ;; The comment below is dead and buried, but it can be rebuilt if - ;; necessary. -hniksic + ;; #### - Yo! Emacs assembles strings all over the place, they can't all + ;; be internationalized in the manner proposed below... Add an explicit + ;; call to `gettext' and have the string snarfer pluck the english + ;; strings out of the comment below. XEmacs is on a purespace diet! -Stig (let ((m (concat (if isearch-success nil "failing ") - (if (and isearch-wrapped - (if isearch-forward - (> (point) isearch-opoint) - (< (point) isearch-opoint))) - "overwrapped " - (if isearch-wrapped "wrapped ")) + (if isearch-wrapped "wrapped ") (if isearch-word "word ") (if isearch-regexp "regexp ") (if nonincremental "search" "I-search") @@ -1443,12 +1252,14 @@ (aset m 0 (upcase (aref m 0))) (gettext m))) -(defun isearch-message-suffix (&optional c-q-hack ellipsis) +(defun isearch-message-suffix (&optional c-q-hack) (concat (if c-q-hack "^Q" "") (if isearch-invalid-regexp (concat " [" isearch-invalid-regexp "]") ""))) +;;;;; #### - yuck...this is soooo lame. Is this really worth 4k of purespace??? +;;; ;;;(let ((i (logior (if isearch-success 32 0) ;;; (if isearch-wrapped 16 0) ;;; (if isearch-word 8 0) @@ -1457,7 +1268,68 @@ ;;; (if isearch-forward 1 0)))) ;;; (cond ;;; ((= i 63) (gettext "Wrapped word regexp search: ")) ; 111111 -;;; ...and so on, ad nauseam... +;;; ((= i 62) (gettext "Wrapped word regexp search backward: ")) ; 111110 +;;; ((= i 61) (gettext "Wrapped word regexp I-search: ")) ; 111101 +;;; ((= i 60) (gettext "Wrapped word regexp I-search backward: ")) ; 111100 +;;; ((= i 59) (gettext "Wrapped word search: ")) ; 111011 +;;; ((= i 58) (gettext "Wrapped word search backward: ")) ; 111010 +;;; ((= i 57) (gettext "Wrapped word I-search: ")) ; 111001 +;;; ((= i 56) (gettext "Wrapped word I-search backward: ")) ; 111000 +;;; ((= i 55) (gettext "Wrapped regexp search: ")) ; 110111 +;;; ((= i 54) (gettext "Wrapped regexp search backward: ")) ; 110110 +;;; ((= i 53) (gettext "Wrapped regexp I-search: ")) ; 110101 +;;; ((= i 52) (gettext "Wrapped regexp I-search backward: ")) ; 110100 +;;; ((= i 51) (gettext "Wrapped search: ")) ; 110011 +;;; ((= i 50) (gettext "Wrapped search backward: ")) ; 110010 +;;; ((= i 49) (gettext "Wrapped I-search: ")) ; 110001 +;;; ((= i 48) (gettext "Wrapped I-search backward: ")) ; 110000 +;;; ((= i 47) (gettext "Word regexp search: ")) ; 101111 +;;; ((= i 46) (gettext "Word regexp search backward: ")) ; 101110 +;;; ((= i 45) (gettext "Word regexp I-search: ")) ; 101101 +;;; ((= i 44) (gettext "Word regexp I-search backward: ")) ; 101100 +;;; ((= i 43) (gettext "Word search: ")) ; 101011 +;;; ((= i 42) (gettext "Word search backward: ")) ; 101010 +;;; ((= i 41) (gettext "Word I-search: ")) ; 101001 +;;; ((= i 40) (gettext "Word I-search backward: ")) ; 101000 +;;; ((= i 39) (gettext "Regexp search: ")) ; 100111 +;;; ((= i 38) (gettext "Regexp search backward: ")) ; 100110 +;;; ((= i 37) (gettext "Regexp I-search: ")) ; 100101 +;;; ((= i 36) (gettext "Regexp I-search backward: ")) ; 100100 +;;; ((= i 35) (gettext "Search: ")) ; 100011 +;;; ((= i 34) (gettext "Search backward: ")) ; 100010 +;;; ((= i 33) (gettext "I-search: ")) ; 100001 +;;; ((= i 32) (gettext "I-search backward: ")) ; 100000 +;;; ((= i 31) (gettext "Failing wrapped word regexp search: ")) ; 011111 +;;; ((= i 30) (gettext "Failing wrapped word regexp search backward: ")) ; 011110 +;;; ((= i 29) (gettext "Failing wrapped word regexp I-search: ")) ; 011101 +;;; ((= i 28) (gettext "Failing wrapped word regexp I-search backward: ")) ; 011100 +;;; ((= i 27) (gettext "Failing wrapped word search: ")) ; 011011 +;;; ((= i 26) (gettext "Failing wrapped word search backward: ")) ; 011010 +;;; ((= i 25) (gettext "Failing wrapped word I-search: ")) ; 011001 +;;; ((= i 24) (gettext "Failing wrapped word I-search backward: ")) ; 011000 +;;; ((= i 23) (gettext "Failing wrapped regexp search: ")) ; 010111 +;;; ((= i 22) (gettext "Failing wrapped regexp search backward: ")) ; 010110 +;;; ((= i 21) (gettext "Failing wrapped regexp I-search: ")) ; 010101 +;;; ((= i 20) (gettext "Failing wrapped regexp I-search backward: ")) ; 010100 +;;; ((= i 19) (gettext "Failing wrapped search: ")) ; 010011 +;;; ((= i 18) (gettext "Failing wrapped search backward: ")) ; 010010 +;;; ((= i 17) (gettext "Failing wrapped I-search: ")) ; 010001 +;;; ((= i 16) (gettext "Failing wrapped I-search backward: ")) ; 010000 +;;; ((= i 15) (gettext "Failing word regexp search: ")) ; 001111 +;;; ((= i 14) (gettext "Failing word regexp search backward: ")) ; 001110 +;;; ((= i 13) (gettext "Failing word regexp I-search: ")) ; 001101 +;;; ((= i 12) (gettext "Failing word regexp I-search backward: ")) ; 001100 +;;; ((= i 11) (gettext "Failing word search: ")) ; 001011 +;;; ((= i 10) (gettext "Failing word search backward: ")) ; 001010 +;;; ((= i 9) (gettext "Failing word I-search: ")) ; 001001 +;;; ((= i 8) (gettext "Failing word I-search backward: ")) ; 001000 +;;; ((= i 7) (gettext "Failing regexp search: ")) ; 000111 +;;; ((= i 6) (gettext "Failing regexp search backward: ")) ; 000110 +;;; ((= i 5) (gettext "Failing regexp I-search: ")) ; 000101 +;;; ((= i 4) (gettext "Failing regexp I-search backward: ")) ; 000100 +;;; ((= i 3) (gettext "Failing search: ")) ; 000011 +;;; ((= i 2) (gettext "Failing search backward: ")) ; 000010 +;;; ((= i 1) (gettext "Failing I-search: ")) ; 000001 ;;; ((= i 0) (gettext "Failing I-search backward: ")) ; 000000 ;;; (t (error "Something's rotten"))))) @@ -1471,7 +1343,6 @@ (put 'isearch-repeat-backward 'isearch-command t) (put 'isearch-delete-char 'isearch-command t) (put 'isearch-help-or-delete-char 'isearch-command t) -(put 'isearch-cancel 'isearch-command t) (put 'isearch-abort 'isearch-command t) (put 'isearch-quote-char 'isearch-command t) (put 'isearch-exit 'isearch-command t) @@ -1500,8 +1371,6 @@ (put 'isearch-forward-exit-minibuffer 'isearch-command t) (put 'isearch-reverse-exit-minibuffer 'isearch-command t) (put 'isearch-nonincremental-exit-minibuffer 'isearch-command t) -(put 'isearch-yank-selection 'isearch-command t) -(put 'isearch-yank-clipboard 'isearch-command t) (put 'isearch-yank-x-selection 'isearch-command t) (put 'isearch-yank-x-clipboard 'isearch-command t) @@ -1539,24 +1408,11 @@ ;; (cond ((not (eq (current-buffer) isearch-buffer)) ;; If the buffer (likely meaning "frame") has changed, bail. - ;; This can happen if the user types something into another - ;; frame. It can also happen if a proc filter has popped up - ;; another buffer, which is arguably a bad thing for it to - ;; have done, but the way in which isearch would have hosed - ;; you in that case is unarguably even worse. -jwz - (isearch-done) - - ;; `this-command' is set according to the value of - ;; `overriding-local-map', set by isearch-mode. This is - ;; wrong because that keymap makes sense only in isearch - ;; buffer. To make sure the right command is called, adjust - ;; `this-command' to the appropriate value, now that - ;; `isearch-done' has set `overriding-local-map' to nil. - - ;; FSF does similar magic in `isearch-other-meta-char', which - ;; is horribly complex. I *hope* what we do works in all - ;; cases. - (setq this-command (key-binding (this-command-keys)))) + ;; This can also happen if a proc filter has popped up another + ;; buffer, which is arguably a bad thing for it to have done, + ;; but the way in which isearch would have hosed you in that + ;; case is unarguably even worse. -jwz + (isearch-done)) (t (isearch-maybe-frob-keyboard-macros) (if (and this-command @@ -1597,39 +1453,44 @@ ;;;======================================================== ;;; Highlighting +(defcustom isearch-highlight t + "*Whether isearch and query-replace should highlight the text which +currently matches the search-string.") + (defvar isearch-extent nil) -;; this face is initialized by faces.el since isearch is preloaded. -;(make-face 'isearch) +;; this face is initialized by x-faces.el since isearch is preloaded. +;; this face is now created in initialize-faces +;;(make-face 'isearch) (defun isearch-make-extent (begin end) (let ((x (make-extent begin end (current-buffer)))) - ;; make the isearch extent always take precedence over any mouse- + ;; make the isearch extent always take prescedence over any mouse- ;; highlighted extents we may be passing through, since isearch, being ;; modal, is more interesting (there's nothing they could do with a ;; mouse-highlighted extent while in the midst of a search anyway). - (set-extent-priority x (+ mouse-highlight-priority 2)) + (set-extent-priority x (1+ mouse-highlight-priority)) (set-extent-face x 'isearch) (setq isearch-extent x))) (defun isearch-highlight (begin end) - (if (null search-highlight) + (if (null isearch-highlight) nil ;; make sure isearch-extent is in the current buffer - (or (and (extentp isearch-extent) - (extent-live-p isearch-extent)) + (or (extentp isearch-extent) (isearch-make-extent begin end)) (set-extent-endpoints isearch-extent begin end (current-buffer)))) -;; This used to have a TOTALLY flag that also deleted the extent. I -;; don't think this is necessary any longer, as isearch-highlight can -;; simply move the extent to another buffer. The IGNORED argument is -;; for the code that calls this function with an argument. --hniksic -(defun isearch-dehighlight (&optional ignored) - (and search-highlight - (extentp isearch-extent) - (extent-live-p isearch-extent) - (detach-extent isearch-extent))) +(defun isearch-dehighlight (totally) + (if (and isearch-highlight isearch-extent) + (if totally + (let ((inhibit-quit t)) + (if (extentp isearch-extent) + (delete-extent isearch-extent)) + (setq isearch-extent nil)) + (if (extentp isearch-extent) + (detach-extent isearch-extent) + (setq isearch-extent nil))))) ;;;======================================================== @@ -1641,54 +1502,33 @@ (isearch-fix-case) (condition-case lossage (let ((inhibit-quit nil) - (case-fold-search isearch-case-fold-search) - (retry t)) + (case-fold-search isearch-case-fold-search)) (if isearch-regexp (setq isearch-invalid-regexp nil)) - (setq isearch-within-brackets nil) - (while retry - (setq isearch-success - (funcall - (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))) - isearch-string nil t)) - ;; Clear RETRY unless we matched some invisible text - ;; and we aren't supposed to do that. - (if (or (eq search-invisible t) - (not isearch-success) - (bobp) (eobp) - (= (match-beginning 0) (match-end 0)) - (not (isearch-range-invisible - (match-beginning 0) (match-end 0)))) - (setq retry nil))) + (setq isearch-success + (funcall + (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))) + isearch-string nil t)) (setq isearch-just-started nil) - (when isearch-success - (setq isearch-other-end - (if isearch-forward (match-beginning 0) (match-end 0))) - (and isearch-hide-immediately - (isearch-restore-invisible-extents (match-beginning 0) - (match-end 0))))) + (if isearch-success + (setq isearch-other-end + (if isearch-forward (match-beginning 0) (match-end 0))))) - (quit (setq unread-command-events (nconc unread-command-events - (character-to-event (quit-char)))) + (quit (setq unread-command-event (character-to-event (quit-char))) (setq isearch-success nil)) - (invalid-regexp + (invalid-regexp (setq isearch-invalid-regexp (car (cdr lossage))) - (setq isearch-within-brackets (string-match "\\`Unmatched \\[" - isearch-invalid-regexp)) (if (string-match "\\`Premature \\|\\`Unmatched \\|\\`Invalid " isearch-invalid-regexp) - (setq isearch-invalid-regexp (gettext "incomplete input")))) - (error - ;; stack overflow in regexp search. - (setq isearch-invalid-regexp (car (cdr lossage))))) + (setq isearch-invalid-regexp (gettext "incomplete input"))))) (if isearch-success nil @@ -1708,79 +1548,59 @@ (ding nil 'isearch-failed)) (goto-char (nth 2 (car isearch-cmds))))) -;; Replaced with isearch-edit-string. -;(defun nonincremental-search (forward regexp) -;... +;;;================================================= +;; This is called from incremental-search +;; if the first input character is the exit character. -(defun isearch-unhide-extent (extent) - ;; Store the values for the `invisible' and `intangible' - ;; properties, and then set them to nil. This way the text hidden - ;; by this extent becomes visible. - (put extent 'isearch-invisible (get extent 'invisible)) - (put extent 'isearch-intangible (get extent 'intangible)) - (put extent 'invisible nil) - (put extent 'intangible nil)) +;; We store the search string in `isearch-string' +;; which has been bound already by `isearch-search' +;; so that, when we exit, it is copied into `search-last-string'. -(defun isearch-range-invisible (beg end) - "Return t if all the text from BEG to END is invisible. -Before that, if search-invisible is `open', unhide the extents with an -`isearch-open-invisible' property." - ;; isearch-search uses this to skip the extents that are invisible, - ;; but don't have `isearch-open-invisible' set. It is unclear - ;; what's supposed to happen if only a part of [BEG, END) overlaps - ;; the extent. - (let (to-be-unhidden) - (if (map-extents - (lambda (extent ignored) - (if (and (<= (extent-start-position extent) beg) - (>= (extent-end-position extent) end)) - ;; All of the region is covered by the extent. - (if (and (eq search-invisible 'open) - (get extent 'isearch-open-invisible)) - (progn - (push extent to-be-unhidden) - nil) ; keep mapping - ;; We can't or won't unhide this extent, so we must - ;; skip the whole match. We return from map-extents - ;; immediately. - t) - ;; Else, keep looking. - nil)) - nil beg end nil 'all-extents-closed 'invisible) - ;; The whole match must be skipped. Signal it by returning t - ;; to the caller. - t - ;; If any extents need to be unhidden, unhide them. - (mapc #'isearch-unhide-extent to-be-unhidden) - ;; Will leave this assert for some time, to catch bugs. - (assert (null (intersection to-be-unhidden isearch-unhidden-extents))) - (setq isearch-unhidden-extents (nconc to-be-unhidden - isearch-unhidden-extents)) - nil))) - -(defun isearch-restore-extent (extent) - (put extent 'invisible (get extent 'isearch-invisible)) - (put extent 'intangible (get extent 'isearch-intangible)) - (remprop extent 'isearch-invisible) - (remprop extent 'isearch-intangible)) - -;; FSF calls this function `isearch-clean-overlays'. -(defun isearch-restore-invisible-extents (beg end) - (cond - ((null beg) - ;; Delete all -- this is called at the end of isearch. - (mapc #'isearch-restore-extent isearch-unhidden-extents) - (setq isearch-unhidden-extents nil)) - (t - ;; Extents that do not overlap the match area can be safely - ;; restored to their hidden state. - (setq isearch-unhidden-extents - (delete-if (lambda (extent) - (unless (extent-in-region-p extent beg end - 'all-extents-closed) - (isearch-restore-extent extent) - t)) - isearch-unhidden-extents))))) +;(defun nonincremental-search (forward regexp) +; ;; This may be broken. Anyway, it is replaced by the isearch-edit-string. +; ;; Missing features: word search option, command history. +; (setq isearch-forward forward +; isearch-regexp regexp) +; (let (char function +; inhibit-quit +; (cursor-in-echo-area t)) +; ;; Prompt assuming not word search, +; (setq isearch-message +; (if isearch-regexp +; (if isearch-forward "Regexp search: " +; "Regexp search backward: ") +; (if isearch-forward "Search: " "Search backward: "))) +; (message "%s" isearch-message) +; ;; Read 1 char and switch to word search if it is ^W. +; (setq char (read-char)) +; (if (eq char search-yank-word-char) +; (setq isearch-message (if isearch-forward "Word search: " +; "Word search backward: ")) +; ;; Otherwise let that 1 char be part of the search string. +; (setq unread-command-event (character-to-event char)) +; ) +; (setq function +; (if (eq char search-yank-word-char) +; (if isearch-forward 'word-search-forward 'word-search-backward) +; (if isearch-regexp +; (if isearch-forward 're-search-forward 're-search-backward) +; (if isearch-forward 'search-forward 'search-backward)))) +; ;; Read the search string with corrected prompt. +; (setq isearch-string (read-string isearch-message isearch-string)) +; ;; Empty means use default. +; (if (= 0 (length isearch-string)) +; (setq isearch-string search-last-string) +; ;; Set last search string now so it is set even if we fail. +; (setq search-last-string isearch-string)) +; ;; Since we used the minibuffer, we should be available for redo. +; (setq command-history +; (cons (list function isearch-string) command-history)) +; ;; Go ahead and search. +; (if search-caps-disable-folding +; (setq isearch-case-fold-search +; (no-upper-case-p isearch-string isearch-regexp))) +; (let ((case-fold-search isearch-case-fold-search)) +; (funcall function isearch-string)))) (defun isearch-no-upper-case-p (string) "Return t if there are no upper case chars in string. @@ -1791,18 +1611,6 @@ (not (string-match "\\(^\\|[^\\]\\)[A-Z]" string)))) (make-obsolete 'isearch-no-upper-case-p 'no-upper-case-p) -;; Portability functions to support various Emacs versions. - -(defun isearch-char-to-string (c) - (if (eventp c) - (make-string 1 (event-to-character c nil nil t)) - (make-string 1 c))) - -;(defun isearch-text-char-description (c) -; (isearch-char-to-string c)) - -(define-function 'isearch-text-char-description 'text-char-description) - ;; Used by etags.el and info.el (defmacro with-caps-disable-folding (string &rest body) "\ Eval BODY with `case-fold-search' let to nil if STRING contains @@ -1816,203 +1624,4 @@ (put 'with-caps-disable-folding 'lisp-indent-function 1) (put 'with-caps-disable-folding 'edebug-form-spec '(form body)) - -;;;======================================================== -;;; Advanced highlighting - -;; When active, *every* visible match for the current search string is -;; highlighted: the current one using the normal isearch match color -;; and all the others using the `isearch-secondary' face. The extra -;; highlighting makes it easier to anticipate where the cursor will -;; land each time you press C-s or C-r to repeat a pending search. -;; Only the matches visible at any point are highlighted -- when you -;; move through the buffer, the highlighting is readjusted. - -;; This is based on ideas from Bob Glickstein's `ishl' package. It -;; has been merged with XEmacs by Darryl Okahata, and then completely -;; rewritten by Hrvoje Niksic. - -;; The code makes the following assumptions about the rest of this -;; file, so be careful when modifying it. - -;; * `isearch-highlight-all-update' should get called when the search -;; string changes, or when the search advances. This is done from -;; `isearch-update'. -;; * `isearch-highlight-all-cleanup' should get called when the search -;; is done. This is performed in `isearch-done'. -;; * `isearch-string' is expected to contain the current search string -;; as entered by the user. -;; * `isearch-opoint' is expected to contain the location where the -;; current search began. -;; * the type of the current search is expected to be given by -;; `isearch-word' and `isearch-regexp'. -;; * the variable `isearch-invalid-regexp' is expected to be true iff -;; `isearch-string' is an invalid regexp. - -(defcustom isearch-highlight-all-matches search-highlight - "*Non-nil means highlight all visible matches." - :type 'boolean - :group 'isearch) - -;; We can't create this face here, as isearch.el is preloaded. -;; #### Think up a better name for this! -;(defface isearch-secondary '((t (:foreground "red3"))) -; "Face to use for highlighting all matches." -; :group 'isearch) - -(defvar isearch-highlight-extents nil) -(defvar isearch-window-start nil) -(defvar isearch-window-end nil) -;; We compare isearch-string and isearch-case-fold-search to saved -;; values for better efficiency. -(defvar isearch-highlight-last-string nil) -(defvar isearch-highlight-last-case-fold-search nil) -(defvar isearch-highlight-last-regexp nil) - -(defun isearch-delete-extents-in-range (start end) - ;; Delete all highlighting extents that overlap [START, END). - (setq isearch-highlight-extents - (delete-if (lambda (extent) - (when (extent-in-region-p extent start end) - (delete-extent extent) - t)) - isearch-highlight-extents))) - -(defun isearch-highlight-all-cleanup () - ;; Stop lazily highlighting and remove extra highlighting from - ;; buffer. - (mapc #'delete-extent isearch-highlight-extents) - (setq isearch-highlight-extents nil) - (setq isearch-window-end nil - isearch-highlight-last-string nil)) - -(defun isearch-highlight-all-update () - ;; Update the highlighting if necessary. This needs to check if the - ;; search string has changed, or if the window has changed position - ;; in the buffer. - (let ((need-start-over nil)) - ;; NB: we don't check for isearch-success because if the point is - ;; after the last match, the search can be unsuccessful, and yet - ;; there are things to highlight. - (cond ((not isearch-highlight-all-matches)) - ((or (equal isearch-string "") - isearch-invalid-regexp) - (isearch-highlight-all-cleanup)) - ((not (eq isearch-case-fold-search - isearch-highlight-last-case-fold-search)) - ;; This case is usually caused by search string being - ;; changed, which would be caught below, but it can also be - ;; tripped using isearch-toggle-case-fold. - (setq need-start-over t)) - ((not (eq isearch-regexp isearch-highlight-last-regexp)) - ;; Ditto for isearch-toggle-regexp. - (setq need-start-over t)) - ((equal isearch-string isearch-highlight-last-string) - ;; The search string is the same. We need to do something - ;; if our position has changed. - - ;; It would be nice if we didn't have to do this; however, - ;; window-start doesn't support a GUARANTEE flag, so we must - ;; force redisplay to get the correct value for start and end - ;; of window. - (sit-for 0) - - ;; Check whether our location has changed. - (let ((start (window-start)) - (end (min (window-end) (point-max)))) - (cond ((and (= start isearch-window-start) - (= end isearch-window-end)) - ;; Our position is unchanged -- do nothing. - ) - ((and (> start isearch-window-start) - (> end isearch-window-end) - (<= start isearch-window-end)) - ;; We've migrated downward, but we overlap the old - ;; region. Delete the old non-overlapping extents - ;; and fill in the rest. - (isearch-delete-extents-in-range isearch-window-start start) - (isearch-highlightify-region isearch-window-end end) - (setq isearch-window-start start - isearch-window-end end)) - ((and (<= start isearch-window-start) - (<= end isearch-window-end) - (> end isearch-window-start)) - ;; We've migrated upward, but we overlap the old - ;; region. Delete the old non-overlapping extents - ;; and fill in the rest. - (isearch-delete-extents-in-range - end isearch-window-end) - (isearch-highlightify-region start isearch-window-start) - (setq isearch-window-start start - isearch-window-end end)) - (t - ;; The regions don't overlap, or they overlap in a - ;; weird way. - (setq need-start-over t))))) - (t - ;; The search string has changed. - - ;; If more input is pending, don't start over because - ;; starting over forces redisplay, and that slows down - ;; typing. - (unless (input-pending-p) - (setq need-start-over t)))) - (when need-start-over - ;; Force redisplay before removing the old extents, in order to - ;; avoid flicker. - (sit-for 0) - (isearch-highlight-all-cleanup) - (setq isearch-window-start (window-start) - isearch-window-end (min (window-end) (point-max))) - (isearch-highlightify-region isearch-window-start isearch-window-end)) - - (setq isearch-highlight-last-string isearch-string - isearch-highlight-last-case-fold-search isearch-case-fold-search - isearch-highlight-last-regexp isearch-regexp))) - -(defun isearch-highlight-advance (string forwardp) - ;; Search ahead for the next or previous match. This is the same as - ;; isearch-search, but without the extra baggage. Maybe it should - ;; be in a separate function. - (let ((case-fold-search isearch-case-fold-search)) - (funcall (cond (isearch-word (if forwardp - 'word-search-forward - 'word-search-backward)) - (isearch-regexp (if forwardp - 're-search-forward - 're-search-backward)) - (t (if forwardp - 'search-forward - 'search-backward))) - string nil t))) - -(defun isearch-highlightify-region (start end) - ;; Highlight all occurrences of isearch-string between START and - ;; END. To do this right, we have to search forward as long as - ;; there are matches that overlap [START, END), and then search - ;; backward the same way. - (save-excursion - (goto-char isearch-opoint) - (let ((lastpoint (point))) - (while (and (isearch-highlight-advance isearch-string t) - (/= lastpoint (point)) - (< (match-beginning 0) end)) - (let ((extent (make-extent (match-beginning 0) - (match-end 0)))) - (set-extent-priority extent (1+ mouse-highlight-priority)) - (put extent 'face 'isearch-secondary) - (push extent isearch-highlight-extents)) - (setq lastpoint (point)))) - (goto-char isearch-opoint) - (let ((lastpoint (point))) - (while (and (isearch-highlight-advance isearch-string nil) - (/= lastpoint (point)) - (>= (match-end 0) start)) - (let ((extent (make-extent (match-beginning 0) - (match-end 0)))) - (set-extent-priority extent (1+ mouse-highlight-priority)) - (put extent 'face 'isearch-secondary) - (push extent isearch-highlight-extents)) - (setq lastpoint (point)))))) - ;;; isearch-mode.el ends here