comparison lisp/isearch-mode.el @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents bbff43aa5eb7
children de805c49cfc1
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
1 ;;; isearch-mode.el --- Incremental search minor mode. 1 ;;; isearch-mode.el --- Incremental search minor mode.
2 2
3 ;; Copyright (C) 1992, 1993, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
4 4
5 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu> 5 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
6 ;; Maintainer: XEmacs Development Team 6 ;; Maintainer: XEmacs Development Team
7 ;; Keywords: extensions, dumped 7 ;; Keywords: extensions, dumped
8 8
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details. 19 ;; General Public License for more details.
20 20
21 ;; You should have received a copy of the GNU General Public License 21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the 22 ;; along with XEmacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, 59 Temple Place - Suite 330, 23 ;; Free Software Foundation, 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA. 24 ;; Boston, MA 02111-1307, USA.
25 25
26 ;;; Synched up with: Not synched with FSF. 26 ;;; Synched up with: FSF 20.4.
27 27
28 ;;; Commentary: 28 ;;; Commentary:
29 29
30 ;; LCD Archive Entry:
31 ;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu
32 ;; |A minor mode replacement for isearch.el.
33
34 ;;====================================================================
35 ;; Instructions 30 ;; Instructions
36 31
37 ;; Searching with isearch-mode.el should work just like isearch.el, 32 ;; Searching with isearch-mode.el should work just like isearch.el
38 ;; except it is done in a temporary minor mode that terminates when 33 ;; [the one from Emacs 18], except it is done in a temporary minor
39 ;; you finish searching. 34 ;; mode that terminates when you finish searching.
40 35
41 ;; Semi-modal searching is supported, using a recursive edit. If 36 ;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
42 ;; isearching is started non-interactively by calling one of the 37 ;; isearch-mode behaves modally and does not return until the search
43 ;; isearch commands (e.g. (isearch-forward), but not like gnus does 38 ;; is completed. It uses a recursive-edit to behave this way. In
44 ;; it: (call-interactively 'isearch-forward)), isearch-mode does not 39 ;; that case, you should still be able switch buffers, so be careful
45 ;; return until the search is completed. You should still be able 40 ;; not to get things confused.
46 ;; switch buffers, so be careful not to get things confused.
47 41
48 ;; The key bindings active within isearch-mode are defined below in 42 ;; The key bindings active within isearch-mode are defined below in
49 ;; `isearch-mode-map' which is given bindings close to the default 43 ;; `isearch-mode-map' which is given bindings close to the default
50 ;; characters of isearch.el for version 19. With `isearch-mode', 44 ;; characters of the original isearch.el. With `isearch-mode',
51 ;; however, you can bind multi-character keys and it should be easier 45 ;; however, you can bind multi-character keys and it should be easier
52 ;; to add new commands. One bug though: keys with meta-prefix cannot 46 ;; to add new commands. One bug though: keys with meta-prefix cannot
53 ;; be longer than two chars. Also see minibuffer-local-isearch-map 47 ;; be longer than two chars. Also see minibuffer-local-isearch-map
54 ;; for bindings active during `isearch-edit-string'. 48 ;; for bindings active during `isearch-edit-string'.
55 49
61 ;; exits and does a nonincremental search. 55 ;; exits and does a nonincremental search.
62 56
63 ;; Exiting immediately from isearch uses isearch-edit-string instead 57 ;; Exiting immediately from isearch uses isearch-edit-string instead
64 ;; of nonincremental-search, if search-nonincremental-instead is non-nil. 58 ;; of nonincremental-search, if search-nonincremental-instead is non-nil.
65 ;; The name of this option should probably be changed if we decide to 59 ;; The name of this option should probably be changed if we decide to
66 ;; keep the behavior. One difference is that isearch-edit-string does 60 ;; keep the behavior. No point in forcing nonincremental search until
67 ;; not support word search yet; perhaps isearch-mode should support it 61 ;; the last possible moment.
68 ;; even for incremental searches, but how? 62
69 63 ;; TODO
70 ;;==================================================================== 64 ;; - Integrate generalized command history to isearch-edit-string.
71 ;;; Change History: 65 ;; - Think about incorporating query-replace.
72 66 ;; - Hooks and options for failed search.
73 ;; Header: /import/kaplan/kaplan/liberte/Isearch/RCS/isearch-mode.el,v 1.3 92/06/29 13:10:08 liberte Exp Locker: liberte 67
74 ;; Log: isearch-mode.el,v 68 ;;; Change Log:
75 ;; 69
70 ;; Changes before those recorded in ChangeLog:
71
76 ;; 20-aug-92 Hacked by jwz for Lucid Emacs 19.3. 72 ;; 20-aug-92 Hacked by jwz for Lucid Emacs 19.3.
77 ;; 73 ;;
78 ;; Revision 1.3 92/06/29 13:10:08 liberte 74 ;; Revision 1.3 92/06/29 13:10:08 liberte
79 ;; Moved modal isearch-mode handling into isearch-mode. 75 ;; Moved modal isearch-mode handling into isearch-mode.
80 ;; Got rid of buffer-local isearch variables. 76 ;; Got rid of buffer-local isearch variables.
81 ;; isearch-edit-string used by ring adjustments, completion, and 77 ;; isearch-edit-string used by ring adjustments, completion, and
82 ;; nonincremental searching. C-s and C-r are additional exit commands. 78 ;; nonincremental searching. C-s and C-r are additional exit commands.
83 ;; Renamed all regex to regexp. 79 ;; Renamed all regex to regexp.
84 ;; Got rid of found-start and found-point globals. 80 ;; Got rid of found-start and found-point globals.
85 ;; Generalized handling of upper-case chars. 81 ;; Generalized handling of upper-case chars.
86 82
87 ;; Revision 1.2 92/05/27 11:33:57 liberte 83 ;; Revision 1.2 92/05/27 11:33:57 liberte
88 ;; Emacs version 19 has a search ring, which is supported here. 84 ;; Emacs version 19 has a search ring, which is supported here.
89 ;; Other fixes found in the version 19 isearch are included here. 85 ;; Other fixes found in the version 19 isearch are included here.
90 ;; 86 ;;
91 ;; Also see variables search-caps-disable-folding, 87 ;; Also see variables search-caps-disable-folding,
98 ;; 3/18/92 Fixed invalid-regexp. 94 ;; 3/18/92 Fixed invalid-regexp.
99 ;; 3/18/92 Fixed yanking in regexps. 95 ;; 3/18/92 Fixed yanking in regexps.
100 96
101 ;;; Code: 97 ;;; Code:
102 98
103 (defgroup isearch nil
104 "Incremental search"
105 :prefix "search-"
106 :group 'matching)
107
108
109 (defun isearch-char-to-string (c)
110 (if (eventp c)
111 (make-string 1 (event-to-character c nil nil t))
112 (make-string 1 c)))
113
114 ;(defun isearch-text-char-description (c)
115 ; (isearch-char-to-string c))
116
117 (define-function 'isearch-text-char-description 'text-char-description)
118
119 99
120 ;;;========================================================================= 100 ;;;=========================================================================
121 ;;; User-accessible variables 101 ;;; User-accessible variables
122 102
123 (defvar search-last-string "" 103 (defgroup isearch nil
124 "Last string search for by a search command. 104 "Incremental search minor mode."
125 This does not include direct calls to the primitive search functions, 105 :prefix "search-"
126 and does not include searches that are aborted.") 106 :group 'matching)
127 107
128 (defvar search-last-regexp "" 108
129 "Last string searched for by a regexp search command. 109 (defcustom search-exit-option t
130 This does not include direct calls to the primitive search functions, 110 "*Non-nil means random control characters terminate incremental search."
131 and does not include searches that are aborted.") 111 :type 'boolean
132 112 :group 'isearch)
133 (defconst search-exit-option t
134 "Non-nil means random control characters terminate incremental search.")
135 113
136 (defcustom search-slow-window-lines 1 114 (defcustom search-slow-window-lines 1
137 "*Number of lines in slow search display windows. 115 "*Number of lines in slow search display windows.
138 These are the short windows used during incremental search on slow terminals. 116 These are the short windows used during incremental search on slow terminals.
139 Negative means put the slow search window at the top (normally it's at bottom) 117 Negative means put the slow search window at the top (normally it's at bottom)
146 This is the style where a one-line window is created to show the line 124 This is the style where a one-line window is created to show the line
147 that the search has reached." 125 that the search has reached."
148 :type 'integer 126 :type 'integer
149 :group 'isearch) 127 :group 'isearch)
150 128
129 ;; We have `search-caps-disable-folding'.
130 ;(defcustom search-upper-case 'not-yanks
131 ; "*If non-nil, upper case chars disable case fold searching.
132 ;That is, upper and lower case chars must match exactly.
133 ;This applies no matter where the chars come from, but does not
134 ;apply to chars in regexps that are prefixed with `\\'.
135 ;If this value is `not-yanks', yanked text is always downcased."
136 ; :type '(choice (const :tag "off" nil)
137 ; (const not-yanks)
138 ; (other :tag "on" t))
139 ; :group 'isearch)
140
151 (defcustom search-nonincremental-instead t 141 (defcustom search-nonincremental-instead t
152 "*If non-nil, do a nonincremental search instead if exiting immediately." 142 "*If non-nil, do a nonincremental search instead if exiting immediately.
143 Actually, `isearch-edit-string' is called to let you enter the search
144 string, and RET terminates editing and does a nonincremental search."
153 :type 'boolean 145 :type 'boolean
154 :group 'isearch) 146 :group 'isearch)
155 147
156 (defcustom search-whitespace-regexp "\\(\\s \\|[\n\r]\\)+" 148 ;; FSF default is "\\s-+", but I think our default is better so I'm
149 ;; leaving it.
150 (defcustom search-whitespace-regexp "\\(\\s-\\|[\n\r]\\)+"
157 "*If non-nil, regular expression to match a sequence of whitespace chars." 151 "*If non-nil, regular expression to match a sequence of whitespace chars."
158 :type 'regexp 152 :type 'regexp
159 :group 'isearch) 153 :group 'isearch)
154
155 (defcustom search-highlight t
156 "*Whether incremental search and query-replace should highlight
157 the text that currently matches the search string."
158 :type 'boolean
159 :group 'isearch)
160
161 ;; I think the name `search-highlight' makes more sense, both because
162 ;; of consistency with other search-* variables above, and because it
163 ;; also applies to query-replace.
164 (define-obsolete-variable-alias 'isearch-highlight 'search-highlight)
165
166 (defcustom search-invisible 'open
167 "If t incremental search can match hidden text.
168 nil means don't match invisible text.
169 If the value is `open', if the text matched is made invisible by
170 an overlay having an `invisible' property and that overlay has a property
171 `isearch-open-invisible', then incremental search will show the contents.
172 \(This applies when using `outline.el' and `hideshow.el'.)"
173 :type '(choice (const :tag "Match hidden text" t)
174 (const :tag "Open overlays" open)
175 (const :tag "Don't match hidden text" nil))
176 :group 'isearch)
177
178 (defcustom isearch-hide-immediately t
179 "If non-nil, re-hide an invisible match right away.
180 This variable makes a difference when `search-invisible' is set to `open'.
181 It means that after search makes some invisible text visible
182 to show the match, it makes the text invisible again when the match moves.
183 Ordinarily the text becomes invisible again at the end of the search."
184 :type 'boolean
185 :group 'isearch)
186
187 (defvar isearch-mode-hook nil
188 "Function(s) to call after starting up an incremental search.")
189
190 (defvar isearch-mode-end-hook nil
191 "Function(s) to call after terminating an incremental search.")
160 192
161 ;;;================================================================== 193 ;;;==================================================================
162 ;;; Search ring. 194 ;;; Search ring.
163 195
164 (defvar search-ring nil 196 (defvar search-ring nil
173 (defcustom regexp-search-ring-max 16 205 (defcustom regexp-search-ring-max 16
174 "*Maximum length of regexp search ring before oldest elements are thrown away." 206 "*Maximum length of regexp search ring before oldest elements are thrown away."
175 :type 'integer 207 :type 'integer
176 :group 'isearch) 208 :group 'isearch)
177 209
210 ;; The important difference between pre-20.4-merge yank-pointers and
211 ;; current code is that the yank pointers positions used to be
212 ;; preserved across the isearch sessions. I changed this because I
213 ;; think the FSF code is closer to how the feature is supposed to
214 ;; behave (read: to minibuffer histories.)
178 (defvar search-ring-yank-pointer nil 215 (defvar search-ring-yank-pointer nil
179 "The tail of the search ring whose car is the last thing searched for.") 216 "Index in `search-ring' of last string reused.
217 nil if none yet.")
180 (defvar regexp-search-ring-yank-pointer nil 218 (defvar regexp-search-ring-yank-pointer nil
181 "The tail of the regular expression search ring whose car is the last 219 "Index in `regexp-search-ring' of last string reused.
182 thing searched for.") 220 nil if none yet.")
221
222 (defcustom search-ring-update nil
223 "*Non-nil if advancing or retreating in the search ring should cause search.
224 Default nil means edit the string from the search ring first."
225 :type 'boolean
226 :group 'isearch)
183 227
184 ;;;==================================================== 228 ;;;====================================================
185 ;;; Define isearch-mode keymap. 229 ;;; Define isearch-mode keymap.
186 230
187 (defvar isearch-mode-map 231 (defvar isearch-mode-map
188 (let ((map (make-keymap))) 232 (let ((map (make-keymap)))
189 (set-keymap-name map 'isearch-mode-map) 233 (set-keymap-name map 'isearch-mode-map)
190 234
191 ;; Bind all printing characters to `isearch-printing-char'. 235 ;; Bind all printing characters to `isearch-printing-char'.
192 ;; This isn't normally necessary, but if a printing character were 236 ;; This isn't normally necessary, but if a printing character were
193 ;; bound to something other than self-insert-command in global-map, 237 ;; bound to something other than self-insert-command in global-map,
194 ;; then it would terminate the search and be executed without this. 238 ;; then it would terminate the search and be executed without this.
195 (let ((i 32) 239 (let ((i 32)
196 (str (make-string 1 0))) 240 (str (make-string 1 0)))
197 (while (< i 127) 241 (while (< i 127)
198 (aset str 0 i) 242 (aset str 0 i)
199 (define-key map str 'isearch-printing-char) 243 (define-key map str 'isearch-printing-char)
200 (setq i (1+ i)))) 244 (setq i (1+ i))))
201 (define-key map "\t" 'isearch-printing-char) 245
246 ;; Here FSF sets up various kludges to handle local bindings with
247 ;; meta char prefix keys. We don't need isearch-other-meta-char
248 ;; because we handle things differently (via pre-command-hook).
202 249
203 ;; Several non-printing chars change the searching behavior. 250 ;; Several non-printing chars change the searching behavior.
204 ;; 251 ;;
205 (define-key map "\C-s" 'isearch-repeat-forward) 252 (define-key map "\C-s" 'isearch-repeat-forward)
206 (define-key map "\M-\C-s" 'isearch-repeat-forward) 253 (define-key map "\M-\C-s" 'isearch-repeat-forward)
207 (define-key map "\C-r" 'isearch-repeat-backward) 254 (define-key map "\C-r" 'isearch-repeat-backward)
208 (define-key map "\C-g" 'isearch-abort) 255 (define-key map "\C-g" 'isearch-abort)
209 256
257 ;; I wish this worked...
258 ;(define-key map [escape escape escape] 'isearch-cancel)
259 (define-key map [(meta escape) escape] 'isearch-cancel)
260
210 (define-key map "\C-q" 'isearch-quote-char) 261 (define-key map "\C-q" 'isearch-quote-char)
211 262
212 (define-key map "\C-m" 'isearch-exit) 263 (define-key map "\C-m" 'isearch-exit)
213 (define-key map "\C-j" 'isearch-printing-char) 264 (define-key map "\C-j" 'isearch-printing-char)
214 (define-key map "\t" 'isearch-printing-char) 265 (define-key map "\t" 'isearch-printing-char)
266 ;; I prefer our default.
267 ;(define-key map " " 'isearch-whitespace-chars)
268 (define-key map "\M- " 'isearch-whitespace-chars)
215 269
216 (define-key map "\C-w" 'isearch-yank-word) 270 (define-key map "\C-w" 'isearch-yank-word)
217 (define-key map "\C-y" 'isearch-yank-line) 271 (define-key map "\C-y" 'isearch-yank-line)
218 (define-key map "\M-y" 'isearch-yank-kill) 272 (define-key map "\M-y" 'isearch-yank-kill)
219 273
220 ;; Define keys for regexp chars * ? | 274 ;; Define keys for regexp chars * ? |.
275 ;; Nothing special for + because it matches at least once.
221 (define-key map "*" 'isearch-*-char) 276 (define-key map "*" 'isearch-*-char)
222 (define-key map "?" 'isearch-*-char) 277 (define-key map "?" 'isearch-*-char)
223 (define-key map "|" 'isearch-|-char) 278 (define-key map "|" 'isearch-|-char)
224
225 ;; Some bindings you may want to put in your isearch-mode-hook.
226 ;; Suggest some alternates...
227 ;; (define-key map "\C-t" 'isearch-toggle-regexp)
228 ;; (define-key map "\C-^" 'isearch-edit-string)
229 279
230 ;; delete and backspace delete backward, f1 is help, and C-h can be either 280 ;; delete and backspace delete backward, f1 is help, and C-h can be either
231 (define-key map 'delete 'isearch-delete-char) 281 (define-key map 'delete 'isearch-delete-char)
232 (define-key map 'backspace 'isearch-delete-char) 282 (define-key map 'backspace 'isearch-delete-char)
233 (define-key map '(control h) 'isearch-help-or-delete-char) 283 (define-key map '(control h) 'isearch-help-or-delete-char)
234 (define-key map 'f1 'isearch-mode-help) 284 (define-key map 'f1 'isearch-mode-help)
235 (define-key map 'help 'isearch-mode-help) 285 (define-key map 'help 'isearch-mode-help)
236 286
237 (define-key map "\M-n" 'isearch-ring-advance) 287 (define-key map "\M-n" 'isearch-ring-advance)
238 (define-key map "\M-p" 'isearch-ring-retreat) 288 (define-key map "\M-p" 'isearch-ring-retreat)
239 (define-key map "\M- " 'isearch-whitespace-chars)
240 (define-key map "\M-\t" 'isearch-complete) 289 (define-key map "\M-\t" 'isearch-complete)
241 290
242 (define-key map 'button2 'isearch-yank-x-selection) 291 ;; I find this binding somewhat unintuitive, because it doesn't
292 ;; work if the mouse pointer is over the echo area -- it has to be
293 ;; over the search window.
294 (define-key map 'button2 'isearch-yank-selection)
243 295
244 map) 296 map)
245 "Keymap for isearch-mode.") 297 "Keymap for isearch-mode.")
246 298
247 (defvar minibuffer-local-isearch-map 299 ;; Some bindings you may want to put in your isearch-mode-hook.
300 ;; Suggest some alternates...
301 ;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-case-fold)
302 ;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
303 ;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
304
305 (defvar minibuffer-local-isearch-map
248 (let ((map (make-sparse-keymap))) 306 (let ((map (make-sparse-keymap)))
249 ;; #### - this should also be minor-mode-ified 307 ;; #### - this should also be minor-mode-ified
250 (set-keymap-parents map (list minibuffer-local-map)) 308 (set-keymap-parents map (list minibuffer-local-map))
251 (set-keymap-name map 'minibuffer-local-isearch-map) 309 (set-keymap-name map 'minibuffer-local-isearch-map)
252 310
253 ;;#### This should just arrange to use the usual Emacs minibuffer histories 311 ;;#### This should just arrange to use the usual Emacs minibuffer histories
254 (define-key map "\r" 'isearch-nonincremental-exit-minibuffer) 312 (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
255 (define-key map "\M-n" 'isearch-ring-advance-edit) 313 (define-key map "\M-n" 'isearch-ring-advance-edit)
256 (define-key map "\M-p" 'isearch-ring-retreat-edit) 314 (define-key map "\M-p" 'isearch-ring-retreat-edit)
315 (define-key map 'down 'isearch-ring-advance-edit)
316 (define-key map 'up 'isearch-ring-retreat-edit)
257 (define-key map "\M-\t" 'isearch-complete-edit) 317 (define-key map "\M-\t" 'isearch-complete-edit)
258 (define-key map "\C-s" 'isearch-forward-exit-minibuffer) 318 (define-key map "\C-s" 'isearch-forward-exit-minibuffer)
259 (define-key map "\C-r" 'isearch-reverse-exit-minibuffer) 319 (define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
260 map) 320 map)
261 "Keymap for editing isearch strings in the minibuffer.") 321 "Keymap for editing isearch strings in the minibuffer.")
262 322
263 ;;;======================================================== 323 ;;;========================================================
264 ;; Internal variables declared globally for byte-compiler. 324 ;; Internal variables declared globally for byte-compiler.
265 ;; These are all bound locally while editing the search string. 325 ;; These are all set with setq while isearching
326 ;; and bound locally while editing the search string.
266 327
267 (defvar isearch-forward nil) ; Searching in the forward direction. 328 (defvar isearch-forward nil) ; Searching in the forward direction.
268 (defvar isearch-regexp nil) ; Searching for a regexp. 329 (defvar isearch-regexp nil) ; Searching for a regexp.
269 (defvar isearch-word nil) ; Searching for words. 330 (defvar isearch-word nil) ; Searching for words.
270 331
272 (defvar isearch-string "") ; The current search string. 333 (defvar isearch-string "") ; The current search string.
273 (defvar isearch-message "") ; text-char-description version of isearch-string 334 (defvar isearch-message "") ; text-char-description version of isearch-string
274 335
275 (defvar isearch-success t) ; Searching is currently successful. 336 (defvar isearch-success t) ; Searching is currently successful.
276 (defvar isearch-invalid-regexp nil) ; Regexp not well formed. 337 (defvar isearch-invalid-regexp nil) ; Regexp not well formed.
338 (defvar isearch-within-brackets nil) ; Regexp has unclosed [.
277 (defvar isearch-other-end nil) ; Start (end) of match if forward (backward). 339 (defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
278 (defvar isearch-wrapped nil) ; Searching restarted from the top (bottom). 340 (defvar isearch-wrapped nil) ; Searching restarted from the top (bottom).
279 (defvar isearch-barrier 0) 341 (defvar isearch-barrier 0)
280 (defvar isearch-just-started nil) 342 (defvar isearch-just-started nil)
281 (defvar isearch-buffer nil) ; the buffer we've frobbed the keymap of 343 (defvar isearch-buffer nil) ; the buffer we've frobbed the keymap of
282 344
283 (defvar isearch-case-fold-search nil) 345 (defvar isearch-case-fold-search nil)
346
347 ;; Need this for toggling case in isearch-toggle-case-fold. When this
348 ;; is non-nil, the case-sensitiveness of the search is set by the
349 ;; user, and is may no longer be dynamically changed as per
350 ;; search-caps-disable-folding.
351 (defvar isearch-fixed-case nil)
284 352
285 (defvar isearch-adjusted nil) 353 (defvar isearch-adjusted nil)
286 (defvar isearch-slow-terminal-mode nil) 354 (defvar isearch-slow-terminal-mode nil)
287 ;;; If t, using a small window. 355 ;;; If t, using a small window.
288 (defvar isearch-small-window nil) 356 (defvar isearch-small-window nil)
306 (defvar isearch-nonincremental nil) 374 (defvar isearch-nonincremental nil)
307 375
308 ;; New value of isearch-forward after isearch-edit-string. 376 ;; New value of isearch-forward after isearch-edit-string.
309 (defvar isearch-new-forward nil) 377 (defvar isearch-new-forward nil)
310 378
311 379 ;; Accumulate here the extents unhidden during searching.
312 (defvar isearch-mode-hook nil 380 (defvar isearch-unhidden-extents nil) ; in FSF: isearch-opened-overlays
313 "Function(s) to call after starting up an incremental search.") 381
314
315 (defvar isearch-mode-end-hook nil
316 "Function(s) to call after terminating an incremental search.")
317 382
318 ;;;============================================================== 383 ;;;==============================================================
319 ;; Minor-mode-alist changes - kind of redundant with the 384 ;; Minor-mode-alist changes - kind of redundant with the
320 ;; echo area, but if isearching in multiple windows, it can be useful. 385 ;; echo area, but if isearching in multiple windows, it can be useful.
321 386
322 (add-minor-mode 'isearch-mode 'isearch-mode) 387 (add-minor-mode 'isearch-mode 'isearch-mode)
323 388
324 (defvar isearch-mode nil) 389 (defvar isearch-mode nil) ;; Name of the minor mode, if non-nil.
325 (make-variable-buffer-local 'isearch-mode) 390 (make-variable-buffer-local 'isearch-mode)
391
392 ;; We bind these in keydefs.el.
393 ;(define-key global-map "\C-s" 'isearch-forward)
394 ;(define-key global-map "\C-r" 'isearch-backward)
395 ;(define-key global-map "\M-\C-s" 'isearch-forward-regexp)
396 ;(define-key global-map "\M-\C-r" 'isearch-backward-regexp)
326 397
327 ;;;=============================================================== 398 ;;;===============================================================
328 ;;; Entry points to isearch-mode. 399 ;;; Entry points to isearch-mode.
329 ;;; These four functions should replace those in loaddefs.el 400 ;;; These four functions should replace those in loaddefs.el
330 ;;; An alternative is to fset isearch-forward etc to isearch-mode, 401 ;;; An alternative is to defalias isearch-forward etc to isearch-mode,
331 ;;; and look at the last command to set the options accordingly. 402 ;;; and look at this-command to set the options accordingly.
332 403
333 (defun isearch-forward (&optional regexp-p) 404 (defun isearch-forward (&optional regexp-p no-recursive-edit)
334 "Do incremental search forward. 405 "\
406 Do incremental search forward.
335 With a prefix argument, do an incremental regular expression search instead. 407 With a prefix argument, do an incremental regular expression search instead.
336 \\<isearch-mode-map> 408 \\<isearch-mode-map>
337 As you type characters, they add to the search string and are found. 409 As you type characters, they add to the search string and are found.
338 The following non-printing keys are bound in `isearch-mode-map'. 410 The following non-printing keys are bound in `isearch-mode-map'.
339 411
340 Type \\[isearch-delete-char] to cancel characters from end of search string. 412 Type \\[isearch-delete-char] to cancel characters from end of search string.
341 Type \\[isearch-exit] to exit, leaving point at location found. 413 Type \\[isearch-exit] to exit, leaving point at location found.
342 Type LFD (C-j) to match end of line. 414 Type LFD (C-j) to match end of line.
343 Type \\[isearch-repeat-forward] to search again forward,\ 415 Type \\[isearch-repeat-forward] to search again forward,\
344 \\[isearch-repeat-backward] to search again backward. 416 \\[isearch-repeat-backward] to search again backward.
345 Type \\[isearch-yank-word] to yank word from buffer onto end of search\ 417 Type \\[isearch-yank-word] to yank word from buffer onto end of search\
346 string and search for it. 418 string and search for it.
347 Type \\[isearch-yank-line] to yank rest of line onto end of search string\ 419 Type \\[isearch-yank-line] to yank rest of line onto end of search string\
348 and search for it. 420 and search for it.
421 Type \\[isearch-yank-kill] to yank last killed text onto end of search string\
422 and search for it.
349 Type \\[isearch-quote-char] to quote control character to search for it. 423 Type \\[isearch-quote-char] to quote control character to search for it.
350 Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp. 424 Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp.
351 \\[isearch-abort] while searching or when search has failed cancels input\ 425 \\[isearch-abort] while searching or when search has failed cancels input\
352 back to what has 426 back to what has
353 been found successfully. 427 been found successfully.
375 ;; Non-standard bindings 449 ;; Non-standard bindings
376 ;; Type \\[isearch-toggle-regexp] to toggle regular expression with normal searching. 450 ;; Type \\[isearch-toggle-regexp] to toggle regular expression with normal searching.
377 ;; Type \\[isearch-edit-string] to edit the search string in the minibuffer. 451 ;; Type \\[isearch-edit-string] to edit the search string in the minibuffer.
378 ;; Terminate editing and return to incremental searching with CR. 452 ;; Terminate editing and return to incremental searching with CR.
379 453
380 (interactive "_P") 454 (interactive "_P\np")
381 (isearch-mode t (not (null regexp-p)) nil (not (interactive-p)))) 455 (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
382 456
383 (defun isearch-forward-regexp () 457 (defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
384 "\ 458 "\
385 Do incremental search forward for regular expression. 459 Do incremental search forward for regular expression.
460 With a prefix argument, do a regular string search instead.
386 Like ordinary incremental search except that your input 461 Like ordinary incremental search except that your input
387 is treated as a regexp. See \\[isearch-forward] for more info." 462 is treated as a regexp. See \\[isearch-forward] for more info."
388 (interactive "_") 463 (interactive "_P\np")
389 (isearch-mode t t nil (not (interactive-p)))) 464 (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
390 465
391 (defun isearch-backward (&optional regexp-p) 466 (defun isearch-backward (&optional regexp-p no-recursive-edit)
392 "\ 467 "\
393 Do incremental search backward. 468 Do incremental search backward.
394 With a prefix argument, do an incremental regular expression search instead. 469 With a prefix argument, do a regular expression search instead.
395 See \\[isearch-forward] for more information." 470 See \\[isearch-forward] for more information."
396 (interactive "_P") 471 (interactive "_P\np")
397 (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p)))) 472 (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
398 473
399 (defun isearch-backward-regexp () 474 (defun isearch-backward-regexp (&optional not-regexp no-recursive-edit)
400 "\ 475 "\
401 Do incremental search backward for regular expression. 476 Do incremental search backward for regular expression.
477 With a prefix argument, do a regular string search instead.
402 Like ordinary incremental search except that your input 478 Like ordinary incremental search except that your input
403 is treated as a regexp. See \\[isearch-forward] for more info." 479 is treated as a regexp. See \\[isearch-forward] for more info."
404 (interactive "_") 480 (interactive "_P\np")
405 (isearch-mode nil t nil (not (interactive-p)))) 481 (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
406 482
407 ;; This function is way wrong, because you can't scroll the help 483 ;; The problem here is that you can't scroll the help screen; as soon
408 ;; screen; as soon as you press a key, it's gone. I don't know of a 484 ;; as you press a key, it's gone. I don't know of a good way to fix
409 ;; good way to fix it, though. -hniksic 485 ;; it, though. -hniksic
410 (defun isearch-mode-help () 486 (defun isearch-mode-help ()
411 (interactive "_") 487 (interactive "_")
412 (let ((w (selected-window))) 488 (let ((w (selected-window)))
413 (describe-function 'isearch-forward) 489 (describe-function 'isearch-forward)
414 (select-window w)) 490 (select-window w))
418 ;;;================================================================== 494 ;;;==================================================================
419 ;; isearch-mode only sets up incremental search for the minor mode. 495 ;; isearch-mode only sets up incremental search for the minor mode.
420 ;; All the work is done by the isearch-mode commands. 496 ;; All the work is done by the isearch-mode commands.
421 497
422 (defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p) 498 (defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
423 "Start isearch minor mode. Called by isearch-forward, etc." 499 "Start isearch minor mode. Called by `isearch-forward', etc.
500
501 \\{isearch-mode-map}"
424 502
425 (if executing-kbd-macro (setq recursive-edit nil)) 503 (if executing-kbd-macro (setq recursive-edit nil))
426 504
427 (let ((inhibit-quit t)) ; don't leave things in an inconsistent state... 505 (let ((inhibit-quit t)) ; don't leave things in an inconsistent state...
428 506
431 isearch-forward forward 509 isearch-forward forward
432 isearch-regexp regexp 510 isearch-regexp regexp
433 isearch-word word-p 511 isearch-word word-p
434 isearch-op-fun op-fun 512 isearch-op-fun op-fun
435 isearch-case-fold-search case-fold-search 513 isearch-case-fold-search case-fold-search
514 isearch-fixed-case nil
436 isearch-string "" 515 isearch-string ""
437 isearch-message "" 516 isearch-message ""
438 isearch-cmds nil 517 isearch-cmds nil
439 isearch-success t 518 isearch-success t
440 isearch-wrapped nil 519 isearch-wrapped nil
441 isearch-barrier (point) 520 isearch-barrier (point)
442 isearch-adjusted nil 521 isearch-adjusted nil
443 isearch-yank-flag nil 522 isearch-yank-flag nil
444 isearch-invalid-regexp nil 523 isearch-invalid-regexp nil
524 isearch-within-brackets nil
445 isearch-slow-terminal-mode (and (<= (device-baud-rate) 525 isearch-slow-terminal-mode (and (<= (device-baud-rate)
446 search-slow-speed) 526 search-slow-speed)
447 (> (window-height) 527 (> (window-height)
448 (* 4 search-slow-window-lines))) 528 (* 4 search-slow-window-lines)))
449 isearch-other-end nil 529 isearch-other-end nil
450 isearch-small-window nil 530 isearch-small-window nil
451 isearch-just-started t 531 isearch-just-started t
452 532
453 isearch-opoint (point) 533 isearch-opoint (point)
534 search-ring-yank-pointer nil
535 regexp-search-ring-yank-pointer nil
536 isearch-unhidden-extents nil
454 isearch-window-configuration (current-window-configuration) 537 isearch-window-configuration (current-window-configuration)
455 538
456 ;; #### Should we remember the old value of 539 ;; #### What we really need is a buffer-local
457 ;; overriding-local-map? 540 ;; overriding-local-map. See isearch-pre-command-hook for
541 ;; more details.
458 overriding-local-map (progn 542 overriding-local-map (progn
459 (set-keymap-parents isearch-mode-map 543 (set-keymap-parents isearch-mode-map
460 (nconc (current-minor-mode-maps) 544 (nconc (current-minor-mode-maps)
461 (and (current-local-map) 545 (and (current-local-map)
462 (list (current-local-map))))) 546 (list (current-local-map)))))
463 isearch-mode-map) 547 isearch-mode-map)
464 isearch-selected-frame (selected-frame) 548 isearch-selected-frame (selected-frame)
465 549
466 isearch-mode (gettext " Isearch")
467 ) 550 )
468 551
469 ;; XEmacs change: without clearing the match data, sometimes old values 552 ;; XEmacs change: without clearing the match data, sometimes old values
470 ;; of isearch-other-end get used. Don't ask me why... 553 ;; of isearch-other-end get used. Don't ask me why...
471 (store-match-data nil) 554 (store-match-data nil)
472 555
473 (add-hook 'pre-command-hook 'isearch-pre-command-hook) 556 (add-hook 'pre-command-hook 'isearch-pre-command-hook)
474 (set-buffer-modified-p (buffer-modified-p)) ; update modeline 557
558 (setq isearch-mode (gettext " Isearch"))
559 (redraw-modeline)
560
475 (isearch-push-state) 561 (isearch-push-state)
476 562
477 ) ; inhibit-quit is t before here 563 ) ; inhibit-quit is t before here
478 564
479 (isearch-update) 565 (isearch-update)
480 (run-hooks 'isearch-mode-hook) 566 (run-hooks 'isearch-mode-hook)
481 567
482 ;; isearch-mode can be made modal (in the sense of not returning to 568 ;; isearch-mode can be made modal (in the sense of not returning to
483 ;; the calling function until searching is completed) by entering 569 ;; the calling function until searching is completed) by entering
484 ;; a recursive-edit and exiting it when done isearching. 570 ;; a recursive-edit and exiting it when done isearching.
485 (if recursive-edit 571 (if recursive-edit
486 (let ((isearch-recursive-edit t)) 572 (let ((isearch-recursive-edit t))
487 (recursive-edit))) 573 (recursive-edit)))
488 ) 574 isearch-success)
489 575
490 576
491 ;;;==================================================== 577 ;;;====================================================
492 ;; Some high level utilities. Others below. 578 ;; Some high level utilities. Others below.
493 579
494 (defun isearch-update () 580 (defun isearch-update ()
495 ;; Called after each command to update the display. 581 ;; Called after each command to update the display.
496 (if (null unread-command-event) 582 (if (null unread-command-events)
497 (progn 583 (progn
498 (if (not (input-pending-p)) 584 (if (not (input-pending-p))
499 (isearch-message)) 585 (isearch-message))
500 (if (and isearch-slow-terminal-mode 586 (if (and isearch-slow-terminal-mode
501 (not (or isearch-small-window 587 (not (or isearch-small-window
502 (pos-visible-in-window-p)))) 588 (pos-visible-in-window-p))))
503 (let ((found-point (point))) 589 (let ((found-point (point)))
504 (setq isearch-small-window t) 590 (setq isearch-small-window t)
505 (move-to-window-line 0) 591 (move-to-window-line 0)
506 (let ((window-min-height 1)) 592 (let ((window-min-height 1))
518 (goto-char found-point))) 604 (goto-char found-point)))
519 (if isearch-other-end 605 (if isearch-other-end
520 (if (< isearch-other-end (point)) 606 (if (< isearch-other-end (point))
521 (isearch-highlight isearch-other-end (point)) 607 (isearch-highlight isearch-other-end (point))
522 (isearch-highlight (point) isearch-other-end)) 608 (isearch-highlight (point) isearch-other-end))
523 (if (extentp isearch-extent) 609 (isearch-dehighlight))
524 (isearch-dehighlight nil)))
525 )) 610 ))
526 (setq ;; quit-flag nil not for isearch-mode 611 (setq ;; quit-flag nil not for isearch-mode
527 isearch-adjusted nil 612 isearch-adjusted nil
528 isearch-yank-flag nil) 613 isearch-yank-flag nil)
614 (isearch-highlight-all-update)
529 ) 615 )
530 616
531 617
532 (defun isearch-done () 618 (defun isearch-done (&optional nopush edit)
533 ;; Called by all commands that terminate isearch-mode. 619 ;; Called by all commands that terminate isearch-mode.
534 (let ((inhibit-quit t)) ; danger danger! 620 (let ((inhibit-quit t)) ; danger danger!
535 (if (and isearch-buffer (buffer-live-p isearch-buffer)) 621 (if (and isearch-buffer (buffer-live-p isearch-buffer))
536 (save-excursion 622 ;; Some loser process filter might have switched the window's
537 ;; Some loser process filter might have switched the 623 ;; buffer, so be sure to set these variables back in the
538 ;; window's buffer, so be sure to set these variables back 624 ;; buffer we frobbed them in. But only if the buffer is still
539 ;; in the buffer we frobbed them in. But only if the buffer 625 ;; alive.
540 ;; is still alive. 626 (with-current-buffer isearch-buffer
541 (set-buffer isearch-buffer)
542 ;; #### Should we restore the old value of
543 ;; overriding-local-map?
544 (setq overriding-local-map nil) 627 (setq overriding-local-map nil)
545 ;; Use remove-hook instead of just setting it to our saved value 628 ;; Use remove-hook instead of just setting it to our saved value
546 ;; in case some process filter has created a buffer and modified 629 ;; in case some process filter has created a buffer and modified
547 ;; the pre-command-hook in that buffer... yeah, this is obscure, 630 ;; the pre-command-hook in that buffer... yeah, this is obscure,
548 ;; and yeah, I was getting screwed by it. -jwz 631 ;; and yeah, I was getting screwed by it. -jwz
549 (remove-hook 'pre-command-hook 'isearch-pre-command-hook) 632 (remove-hook 'pre-command-hook 'isearch-pre-command-hook)
550 (set-keymap-parents isearch-mode-map nil) 633 (set-keymap-parents isearch-mode-map nil)
551 (setq isearch-mode nil) 634 (setq isearch-mode nil)
552 (set-buffer-modified-p (buffer-modified-p));; update modeline 635 (redraw-modeline)
553 (isearch-dehighlight t))) 636 (isearch-dehighlight)
637 (isearch-highlight-all-cleanup)
638 (isearch-restore-invisible-extents nil nil)
639 ))
554 640
555 ;; it's not critical that this be inside inhibit-quit, but leaving 641 ;; it's not critical that this be inside inhibit-quit, but leaving
556 ;; things in small-window-mode would be bad. 642 ;; things in small-window-mode would be bad.
557 (let ((found-start (window-start (selected-window))) 643 (let ((found-start (window-start (selected-window)))
558 (found-point (point))) 644 (found-point (point)))
566 (set-window-start (selected-window) found-start t)))) 652 (set-window-start (selected-window) found-start t))))
567 ;; If there was movement, mark the starting position. 653 ;; If there was movement, mark the starting position.
568 ;; Maybe should test difference between and set mark iff > threshold. 654 ;; Maybe should test difference between and set mark iff > threshold.
569 (if (and (buffer-live-p isearch-buffer) 655 (if (and (buffer-live-p isearch-buffer)
570 (/= (point isearch-buffer) isearch-opoint)) 656 (/= (point isearch-buffer) isearch-opoint))
657 ;; #### FSF doesn't do this if the region is active. Should
658 ;; we do the same?
571 (progn 659 (progn
572 (push-mark isearch-opoint t nil isearch-buffer) 660 (push-mark isearch-opoint t nil isearch-buffer)
573 (or executing-kbd-macro (> (minibuffer-depth) 0) 661 (or executing-kbd-macro (> (minibuffer-depth) 0)
574 (display-message 'command "Mark saved where search started")))) 662 (display-message 'command "Mark saved where search started")))))
575 )
576 (setq isearch-buffer nil) 663 (setq isearch-buffer nil)
577 ) ; inhibit-quit is t before here 664 ) ; inhibit-quit is t before here
578 665
579 (if (> (length isearch-string) 0) 666 (if (and (> (length isearch-string) 0) (not nopush))
580 ;; Update the ring data. 667 ;; Update the ring data.
581 (if isearch-regexp 668 (isearch-update-ring isearch-string isearch-regexp))
582 (if (not (setq regexp-search-ring-yank-pointer
583 (member isearch-string regexp-search-ring)))
584 (progn
585 (setq regexp-search-ring
586 (cons isearch-string regexp-search-ring)
587 regexp-search-ring-yank-pointer regexp-search-ring)
588 (if (> (length regexp-search-ring) regexp-search-ring-max)
589 (setcdr (nthcdr (1- regexp-search-ring-max) regexp-search-ring)
590 nil))))
591 (if (not (setq search-ring-yank-pointer
592 ;; really need equal test instead of eq.
593 (member isearch-string search-ring)))
594 (progn
595 (setq search-ring (cons isearch-string search-ring)
596 search-ring-yank-pointer search-ring)
597 (if (> (length search-ring) search-ring-max)
598 (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
599 669
600 (run-hooks 'isearch-mode-end-hook) 670 (run-hooks 'isearch-mode-end-hook)
601 (if isearch-recursive-edit (exit-recursive-edit))) 671
672 (and (not edit) isearch-recursive-edit (exit-recursive-edit)))
673
674 (defun isearch-update-ring (string &optional regexp)
675 "Add STRING to the beginning of the search ring.
676 REGEXP says which ring to use."
677 (if regexp
678 (if (or (null regexp-search-ring)
679 (not (string= string (car regexp-search-ring))))
680 (progn
681 (setq regexp-search-ring
682 (cons string regexp-search-ring))
683 (if (> (length regexp-search-ring) regexp-search-ring-max)
684 (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
685 nil))))
686 (if (or (null search-ring)
687 (not (string= string (car search-ring))))
688 (progn
689 (setq search-ring (cons string search-ring))
690 (if (> (length search-ring) search-ring-max)
691 (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
602 692
603 693
604 ;;;==================================================== 694 ;;;====================================================
605 ;; Commands active while inside of the isearch minor mode. 695 ;; Commands active while inside of the isearch minor mode.
606 696
607 (defun isearch-exit () 697 (defun isearch-exit ()
608 "Exit search normally. 698 "Exit search normally.
609 However, if this is the first command after starting incremental 699 However, if this is the first command after starting incremental
610 search and `search-nonincremental-instead' is non-nil, do an 700 search and `search-nonincremental-instead' is non-nil, do a
611 incremental search via `isearch-edit-string'." 701 nonincremental search instead via `isearch-edit-string'."
612 (interactive) 702 (interactive)
613 (if (and search-nonincremental-instead 703 (if (and search-nonincremental-instead
614 (= 0 (length isearch-string))) 704 (= 0 (length isearch-string)))
615 (let ((isearch-nonincremental t)) 705 (let ((isearch-nonincremental t)
706 ;; Highlighting only gets in the way of nonincremental
707 ;; search.
708 (search-highlight nil)
709 (isearch-highlight-all-matches nil))
616 (isearch-edit-string)) 710 (isearch-edit-string))
617 (isearch-done))) 711 (isearch-done)))
618 712
619 713
620 (defun isearch-edit-string () 714 (defun isearch-edit-string ()
621 "Edit the search string in the minibuffer. 715 "Edit the search string in the minibuffer.
622 The following additional command keys are active while editing. 716 The following additional command keys are active while editing.
623 \\<minibuffer-local-isearch-map> 717 \\<minibuffer-local-isearch-map>
624 \\[exit-minibuffer] to exit editing and resume incremental searching. 718 \\[exit-minibuffer] to resume incremental searching with the edited string.
719 \\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
625 \\[isearch-forward-exit-minibuffer] to resume isearching forward. 720 \\[isearch-forward-exit-minibuffer] to resume isearching forward.
626 \\[isearch-backward-exit-minibuffer] to resume isearching backward. 721 \\[isearch-reverse-exit-minibuffer] to resume isearching backward.
627 \\[isearch-ring-advance-edit] to replace the search string with the next\ 722 \\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring.
628 item in the search ring. 723 \\[isearch-ring-retreat-edit] to replace the search string with the previous item in the search ring.
629 \\[isearch-ring-retreat-edit] to replace the search string with the next\ 724 \\[isearch-complete-edit] to complete the search string using the search ring.
630 item in the search ring. 725 \\<isearch-mode-map>
631 \\[isearch-complete-edit] to complete the search string from the search ring." 726 If first char entered is \\[isearch-yank-word], then do word search instead."
632 727
728 ;; This code is very hairy for several reasons, explained in the code.
729 ;; Mainly, isearch-mode must be terminated while editing and then restarted.
730 ;; If there were a way to catch any change of buffer from the minibuffer,
731 ;; this could be simplified greatly.
633 ;; Editing doesn't back up the search point. Should it? 732 ;; Editing doesn't back up the search point. Should it?
634 (interactive) 733 (interactive)
635 734
636 (condition-case nil 735 (condition-case nil
637 (let ((minibuffer-local-map minibuffer-local-isearch-map) 736 (progn
638 isearch-nonincremental ; should search nonincrementally? 737 (let ((isearch-nonincremental isearch-nonincremental)
639 isearch-new-string 738
640 isearch-new-message 739 ;; Locally bind all isearch global variables to protect them
641 (isearch-new-forward isearch-forward) 740 ;; from recursive isearching.
642 741 ;; isearch-string -message and -forward are not bound
643 ;; Locally bind all isearch global variables to protect them 742 ;; so they may be changed. Instead, save the values.
644 ;; from recursive isearching. 743 (isearch-new-string isearch-string)
645 (isearch-string isearch-string) 744 (isearch-new-message isearch-message)
646 (isearch-message isearch-message) 745 (isearch-new-forward isearch-forward)
647 (isearch-forward isearch-forward) ; set by commands below. 746 (isearch-new-word isearch-word)
648 747
649 (isearch-forward isearch-forward) 748 (isearch-regexp isearch-regexp)
650 (isearch-regexp isearch-regexp) 749 (isearch-op-fun isearch-op-fun)
651 (isearch-word isearch-word) 750 (isearch-cmds isearch-cmds)
652 (isearch-op-fun isearch-op-fun) 751 (isearch-success isearch-success)
653 (isearch-cmds isearch-cmds) 752 (isearch-wrapped isearch-wrapped)
654 (isearch-success isearch-success) 753 (isearch-barrier isearch-barrier)
655 (isearch-wrapped isearch-wrapped) 754 (isearch-adjusted isearch-adjusted)
656 (isearch-barrier isearch-barrier) 755 (isearch-fixed-case isearch-fixed-case)
657 (isearch-adjusted isearch-adjusted) 756 (isearch-yank-flag isearch-yank-flag)
658 (isearch-yank-flag isearch-yank-flag) 757 (isearch-invalid-regexp isearch-invalid-regexp)
659 (isearch-invalid-regexp isearch-invalid-regexp) 758 (isearch-within-brackets isearch-within-brackets)
660 (isearch-other-end isearch-other-end) 759 ;;; Don't bind this. We want isearch-search, below, to set it.
661 (isearch-opoint isearch-opoint) 760 ;;; And the old value won't matter after that.
662 (isearch-slow-terminal-mode isearch-slow-terminal-mode) 761 ;;; (isearch-other-end isearch-other-end)
663 (isearch-small-window isearch-small-window) 762 (isearch-opoint isearch-opoint)
664 (isearch-recursive-edit isearch-recursive-edit) 763 (isearch-slow-terminal-mode isearch-slow-terminal-mode)
665 (isearch-window-configuration (current-window-configuration)) 764 (isearch-small-window isearch-small-window)
666 (isearch-selected-frame (selected-frame)) 765 (isearch-recursive-edit isearch-recursive-edit)
667 ) 766 (isearch-window-configuration (current-window-configuration))
668 ;; Actually terminate isearching until editing is done. 767 (isearch-selected-frame (selected-frame))
669 ;; This is so that the user can do anything without failure, 768 )
670 ;; like switch buffers and start another isearch, and return. 769 ;; Actually terminate isearching until editing is done.
770 ;; This is so that the user can do anything without failure,
771 ;; like switch buffers and start another isearch, and return.
671 ;; (condition-case nil 772 ;; (condition-case nil
672 (isearch-done) 773 (isearch-done t t)
673 ;;#### What does this mean? There is no such condition! 774 ;;#### What does this mean? There is no such condition!
674 ;; (exit nil)) ; was recursive editing 775 ;; (exit nil)) ; was recursive editing
675 776
676 (unwind-protect 777 (unwind-protect
677 (let ((prompt (isearch-message-prefix nil t)) 778 (progn
678 event) 779 ;; Fake the prompt message for the sake of
679 ;; If the first character the user types when we prompt them 780 ;; next-command-event below.
680 ;; for a string is the yank-word character, then go into 781 (isearch-message)
681 ;; word-search mode. Otherwise unread that character and 782 ;; If the first character the user types when we
682 ;; read a string the normal way. 783 ;; prompt them for a string is the yank-word
683 (let ((cursor-in-echo-area t)) 784 ;; character, then go into word-search mode.
684 (display-message 'prompt prompt) 785 ;; Otherwise unread that character and read a string
685 (setq event (next-command-event)) 786 ;; the normal way.
686 (if (eq 'isearch-yank-word 787 (let* ((cursor-in-echo-area t)
687 (lookup-key isearch-mode-map (vector event))) 788 (event (next-command-event)))
688 (setq isearch-word t) 789 (if (eq 'isearch-yank-word
689 (setq unread-command-event event))) 790 (lookup-key isearch-mode-map (vector event)))
690 (setq isearch-new-string 791 (setq isearch-word t;; so message-prefix is right
691 ;; (if (fboundp 'gmhist-old-read-from-minibuffer) 792 isearch-new-word t)
692 ;; ;; Eschew gmhist crockery 793 (setq unread-command-event event)))
693 ;; (gmhist-old-read-from-minibuffer prompt isearch-string) 794 (setq isearch-new-string
694 (read-string 795 (read-from-minibuffer
695 prompt isearch-string 796 (isearch-message-prefix nil isearch-nonincremental)
696 't ;does its own history (but shouldn't) 797 isearch-string
697 ;; (if isearch-regexp 798 minibuffer-local-isearch-map
698 ;; ;; The search-rings aren't exactly minibuffer 799 nil
699 ;; ;; histories, but they are close enough 800 't ;does its own history (but shouldn't)
700 ;; (cons 'regexp-search-ring
701 ;; (- (length regexp-search-ring-yank-pointer)
702 ;; (length regexp-search-ring)))
703 ;; (cons 'search-ring
704 ;; (- (length search-ring-yank-pointer)
705 ;; (length search-ring))))
706 ) 801 )
707 ;; ) 802 isearch-new-message (mapconcat
708 isearch-new-message (mapconcat 803 'isearch-text-char-description
709 'isearch-text-char-description 804 isearch-new-string "")))
710 isearch-new-string "")) 805 ;; Always resume isearching by restarting it.
711 ) 806 (isearch-mode isearch-forward
712 ;; Always resume isearching by restarting it. 807 isearch-regexp
713 (isearch-mode isearch-forward 808 isearch-op-fun
714 isearch-regexp 809 isearch-recursive-edit
715 isearch-op-fun 810 isearch-word)
716 isearch-recursive-edit 811
717 isearch-word) 812 ;; Copy new values in outer locals to isearch globals
718 ) 813 (setq isearch-string isearch-new-string
719 814 isearch-message isearch-new-message
720 ;; Copy new values in outer locals to isearch globals 815 isearch-forward isearch-new-forward
721 (setq isearch-string isearch-new-string 816 isearch-word isearch-new-word))
722 isearch-message isearch-new-message 817
723 isearch-forward isearch-new-forward) 818 ;; Empty isearch-string means use default.
724 819 (if (= 0 (length isearch-string))
725 ;; Empty isearch-string means use default. 820 (setq isearch-string (or (car (if isearch-regexp
726 (if (= 0 (length isearch-string)) 821 regexp-search-ring
727 (setq isearch-string (if isearch-regexp search-last-regexp 822 search-ring))
728 search-last-string)) 823 ""))))
729 ;; Set last search string now so it is set even if we fail.
730 (if search-last-regexp
731 (setq search-last-regexp isearch-string)
732 (setq search-last-string isearch-string)))
733 824
734 ;; Reinvoke the pending search. 825 ;; Reinvoke the pending search.
735 (isearch-push-state) 826 (isearch-push-state)
736 (isearch-search) 827 (isearch-search)
737 (isearch-update) 828 (isearch-update)
754 (defun isearch-reverse-exit-minibuffer () 845 (defun isearch-reverse-exit-minibuffer ()
755 (interactive) 846 (interactive)
756 (setq isearch-new-forward nil) 847 (setq isearch-new-forward nil)
757 (exit-minibuffer)) 848 (exit-minibuffer))
758 849
850 (defun isearch-cancel ()
851 "Terminate the search and go back to the starting point."
852 (interactive)
853 (goto-char isearch-opoint)
854 (isearch-done t)
855 (signal 'quit '(isearch))) ; and pass on quit signal
759 856
760 (defun isearch-abort () 857 (defun isearch-abort ()
761 "Quit incremental search mode if searching is successful, signalling quit. 858 "Abort incremental search mode if searching is successful, signaling quit.
762 Otherwise, revert to previous successful search and continue searching. 859 Otherwise, revert to previous successful search and continue searching.
763 Use `isearch-exit' to quit without signalling." 860 Use `isearch-exit' to quit without signaling."
764 (interactive) 861 (interactive)
765 ;; (ding) signal instead below, if quiting 862 ;; (ding) signal instead below, if quitting
766 (discard-input) 863 (discard-input)
767 (if isearch-success 864 (if isearch-success
768 ;; If search is successful, move back to starting point 865 ;; If search is successful, move back to starting point
769 ;; and really do quit. 866 ;; and really do quit.
770 (progn (goto-char isearch-opoint) 867 (progn (goto-char isearch-opoint)
771 (isearch-done) ; exit isearch 868 (setq isearch-success nil)
869 (isearch-done t) ; exit isearch
772 (signal 'quit '(isearch))) ; and pass on quit signal 870 (signal 'quit '(isearch))) ; and pass on quit signal
773 ;; If search is failing, rub out until it is once more successful. 871 ;; If search is failing, or has an incomplete regexp,
774 (while (not isearch-success) (isearch-pop-state)) 872 ;; rub out until it is once more successful.
873 (while (or (not isearch-success) isearch-invalid-regexp)
874 (isearch-pop-state))
775 (isearch-update))) 875 (isearch-update)))
776
777 876
778 (defun isearch-repeat (direction) 877 (defun isearch-repeat (direction)
779 ;; Utility for isearch-repeat-forward and -backward. 878 ;; Utility for isearch-repeat-forward and -backward.
780 (if (eq isearch-forward (eq direction 'forward)) 879 (if (eq isearch-forward (eq direction 'forward))
781 ;; C-s in forward or C-r in reverse. 880 ;; C-s in forward or C-r in reverse.
782 (if (equal isearch-string "") 881 (if (equal isearch-string "")
783 ;; If search string is empty, use last one. 882 ;; If search string is empty, use last one.
784 (setq isearch-string 883 (setq isearch-string
785 (or (if isearch-regexp 884 (or (if isearch-regexp
786 (if regexp-search-ring-yank-pointer 885 (car regexp-search-ring)
787 (car regexp-search-ring-yank-pointer) 886 (car search-ring))
788 (car regexp-search-ring))
789 (if search-ring-yank-pointer
790 (car search-ring-yank-pointer)
791 (car search-ring)))
792 "") 887 "")
793 isearch-message 888 isearch-message
794 (mapconcat 'isearch-text-char-description 889 (mapconcat 'isearch-text-char-description
795 isearch-string "")) 890 isearch-string ""))
796 ;; If already have what to search for, repeat it. 891 ;; If already have what to search for, repeat it.
797 (or isearch-success 892 (or isearch-success
798 (progn 893 (progn
799
800 (goto-char (if isearch-forward (point-min) (point-max))) 894 (goto-char (if isearch-forward (point-min) (point-max)))
801 (setq isearch-wrapped t)))) 895 (setq isearch-wrapped t))))
802 ;; C-s in reverse or C-r in forward, change direction. 896 ;; C-s in reverse or C-r in forward, change direction.
803 (setq isearch-forward (not isearch-forward))) 897 (setq isearch-forward (not isearch-forward)))
804 898
805 (setq isearch-barrier (point)) ; For subsequent \| if regexp. 899 (setq isearch-barrier (point)) ; For subsequent \| if regexp.
900
806 (if (equal isearch-string "") 901 (if (equal isearch-string "")
807 (setq isearch-success t) 902 (setq isearch-success t)
808 (if (and (equal (match-end 0) (match-beginning 0)) 903 (if (and isearch-success (equal (match-end 0) (match-beginning 0))
809 isearch-success
810 (not isearch-just-started)) 904 (not isearch-just-started))
811 ;; If repeating a search that found 905 ;; If repeating a search that found
812 ;; an empty string, ensure we advance. 906 ;; an empty string, ensure we advance.
813 (if (if isearch-forward (eobp) (bobp)) 907 (if (if isearch-forward (eobp) (bobp))
814 ;; nowhere to advance to, so fail (and wrap next time) 908 ;; If there's nowhere to advance to, fail (and wrap next time).
815 (progn 909 (progn
816 (setq isearch-success nil) 910 (setq isearch-success nil)
817 (and executing-kbd-macro 911 (and executing-kbd-macro
818 (not defining-kbd-macro) 912 (not defining-kbd-macro)
819 (isearch-done)) 913 (isearch-done))
820 (ding nil 'isearch-failed)) 914 (ding nil 'isearch-failed))
821 (forward-char (if isearch-forward 1 -1)) 915 (forward-char (if isearch-forward 1 -1))
822 (isearch-search)) 916 (isearch-search))
823 (isearch-search))) 917 (isearch-search)))
918
824 (isearch-push-state) 919 (isearch-push-state)
825 (isearch-update)) 920 (isearch-update))
826 921
827 (defun isearch-repeat-forward () 922 (defun isearch-repeat-forward ()
828 "Repeat incremental search forwards." 923 "Repeat incremental search forwards."
843 (isearch-update)) 938 (isearch-update))
844 939
845 (defun isearch-toggle-case-fold () 940 (defun isearch-toggle-case-fold ()
846 "Toggle case folding in searching on or off." 941 "Toggle case folding in searching on or off."
847 (interactive) 942 (interactive)
848 (setq isearch-case-fold-search 943 (setq isearch-case-fold-search (if isearch-case-fold-search nil 'yes)
849 (if isearch-case-fold-search nil 'yes)) 944 isearch-fixed-case t)
850 (message "%s%s [case %ssensitive]" 945 (lmessage 'progress "%s%s [case %ssensitive]"
851 (isearch-message-prefix) 946 (isearch-message-prefix)
852 isearch-message 947 isearch-message
853 (if isearch-case-fold-search "in" "")) 948 (if isearch-case-fold-search "in" ""))
854 (setq isearch-adjusted t) 949 (setq isearch-adjusted t)
950 ;; Update the highlighting here so that it gets done before the
951 ;; one-second pause.
952 (isearch-highlight-all-update)
855 (sit-for 1) 953 (sit-for 1)
856 (isearch-update)) 954 (isearch-update))
857 955
858 (defun isearch-delete-char () 956 (defun isearch-delete-char ()
859 "Discard last input item and move point back. 957 "Discard last input item and move point back.
860 If no previous match was done, just beep." 958 If no previous match was done, just beep."
861 (interactive) 959 (interactive)
862 (if (null (cdr isearch-cmds)) 960 (if (null (cdr isearch-cmds))
863 (ding nil 'isearch-quit) 961 (ding nil 'isearch-quit)
864 (isearch-pop-state)) 962 (isearch-pop-state))
874 ('tty (eq tty-erase-char ?\C-h)) 972 ('tty (eq tty-erase-char ?\C-h))
875 ('x (not (x-keysym-on-keyboard-sans-modifiers-p 'backspace))))) 973 ('x (not (x-keysym-on-keyboard-sans-modifiers-p 'backspace)))))
876 (isearch-delete-char) 974 (isearch-delete-char)
877 (isearch-mode-help))) 975 (isearch-mode-help)))
878 976
977 ;; This is similar to FSF isearch-yank-string, but more general.
879 (defun isearch-yank (chunk) 978 (defun isearch-yank (chunk)
880 ;; Helper for isearch-yank-* functions. CHUNK can be a string or a 979 ;; Helper for isearch-yank-* functions. CHUNK can be a string or a
881 ;; function. 980 ;; function.
882 (let ((word (if (stringp chunk) 981 (let ((word (if (stringp chunk)
883 chunk 982 chunk
884 (save-excursion 983 (save-excursion
885 (and (not isearch-forward) isearch-other-end 984 (and (not isearch-forward) isearch-other-end
886 (goto-char isearch-other-end)) 985 (goto-char isearch-other-end))
887 (buffer-substring 986 (buffer-substring
888 (point) 987 (point)
889 (save-excursion 988 (progn
890 (funcall chunk) 989 (funcall chunk)
891 (point))))))) 990 (point)))))))
892 ;; if configured so that typing upper-case characters turns off case 991 ;; if configured so that typing upper-case characters turns off case
893 ;; folding, then downcase the string so that yanking an upper-case 992 ;; folding, then downcase the string so that yanking an upper-case
894 ;; word doesn't mess with case-foldedness. 993 ;; word doesn't mess with case-foldedness.
902 word "")) 1001 word ""))
903 ;; Don't move cursor in reverse search. 1002 ;; Don't move cursor in reverse search.
904 isearch-yank-flag t)) 1003 isearch-yank-flag t))
905 (isearch-search-and-update)) 1004 (isearch-search-and-update))
906 1005
907
908 (defun isearch-yank-word () 1006 (defun isearch-yank-word ()
909 "Pull next word from buffer into search string." 1007 "Pull next word from buffer into search string."
910 (interactive) 1008 (interactive)
911 (isearch-yank (function (lambda () (forward-word 1))))) 1009 (isearch-yank (function (lambda () (forward-word 1)))))
912 1010
923 (defun isearch-yank-sexp () 1021 (defun isearch-yank-sexp ()
924 "Pull next expression from buffer into search string." 1022 "Pull next expression from buffer into search string."
925 (interactive) 1023 (interactive)
926 (isearch-yank 'forward-sexp)) 1024 (isearch-yank 'forward-sexp))
927 1025
928 (defun isearch-yank-x-selection () 1026 (defun isearch-yank-selection ()
929 "Pull the current X selection into the search string." 1027 "Pull the current selection into the search string."
930 (interactive) 1028 (interactive)
931 (isearch-yank (x-get-selection))) 1029 (isearch-yank (get-selection)))
932 1030
933 (defun isearch-yank-x-clipboard () 1031 (defun isearch-yank-clipboard ()
934 "Pull the current X clipboard selection into the search string." 1032 "Pull the current clipboard selection into the search string."
935 (interactive) 1033 (interactive)
936 (isearch-yank (x-get-clipboard))) 1034 (isearch-yank (get-clipboard)))
937 1035
938 (defun isearch-fix-case () 1036 (defun isearch-fix-case ()
939 (if (and isearch-case-fold-search search-caps-disable-folding) 1037 ;; The commented-out (and ...) form implies that, once
940 (setq isearch-case-fold-search 1038 ;; isearch-case-fold-search becomes nil due to a capital letter
1039 ;; typed in, it can never be restored to the original value. In
1040 ;; that case, it's impossible to revert a case-sensitive search back
1041 ;; to case-insensitive.
1042 (if ;(and isearch-case-fold-search search-caps-disable-folding)
1043 (and case-fold-search
1044 ;; Make sure isearch-toggle-case-fold works.
1045 (not isearch-fixed-case)
1046 search-caps-disable-folding)
1047 (setq isearch-case-fold-search
941 (no-upper-case-p isearch-string isearch-regexp))) 1048 (no-upper-case-p isearch-string isearch-regexp)))
942 (setq isearch-mode (if case-fold-search 1049 (setq isearch-mode (if case-fold-search
943 (if isearch-case-fold-search 1050 (if isearch-case-fold-search
944 " Isearch" ;As God Intended Mode 1051 " Isearch" ;As God Intended Mode
945 " ISeARch") ;Warn about evil case via StuDLYcAps. 1052 " ISeARch") ;Warn about evil case via StuDLYcAps.
946 "Isearch" 1053 " Isearch")))
947 ; (if isearch-case-fold-search
948 ; " isearch" ;Presumably case-sensitive losers
949 ; ;will notice this 1-char difference.
950 ; " Isearch") ;Weenie mode.
951 )))
952 1054
953 (defun isearch-search-and-update () 1055 (defun isearch-search-and-update ()
954 ;; Do the search and update the display. 1056 ;; Do the search and update the display.
955 (if (and (not isearch-success) 1057 (if (and (not isearch-success)
956 ;; unsuccessful regexp search may become 1058 ;; unsuccessful regexp search may become
970 (let ((case-fold-search isearch-case-fold-search)) 1072 (let ((case-fold-search isearch-case-fold-search))
971 (looking-at (if isearch-regexp isearch-string 1073 (looking-at (if isearch-regexp isearch-string
972 (regexp-quote isearch-string))))) 1074 (regexp-quote isearch-string)))))
973 (error nil)) 1075 (error nil))
974 (or isearch-yank-flag 1076 (or isearch-yank-flag
975 (<= (match-end 0) 1077 (<= (match-end 0)
976 (min isearch-opoint isearch-barrier)))) 1078 (min isearch-opoint isearch-barrier))))
977 (setq isearch-success t 1079 (setq isearch-success t
978 isearch-invalid-regexp nil 1080 isearch-invalid-regexp nil
1081 isearch-within-brackets nil
979 isearch-other-end (match-end 0)) 1082 isearch-other-end (match-end 0))
980 ;; Not regexp, not reverse, or no match at point. 1083 ;; Not regexp, not reverse, or no match at point.
981 (if (and isearch-other-end (not isearch-adjusted)) 1084 (if (and isearch-other-end (not isearch-adjusted))
982 (goto-char (if isearch-forward isearch-other-end 1085 (goto-char (if isearch-forward isearch-other-end
983 (min isearch-opoint 1086 (min isearch-opoint
984 isearch-barrier 1087 isearch-barrier
985 (1+ isearch-other-end))))) 1088 (1+ isearch-other-end)))))
986 (isearch-search) 1089 (isearch-search)
987 )) 1090 ))
988 (isearch-push-state) 1091 (isearch-push-state)
989 (if isearch-op-fun (funcall isearch-op-fun)) 1092 (if isearch-op-fun (funcall isearch-op-fun))
990 (isearch-update)) 1093 (isearch-update))
991 1094
992 1095
993 ;; *, ?, and | chars can make a regexp more liberal. 1096 ;; *, ?, and | chars can make a regexp more liberal.
994 ;; They can make a regexp match sooner 1097 ;; They can make a regexp match sooner or make it succeed instead of failing.
995 ;; or make it succeed instead of failing.
996 ;; So go back to place last successful search started 1098 ;; So go back to place last successful search started
997 ;; or to the last ^S/^R (barrier), whichever is nearer. 1099 ;; or to the last ^S/^R (barrier), whichever is nearer.
1100 ;; + needs no special handling because the string must match at least once.
998 1101
999 (defun isearch-*-char () 1102 (defun isearch-*-char ()
1000 "Handle * and ? specially in regexps." 1103 "Handle * and ? specially in regexps."
1001 (interactive) 1104 (interactive)
1002 (if isearch-regexp 1105 (if isearch-regexp
1003 1106 (let ((idx (length isearch-string)))
1004 (progn 1107 (while (and (> idx 0)
1005 (setq isearch-adjusted t) 1108 (eq (aref isearch-string (1- idx)) ?\\))
1006 (let ((cs (nth (if isearch-forward 1109 (setq idx (1- idx)))
1007 5 ; isearch-other-end 1110 (when (= (mod (- (length isearch-string) idx) 2) 0)
1008 2) ; saved (point) 1111 (setq isearch-adjusted t)
1009 (car (cdr isearch-cmds))))) 1112 ;; Get the isearch-other-end from before the last search.
1113 ;; We want to start from there,
1114 ;; so that we don't retreat farther than that.
1010 ;; (car isearch-cmds) is after last search; 1115 ;; (car isearch-cmds) is after last search;
1011 ;; (car (cdr isearch-cmds)) is from before it. 1116 ;; (car (cdr isearch-cmds)) is from before it.
1012 (setq cs (or cs isearch-barrier)) 1117 (let ((cs (nth 5 (car (cdr isearch-cmds)))))
1013 (goto-char 1118 (setq cs (or cs isearch-barrier))
1014 (if isearch-forward 1119 (goto-char
1015 (max cs isearch-barrier) 1120 (if isearch-forward
1016 (min cs isearch-barrier)))))) 1121 (max cs isearch-barrier)
1122 (min cs isearch-barrier)))))))
1017 (isearch-process-search-char last-command-event)) 1123 (isearch-process-search-char last-command-event))
1018 1124
1019 1125
1020 1126
1021 (defun isearch-|-char () 1127 (defun isearch-|-char ()
1022 "If in regexp search, jump to the barrier." 1128 "If in regexp search, jump to the barrier."
1023 (interactive) 1129 (interactive)
1025 (progn 1131 (progn
1026 (setq isearch-adjusted t) 1132 (setq isearch-adjusted t)
1027 (goto-char isearch-barrier))) 1133 (goto-char isearch-barrier)))
1028 (isearch-process-search-char last-command-event)) 1134 (isearch-process-search-char last-command-event))
1029 1135
1136 ;; FSF:
1137 ;(defalias 'isearch-other-control-char 'isearch-other-meta-char)
1138 ;
1139 ;(defun isearch-other-meta-char ()
1140 ;...
1141 ;
1142
1030 (defun isearch-quote-char () 1143 (defun isearch-quote-char ()
1031 "Quote special characters for incremental search." 1144 "Quote special characters for incremental search."
1032 (interactive) 1145 (interactive)
1146 ;; #### Here FSF does some special conversion of chars in 0200-0377
1147 ;; range. Maybe we should do the same.
1033 (isearch-process-search-char (read-quoted-char (isearch-message t)))) 1148 (isearch-process-search-char (read-quoted-char (isearch-message t))))
1034
1035 1149
1036 (defun isearch-return-char () 1150 (defun isearch-return-char ()
1037 "Convert return into newline for incremental search. 1151 "Convert return into newline for incremental search.
1038 Obsolete." 1152 Obsolete."
1039 (interactive) 1153 (interactive)
1040 (isearch-process-search-char ?\n)) 1154 (isearch-process-search-char ?\n))
1041 1155
1042
1043 (defun isearch-printing-char () 1156 (defun isearch-printing-char ()
1044 "Any other printing character => add it to the search string and search." 1157 "Add this ordinary printing character to the search string and search."
1045 (interactive) 1158 (interactive)
1046 (isearch-process-search-char last-command-event)) 1159 (let ((event last-command-event))
1047 1160 ;; If we are called by isearch-whitespace-chars because the
1161 ;; context disallows whitespace search (e.g. within brackets),
1162 ;; replace M-SPC with a space. FSF has similar code.
1163 (and (eq this-command 'isearch-whitespace-chars)
1164 (null (event-to-character event))
1165 (setq event (character-to-event ?\ )))
1166 (isearch-process-search-char event)))
1048 1167
1049 (defun isearch-whitespace-chars () 1168 (defun isearch-whitespace-chars ()
1050 "Match all whitespace chars, if in regexp mode." 1169 "Match all whitespace chars, if in regexp mode."
1051 (interactive) 1170 ;; FSF docstring adds: "If you want to search for just a space, type
1052 (if (and isearch-regexp search-whitespace-regexp) 1171 ;; C-q SPC." But we don't need the addition because we have a
1053 (isearch-process-search-string search-whitespace-regexp " ") 1172 ;; different (better) default for the variable.
1054 (beep) 1173 (interactive)
1055 (isearch-process-search-char ?\ ) 1174 (if isearch-regexp
1056 ; (if isearch-word 1175 (if (and search-whitespace-regexp (not isearch-within-brackets)
1057 ; nil 1176 (not isearch-invalid-regexp))
1058 ; (setq isearch-word t) 1177 (isearch-process-search-string search-whitespace-regexp " ")
1059 ; (goto-char isearch-other-end) 1178 (isearch-printing-char))
1060 ; (isearch-process-search-char ?\ )) 1179 (progn
1061 )) 1180 ;; This way of doing word search doesn't correctly extend current search.
1181 ;; (setq isearch-word t)
1182 ;; (setq isearch-adjusted t)
1183 ;; (goto-char isearch-barrier)
1184 (isearch-printing-char))))
1062 1185
1063 (defun isearch-process-search-char (char) 1186 (defun isearch-process-search-char (char)
1064 ;; Append the char to the search string, update the message and re-search. 1187 ;; Append the char to the search string, update the message and re-search.
1065 (isearch-process-search-string (isearch-char-to-string char) 1188 (isearch-process-search-string (isearch-char-to-string char)
1066 (isearch-text-char-description char))) 1189 (isearch-text-char-description char)))
1067 1190
1068 (defun isearch-process-search-string (string message) 1191 (defun isearch-process-search-string (string message)
1069 (setq isearch-string (concat isearch-string string) 1192 (setq isearch-string (concat isearch-string string)
1070 isearch-message (concat isearch-message message)) 1193 isearch-message (concat isearch-message message))
1072 1195
1073 1196
1074 ;;=========================================================== 1197 ;;===========================================================
1075 ;; Search Ring 1198 ;; Search Ring
1076 1199
1077 (defcustom search-ring-update nil
1078 "*Non-nil if advancing or retreating in the search ring should cause search.
1079 Default nil means edit the string from the search ring first."
1080 :type 'boolean
1081 :group 'isearch)
1082
1083 (defun isearch-ring-adjust1 (advance) 1200 (defun isearch-ring-adjust1 (advance)
1084 ;; Helper for isearch-ring-adjust 1201 ;; Helper for isearch-ring-adjust
1085 (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) 1202 (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
1086 (length (length ring)) 1203 (length (length ring))
1087 (yank-pointer-name (if isearch-regexp 1204 (yank-pointer-name (if isearch-regexp
1090 (yank-pointer (eval yank-pointer-name))) 1207 (yank-pointer (eval yank-pointer-name)))
1091 (if (zerop length) 1208 (if (zerop length)
1092 () 1209 ()
1093 (set yank-pointer-name 1210 (set yank-pointer-name
1094 (setq yank-pointer 1211 (setq yank-pointer
1095 (nthcdr (% (+ (- length (length yank-pointer)) 1212 (mod (+ (or yank-pointer 0)
1096 (if advance (1- length) 1)) 1213 (if advance -1 1))
1097 length) ring))) 1214 length)))
1098 (setq isearch-string (car yank-pointer) 1215 (setq isearch-string (nth yank-pointer ring)
1099 isearch-message (mapconcat 'isearch-text-char-description 1216 isearch-message (mapconcat 'isearch-text-char-description
1100 isearch-string ""))))) 1217 isearch-string "")))))
1101 1218
1102 (defun isearch-ring-adjust (advance) 1219 (defun isearch-ring-adjust (advance)
1103 ;; Helper for isearch-ring-advance and isearch-ring-retreat 1220 ;; Helper for isearch-ring-advance and isearch-ring-retreat
1104 (if (cdr isearch-cmds) ;; is there more than one thing on stack? 1221 ; (if (cdr isearch-cmds) ;; is there more than one thing on stack?
1105 (isearch-pop-state)) 1222 ; (isearch-pop-state))
1106 (isearch-ring-adjust1 advance) 1223 (isearch-ring-adjust1 advance)
1107 (isearch-push-state)
1108 (if search-ring-update 1224 (if search-ring-update
1109 (progn 1225 (progn
1110 (isearch-search) 1226 (isearch-search)
1111 (isearch-update)) 1227 (isearch-update))
1112 (isearch-edit-string) 1228 (isearch-edit-string)
1113 )) 1229 )
1230 (isearch-push-state))
1114 1231
1115 (defun isearch-ring-advance () 1232 (defun isearch-ring-advance ()
1116 "Advance to the next search string in the ring." 1233 "Advance to the next search string in the ring."
1117 ;; This could be more general to handle a prefix arg, but who would use it. 1234 ;; This could be more general to handle a prefix arg, but who would use it.
1118 (interactive) 1235 (interactive)
1121 (defun isearch-ring-retreat () 1238 (defun isearch-ring-retreat ()
1122 "Retreat to the previous search string in the ring." 1239 "Retreat to the previous search string in the ring."
1123 (interactive) 1240 (interactive)
1124 (isearch-ring-adjust nil)) 1241 (isearch-ring-adjust nil))
1125 1242
1126 (defun isearch-ring-adjust-edit (advance) 1243 (defun isearch-ring-advance-edit (n)
1127 "Use the next or previous search string in the ring while in minibuffer." 1244 "Insert the next element of the search history into the minibuffer."
1128 (isearch-ring-adjust1 advance) 1245 (interactive "p")
1129 (erase-buffer) 1246 (let* ((yank-pointer-name (if isearch-regexp
1130 (insert isearch-string)) 1247 'regexp-search-ring-yank-pointer
1131 1248 'search-ring-yank-pointer))
1132 (defun isearch-ring-advance-edit () 1249 (yank-pointer (eval yank-pointer-name))
1133 (interactive) 1250 (ring (if isearch-regexp regexp-search-ring search-ring))
1134 (isearch-ring-adjust-edit 'advance)) 1251 (length (length ring)))
1135 1252 (if (zerop length)
1136 (defun isearch-ring-retreat-edit () 1253 ()
1137 "Retreat to the previous search string in the ring while in the minibuffer." 1254 (set yank-pointer-name
1138 (interactive) 1255 (setq yank-pointer
1139 (isearch-ring-adjust-edit nil)) 1256 (mod (- (or yank-pointer 0) n)
1257 length)))
1258
1259 (erase-buffer)
1260 (insert (nth yank-pointer ring))
1261 (goto-char (point-max)))))
1262
1263 (defun isearch-ring-retreat-edit (n)
1264 "Inserts the previous element of the search history into the minibuffer."
1265 (interactive "p")
1266 (isearch-ring-advance-edit (- n)))
1267
1268 ;; Merging note: FSF comments out these functions and implements them
1269 ;; differently (see above), presumably because the versions below mess
1270 ;; with isearch-string, while what we really want them to do is simply
1271 ;; to insert the correct string to the minibuffer.
1272
1273 ;;(defun isearch-ring-adjust-edit (advance)
1274 ;; "Use the next or previous search string in the ring while in minibuffer."
1275 ;; (isearch-ring-adjust1 advance)
1276 ;; (erase-buffer)
1277 ;; (insert isearch-string))
1278
1279 ;;(defun isearch-ring-advance-edit ()
1280 ;; (interactive)
1281 ;; (isearch-ring-adjust-edit 'advance))
1282
1283 ;;(defun isearch-ring-retreat-edit ()
1284 ;; "Retreat to the previous search string in the ring while in the minibuffer."
1285 ;; (interactive)
1286 ;; (isearch-ring-adjust-edit nil))
1140 1287
1141 1288
1142 (defun isearch-complete1 () 1289 (defun isearch-complete1 ()
1143 ;; Helper for isearch-complete and isearch-complete-edit 1290 ;; Helper for isearch-complete and isearch-complete-edit
1144 ;; Return t if completion OK, 1291 ;; Return t if completion OK, nil if no completion exists.
1145 (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) 1292 (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
1146 (alist (mapcar (function (lambda (string) (list string))) ring)) 1293 (alist (mapcar (function (lambda (string) (list string))) ring))
1147 (completion-ignore-case case-fold-search) 1294 (completion-ignore-case case-fold-search)
1148 (completion (try-completion isearch-string alist)) 1295 (completion (try-completion isearch-string alist)))
1149 )
1150 (cond 1296 (cond
1151 ((eq completion t) 1297 ((eq completion t)
1152 ;; isearch-string stays the same 1298 ;; isearch-string stays the same
1153 t) 1299 t)
1154 ((or completion ; not nil, must be a string 1300 ((or completion ; not nil, must be a string
1155 (= 0 (length isearch-string))) ; shouldn't have to say this 1301 (= 0 (length isearch-string))) ; shouldn't have to say this
1156 (if (equal completion isearch-string) ;; no extension? 1302 (if (equal completion isearch-string) ;; no extension?
1157 (if completion-auto-help 1303 (progn
1158 (with-output-to-temp-buffer "*Isearch completions*" 1304 (if completion-auto-help
1159 (display-completion-list 1305 (with-output-to-temp-buffer "*Isearch completions*"
1160 (all-completions isearch-string alist)))) 1306 (display-completion-list
1161 (setq isearch-string completion)) 1307 (all-completions isearch-string alist))))
1162 t) 1308 t)
1309 (and completion
1310 (setq isearch-string completion))))
1163 (t 1311 (t
1164 (temp-minibuffer-message "No completion") 1312 (temp-minibuffer-message "No completion")
1165 nil)))) 1313 nil))))
1166 1314
1167 (defun isearch-complete () 1315 (defun isearch-complete ()
1184 (erase-buffer) 1332 (erase-buffer)
1185 (insert isearch-string)))) 1333 (insert isearch-string))))
1186 1334
1187 1335
1188 ;;;============================================================== 1336 ;;;==============================================================
1189 ;; The search status stack (and isearch window-local variables, not used). 1337 ;; The search status stack.
1190 1338
1191 (defun isearch-top-state () 1339 (defun isearch-top-state ()
1192 ;; (fetch-window-local-variables)
1193 (let ((cmd (car isearch-cmds))) 1340 (let ((cmd (car isearch-cmds)))
1341 ;; #### Grr, this is so error-prone. If you add something to
1342 ;; isearch-push-state, don't forget to update this. I thought I'd
1343 ;; make a list of variables, and just do (mapcar* #'set vars
1344 ;; values), but the (point) thing would spoil it, leaving to more
1345 ;; complication.
1194 (setq isearch-string (car cmd) 1346 (setq isearch-string (car cmd)
1195 isearch-message (car (cdr cmd)) 1347 isearch-message (car (cdr cmd))
1196 isearch-success (nth 3 cmd) 1348 isearch-success (nth 3 cmd)
1197 isearch-forward (nth 4 cmd) 1349 isearch-forward (nth 4 cmd)
1198 isearch-other-end (nth 5 cmd) 1350 isearch-other-end (nth 5 cmd)
1199 isearch-invalid-regexp (nth 6 cmd) 1351 isearch-word (nth 6 cmd)
1200 isearch-wrapped (nth 7 cmd) 1352 isearch-invalid-regexp (nth 7 cmd)
1201 isearch-barrier (nth 8 cmd)) 1353 isearch-wrapped (nth 8 cmd)
1354 isearch-barrier (nth 9 cmd)
1355 isearch-within-brackets (nth 10 cmd))
1202 (goto-char (car (cdr (cdr cmd)))))) 1356 (goto-char (car (cdr (cdr cmd))))))
1203 1357
1204 (defun isearch-pop-state () 1358 (defun isearch-pop-state ()
1205 ;; (fetch-window-local-variables) 1359 (pop isearch-cmds)
1206 (setq isearch-cmds (cdr isearch-cmds))
1207 (isearch-top-state) 1360 (isearch-top-state)
1208 ) 1361
1362 ;; Make sure isearch-case-fold-search gets the correct value. FSF
1363 ;; simply stores isearch-case-fold-search to isearch-cmds. We
1364 ;; should probably do the same.
1365 (isearch-fix-case)
1366
1367 ;; Here, as well as in isearch-search we must deal with the point
1368 ;; landing at an invisible area which may need unhiding.
1369 (if (or (not (eq search-invisible 'open))
1370 (not isearch-hide-immediately))
1371 ;; If search-invisible is t, invisible text is just like any
1372 ;; other text. If it is nil, it is always skipped and we can't
1373 ;; land inside. In both cases, we don't need to do anything.
1374 ;;
1375 ;; Similarly, if isearch-hide-immediately is nil, needn't
1376 ;; re-hide the area here, and neither can we land back into a
1377 ;; hidden one.
1378 nil
1379 (when isearch-other-end
1380 ;; This will unhide the extents.
1381 (isearch-range-invisible (point) isearch-other-end))
1382 (isearch-restore-invisible-extents (point)
1383 (or isearch-other-end (point)))))
1209 1384
1210 (defun isearch-push-state () 1385 (defun isearch-push-state ()
1211 (setq isearch-cmds 1386 (setq isearch-cmds
1212 (cons (list isearch-string isearch-message (point) 1387 (cons (list isearch-string isearch-message (point)
1213 isearch-success isearch-forward isearch-other-end 1388 isearch-success isearch-forward isearch-other-end
1214 isearch-invalid-regexp isearch-wrapped isearch-barrier) 1389 isearch-word
1390 isearch-invalid-regexp isearch-wrapped isearch-barrier
1391 isearch-within-brackets)
1215 isearch-cmds))) 1392 isearch-cmds)))
1216 1393
1217 1394
1218 ;;;================================================================== 1395 ;;;==================================================================
1219 ;; Message string 1396 ;; Message string
1220 1397
1221 (defun isearch-message (&optional c-q-hack ellipsis) 1398 (defun isearch-message (&optional c-q-hack ellipsis)
1222 ;; Generate and print the message string. 1399 ;; Generate and print the message string.
1223 (let ((cursor-in-echo-area ellipsis) 1400 (let ((cursor-in-echo-area ellipsis)
1224 (m (concat 1401 (m (concat
1225 (isearch-message-prefix c-q-hack) 1402 (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
1226 isearch-message 1403 isearch-message
1227 (isearch-message-suffix c-q-hack) 1404 (isearch-message-suffix c-q-hack ellipsis)
1228 ))) 1405 )))
1229 (if c-q-hack m (display-message 'progress (format "%s" m))))) 1406 (if c-q-hack
1230 1407 m
1231 (defun isearch-message-prefix (&optional c-q-hack nonincremental) 1408 (display-message 'progress (format "%s" m)))))
1409
1410 (defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
1232 ;; If about to search, and previous search regexp was invalid, 1411 ;; If about to search, and previous search regexp was invalid,
1233 ;; check that it still is. If it is valid now, 1412 ;; check that it still is. If it is valid now,
1234 ;; let the message we display while searching say that it is valid. 1413 ;; let the message we display while searching say that it is valid.
1235 (and isearch-invalid-regexp 1414 (and isearch-invalid-regexp ellipsis
1236 (condition-case () 1415 (condition-case ()
1237 (progn (re-search-forward isearch-string (point) t) 1416 (progn (re-search-forward isearch-string (point) t)
1238 (setq isearch-invalid-regexp nil)) 1417 (setq isearch-invalid-regexp nil
1418 isearch-within-brackets nil))
1239 (error nil))) 1419 (error nil)))
1240 ;; #### - Yo! Emacs assembles strings all over the place, they can't all 1420 ;; If currently failing, display no ellipsis.
1241 ;; be internationalized in the manner proposed below... Add an explicit 1421 (or isearch-success (setq ellipsis nil))
1242 ;; call to `gettext' and have the string snarfer pluck the english 1422 ;; #### - ! Emacs assembles strings all over the place, they can't
1243 ;; strings out of the comment below. XEmacs is on a purespace diet! -Stig 1423 ;; all be internationalized in the manner proposed below... Add an
1424 ;; explicit call to `gettext' and have the string snarfer pluck the
1425 ;; english strings out of the comment below. XEmacs is on a
1426 ;; purespace diet! -Stig
1427
1428 ;; The comment below is dead and buried, but it can be rebuilt if
1429 ;; necessary. -hniksic
1244 (let ((m (concat (if isearch-success nil "failing ") 1430 (let ((m (concat (if isearch-success nil "failing ")
1245 (if isearch-wrapped "wrapped ") 1431 (if (and isearch-wrapped
1432 (if isearch-forward
1433 (> (point) isearch-opoint)
1434 (< (point) isearch-opoint)))
1435 "overwrapped "
1436 (if isearch-wrapped "wrapped "))
1246 (if isearch-word "word ") 1437 (if isearch-word "word ")
1247 (if isearch-regexp "regexp ") 1438 (if isearch-regexp "regexp ")
1248 (if nonincremental "search" "I-search") 1439 (if nonincremental "search" "I-search")
1249 (if isearch-forward nil " backward") 1440 (if isearch-forward nil " backward")
1250 ": " 1441 ": "
1251 ))) 1442 )))
1252 (aset m 0 (upcase (aref m 0))) 1443 (aset m 0 (upcase (aref m 0)))
1253 (gettext m))) 1444 (gettext m)))
1254 1445
1255 (defun isearch-message-suffix (&optional c-q-hack) 1446 (defun isearch-message-suffix (&optional c-q-hack ellipsis)
1256 (concat (if c-q-hack "^Q" "") 1447 (concat (if c-q-hack "^Q" "")
1257 (if isearch-invalid-regexp 1448 (if isearch-invalid-regexp
1258 (concat " [" isearch-invalid-regexp "]") 1449 (concat " [" isearch-invalid-regexp "]")
1259 ""))) 1450 "")))
1260 1451
1261 ;;;;; #### - yuck...this is soooo lame. Is this really worth 4k of purespace???
1262 ;;;
1263 ;;;(let ((i (logior (if isearch-success 32 0) 1452 ;;;(let ((i (logior (if isearch-success 32 0)
1264 ;;; (if isearch-wrapped 16 0) 1453 ;;; (if isearch-wrapped 16 0)
1265 ;;; (if isearch-word 8 0) 1454 ;;; (if isearch-word 8 0)
1266 ;;; (if isearch-regexp 4 0) 1455 ;;; (if isearch-regexp 4 0)
1267 ;;; (if nonincremental 2 0) 1456 ;;; (if nonincremental 2 0)
1268 ;;; (if isearch-forward 1 0)))) 1457 ;;; (if isearch-forward 1 0))))
1269 ;;; (cond 1458 ;;; (cond
1270 ;;; ((= i 63) (gettext "Wrapped word regexp search: ")) ; 111111 1459 ;;; ((= i 63) (gettext "Wrapped word regexp search: ")) ; 111111
1271 ;;; ((= i 62) (gettext "Wrapped word regexp search backward: ")) ; 111110 1460 ;;; ...and so on, ad nauseam...
1272 ;;; ((= i 61) (gettext "Wrapped word regexp I-search: ")) ; 111101
1273 ;;; ((= i 60) (gettext "Wrapped word regexp I-search backward: ")) ; 111100
1274 ;;; ((= i 59) (gettext "Wrapped word search: ")) ; 111011
1275 ;;; ((= i 58) (gettext "Wrapped word search backward: ")) ; 111010
1276 ;;; ((= i 57) (gettext "Wrapped word I-search: ")) ; 111001
1277 ;;; ((= i 56) (gettext "Wrapped word I-search backward: ")) ; 111000
1278 ;;; ((= i 55) (gettext "Wrapped regexp search: ")) ; 110111
1279 ;;; ((= i 54) (gettext "Wrapped regexp search backward: ")) ; 110110
1280 ;;; ((= i 53) (gettext "Wrapped regexp I-search: ")) ; 110101
1281 ;;; ((= i 52) (gettext "Wrapped regexp I-search backward: ")) ; 110100
1282 ;;; ((= i 51) (gettext "Wrapped search: ")) ; 110011
1283 ;;; ((= i 50) (gettext "Wrapped search backward: ")) ; 110010
1284 ;;; ((= i 49) (gettext "Wrapped I-search: ")) ; 110001
1285 ;;; ((= i 48) (gettext "Wrapped I-search backward: ")) ; 110000
1286 ;;; ((= i 47) (gettext "Word regexp search: ")) ; 101111
1287 ;;; ((= i 46) (gettext "Word regexp search backward: ")) ; 101110
1288 ;;; ((= i 45) (gettext "Word regexp I-search: ")) ; 101101
1289 ;;; ((= i 44) (gettext "Word regexp I-search backward: ")) ; 101100
1290 ;;; ((= i 43) (gettext "Word search: ")) ; 101011
1291 ;;; ((= i 42) (gettext "Word search backward: ")) ; 101010
1292 ;;; ((= i 41) (gettext "Word I-search: ")) ; 101001
1293 ;;; ((= i 40) (gettext "Word I-search backward: ")) ; 101000
1294 ;;; ((= i 39) (gettext "Regexp search: ")) ; 100111
1295 ;;; ((= i 38) (gettext "Regexp search backward: ")) ; 100110
1296 ;;; ((= i 37) (gettext "Regexp I-search: ")) ; 100101
1297 ;;; ((= i 36) (gettext "Regexp I-search backward: ")) ; 100100
1298 ;;; ((= i 35) (gettext "Search: ")) ; 100011
1299 ;;; ((= i 34) (gettext "Search backward: ")) ; 100010
1300 ;;; ((= i 33) (gettext "I-search: ")) ; 100001
1301 ;;; ((= i 32) (gettext "I-search backward: ")) ; 100000
1302 ;;; ((= i 31) (gettext "Failing wrapped word regexp search: ")) ; 011111
1303 ;;; ((= i 30) (gettext "Failing wrapped word regexp search backward: ")) ; 011110
1304 ;;; ((= i 29) (gettext "Failing wrapped word regexp I-search: ")) ; 011101
1305 ;;; ((= i 28) (gettext "Failing wrapped word regexp I-search backward: ")) ; 011100
1306 ;;; ((= i 27) (gettext "Failing wrapped word search: ")) ; 011011
1307 ;;; ((= i 26) (gettext "Failing wrapped word search backward: ")) ; 011010
1308 ;;; ((= i 25) (gettext "Failing wrapped word I-search: ")) ; 011001
1309 ;;; ((= i 24) (gettext "Failing wrapped word I-search backward: ")) ; 011000
1310 ;;; ((= i 23) (gettext "Failing wrapped regexp search: ")) ; 010111
1311 ;;; ((= i 22) (gettext "Failing wrapped regexp search backward: ")) ; 010110
1312 ;;; ((= i 21) (gettext "Failing wrapped regexp I-search: ")) ; 010101
1313 ;;; ((= i 20) (gettext "Failing wrapped regexp I-search backward: ")) ; 010100
1314 ;;; ((= i 19) (gettext "Failing wrapped search: ")) ; 010011
1315 ;;; ((= i 18) (gettext "Failing wrapped search backward: ")) ; 010010
1316 ;;; ((= i 17) (gettext "Failing wrapped I-search: ")) ; 010001
1317 ;;; ((= i 16) (gettext "Failing wrapped I-search backward: ")) ; 010000
1318 ;;; ((= i 15) (gettext "Failing word regexp search: ")) ; 001111
1319 ;;; ((= i 14) (gettext "Failing word regexp search backward: ")) ; 001110
1320 ;;; ((= i 13) (gettext "Failing word regexp I-search: ")) ; 001101
1321 ;;; ((= i 12) (gettext "Failing word regexp I-search backward: ")) ; 001100
1322 ;;; ((= i 11) (gettext "Failing word search: ")) ; 001011
1323 ;;; ((= i 10) (gettext "Failing word search backward: ")) ; 001010
1324 ;;; ((= i 9) (gettext "Failing word I-search: ")) ; 001001
1325 ;;; ((= i 8) (gettext "Failing word I-search backward: ")) ; 001000
1326 ;;; ((= i 7) (gettext "Failing regexp search: ")) ; 000111
1327 ;;; ((= i 6) (gettext "Failing regexp search backward: ")) ; 000110
1328 ;;; ((= i 5) (gettext "Failing regexp I-search: ")) ; 000101
1329 ;;; ((= i 4) (gettext "Failing regexp I-search backward: ")) ; 000100
1330 ;;; ((= i 3) (gettext "Failing search: ")) ; 000011
1331 ;;; ((= i 2) (gettext "Failing search backward: ")) ; 000010
1332 ;;; ((= i 1) (gettext "Failing I-search: ")) ; 000001
1333 ;;; ((= i 0) (gettext "Failing I-search backward: ")) ; 000000 1461 ;;; ((= i 0) (gettext "Failing I-search backward: ")) ; 000000
1334 ;;; (t (error "Something's rotten"))))) 1462 ;;; (t (error "Something's rotten")))))
1335 1463
1336 1464
1337 ;;;======================================================== 1465 ;;;========================================================
1341 (put 'isearch-return-char 'isearch-command t) 1469 (put 'isearch-return-char 'isearch-command t)
1342 (put 'isearch-repeat-forward 'isearch-command t) 1470 (put 'isearch-repeat-forward 'isearch-command t)
1343 (put 'isearch-repeat-backward 'isearch-command t) 1471 (put 'isearch-repeat-backward 'isearch-command t)
1344 (put 'isearch-delete-char 'isearch-command t) 1472 (put 'isearch-delete-char 'isearch-command t)
1345 (put 'isearch-help-or-delete-char 'isearch-command t) 1473 (put 'isearch-help-or-delete-char 'isearch-command t)
1474 (put 'isearch-cancel 'isearch-command t)
1346 (put 'isearch-abort 'isearch-command t) 1475 (put 'isearch-abort 'isearch-command t)
1347 (put 'isearch-quote-char 'isearch-command t) 1476 (put 'isearch-quote-char 'isearch-command t)
1348 (put 'isearch-exit 'isearch-command t) 1477 (put 'isearch-exit 'isearch-command t)
1349 (put 'isearch-printing-char 'isearch-command t) 1478 (put 'isearch-printing-char 'isearch-command t)
1350 (put 'isearch-printing-char 'isearch-command t) 1479 (put 'isearch-printing-char 'isearch-command t)
1369 (put 'isearch-edit-string 'isearch-command t) 1498 (put 'isearch-edit-string 'isearch-command t)
1370 (put 'isearch-toggle-regexp 'isearch-command t) 1499 (put 'isearch-toggle-regexp 'isearch-command t)
1371 (put 'isearch-forward-exit-minibuffer 'isearch-command t) 1500 (put 'isearch-forward-exit-minibuffer 'isearch-command t)
1372 (put 'isearch-reverse-exit-minibuffer 'isearch-command t) 1501 (put 'isearch-reverse-exit-minibuffer 'isearch-command t)
1373 (put 'isearch-nonincremental-exit-minibuffer 'isearch-command t) 1502 (put 'isearch-nonincremental-exit-minibuffer 'isearch-command t)
1503 (put 'isearch-yank-selection 'isearch-command t)
1504 (put 'isearch-yank-clipboard 'isearch-command t)
1374 (put 'isearch-yank-x-selection 'isearch-command t) 1505 (put 'isearch-yank-x-selection 'isearch-command t)
1375 (put 'isearch-yank-x-clipboard 'isearch-command t) 1506 (put 'isearch-yank-x-clipboard 'isearch-command t)
1376 1507
1377 ;; scrolling the scrollbar should not terminate isearch. 1508 ;; scrolling the scrollbar should not terminate isearch.
1378 1509
1406 ;; them in the buffer. In this way, the set of self-searching characters 1537 ;; them in the buffer. In this way, the set of self-searching characters
1407 ;; need not be exhaustively enumerated, but is derived from other maps. 1538 ;; need not be exhaustively enumerated, but is derived from other maps.
1408 ;; 1539 ;;
1409 (cond ((not (eq (current-buffer) isearch-buffer)) 1540 (cond ((not (eq (current-buffer) isearch-buffer))
1410 ;; If the buffer (likely meaning "frame") has changed, bail. 1541 ;; If the buffer (likely meaning "frame") has changed, bail.
1411 ;; This can also happen if a proc filter has popped up another 1542 ;; This can happen if the user types something into another
1412 ;; buffer, which is arguably a bad thing for it to have done, 1543 ;; frame. It can also happen if a proc filter has popped up
1413 ;; but the way in which isearch would have hosed you in that 1544 ;; another buffer, which is arguably a bad thing for it to
1414 ;; case is unarguably even worse. -jwz 1545 ;; have done, but the way in which isearch would have hosed
1415 (isearch-done)) 1546 ;; you in that case is unarguably even worse. -jwz
1547 (isearch-done)
1548
1549 ;; `this-command' is set according to the value of
1550 ;; `overriding-local-map', set by isearch-mode. This is
1551 ;; wrong because that keymap makes sense only in isearch
1552 ;; buffer. To make sure the right command is called, adjust
1553 ;; `this-command' to the appropriate value, now that
1554 ;; `isearch-done' has set `overriding-local-map' to nil.
1555
1556 ;; FSF does similar magic in `isearch-other-meta-char', which
1557 ;; is horribly complex. I *hope* what we do works in all
1558 ;; cases.
1559 (setq this-command (key-binding (this-command-keys))))
1416 (t 1560 (t
1417 (isearch-maybe-frob-keyboard-macros) 1561 (isearch-maybe-frob-keyboard-macros)
1418 (if (and this-command 1562 (if (and this-command
1419 (symbolp this-command) 1563 (symbolp this-command)
1420 (get this-command 'isearch-command)) 1564 (get this-command 'isearch-command))
1451 1595
1452 1596
1453 ;;;======================================================== 1597 ;;;========================================================
1454 ;;; Highlighting 1598 ;;; Highlighting
1455 1599
1456 (defcustom isearch-highlight t
1457 "*Whether isearch and query-replace should highlight the text which
1458 currently matches the search-string.")
1459
1460 (defvar isearch-extent nil) 1600 (defvar isearch-extent nil)
1461 1601
1462 ;; this face is initialized by x-faces.el since isearch is preloaded. 1602 ;; this face is initialized by faces.el since isearch is preloaded.
1463 ;; this face is now created in initialize-faces 1603 ;(make-face 'isearch)
1464 ;;(make-face 'isearch)
1465 1604
1466 (defun isearch-make-extent (begin end) 1605 (defun isearch-make-extent (begin end)
1467 (let ((x (make-extent begin end (current-buffer)))) 1606 (let ((x (make-extent begin end (current-buffer))))
1468 ;; make the isearch extent always take prescedence over any mouse- 1607 ;; make the isearch extent always take precedence over any mouse-
1469 ;; highlighted extents we may be passing through, since isearch, being 1608 ;; highlighted extents we may be passing through, since isearch, being
1470 ;; modal, is more interesting (there's nothing they could do with a 1609 ;; modal, is more interesting (there's nothing they could do with a
1471 ;; mouse-highlighted extent while in the midst of a search anyway). 1610 ;; mouse-highlighted extent while in the midst of a search anyway).
1472 (set-extent-priority x (1+ mouse-highlight-priority)) 1611 (set-extent-priority x (+ mouse-highlight-priority 2))
1473 (set-extent-face x 'isearch) 1612 (set-extent-face x 'isearch)
1474 (setq isearch-extent x))) 1613 (setq isearch-extent x)))
1475 1614
1476 (defun isearch-highlight (begin end) 1615 (defun isearch-highlight (begin end)
1477 (if (null isearch-highlight) 1616 (if (null search-highlight)
1478 nil 1617 nil
1479 ;; make sure isearch-extent is in the current buffer 1618 ;; make sure isearch-extent is in the current buffer
1480 (or (extentp isearch-extent) 1619 (or (and (extentp isearch-extent)
1620 (extent-live-p isearch-extent))
1481 (isearch-make-extent begin end)) 1621 (isearch-make-extent begin end))
1482 (set-extent-endpoints isearch-extent begin end (current-buffer)))) 1622 (set-extent-endpoints isearch-extent begin end (current-buffer))))
1483 1623
1484 (defun isearch-dehighlight (totally) 1624 ;; This used to have a TOTALLY flag that also deleted the extent. I
1485 (if (and isearch-highlight isearch-extent) 1625 ;; don't think this is necessary any longer, as isearch-highlight can
1486 (if totally 1626 ;; simply move the extent to another buffer. The IGNORED argument is
1487 (let ((inhibit-quit t)) 1627 ;; for the code that calls this function with an argument. --hniksic
1488 (if (extentp isearch-extent) 1628 (defun isearch-dehighlight (&optional ignored)
1489 (delete-extent isearch-extent)) 1629 (and search-highlight
1490 (setq isearch-extent nil)) 1630 (extentp isearch-extent)
1491 (if (extentp isearch-extent) 1631 (extent-live-p isearch-extent)
1492 (detach-extent isearch-extent) 1632 (detach-extent isearch-extent)))
1493 (setq isearch-extent nil)))))
1494 1633
1495 1634
1496 ;;;======================================================== 1635 ;;;========================================================
1497 ;;; Searching 1636 ;;; Searching
1498 1637
1500 ;; Do the search with the current search string. 1639 ;; Do the search with the current search string.
1501 (isearch-message nil t) 1640 (isearch-message nil t)
1502 (isearch-fix-case) 1641 (isearch-fix-case)
1503 (condition-case lossage 1642 (condition-case lossage
1504 (let ((inhibit-quit nil) 1643 (let ((inhibit-quit nil)
1505 (case-fold-search isearch-case-fold-search)) 1644 (case-fold-search isearch-case-fold-search)
1645 (retry t))
1506 (if isearch-regexp (setq isearch-invalid-regexp nil)) 1646 (if isearch-regexp (setq isearch-invalid-regexp nil))
1507 (setq isearch-success 1647 (setq isearch-within-brackets nil)
1508 (funcall 1648 (while retry
1509 (cond (isearch-word 1649 (setq isearch-success
1510 (if isearch-forward 1650 (funcall
1511 'word-search-forward 'word-search-backward)) 1651 (cond (isearch-word
1512 (isearch-regexp 1652 (if isearch-forward
1513 (if isearch-forward 1653 'word-search-forward 'word-search-backward))
1514 're-search-forward 're-search-backward)) 1654 (isearch-regexp
1515 (t 1655 (if isearch-forward
1516 (if isearch-forward 'search-forward 'search-backward))) 1656 're-search-forward 're-search-backward))
1517 isearch-string nil t)) 1657 (t
1658 (if isearch-forward 'search-forward 'search-backward)))
1659 isearch-string nil t))
1660 ;; Clear RETRY unless we matched some invisible text
1661 ;; and we aren't supposed to do that.
1662 (if (or (eq search-invisible t)
1663 (not isearch-success)
1664 (bobp) (eobp)
1665 (= (match-beginning 0) (match-end 0))
1666 (not (isearch-range-invisible
1667 (match-beginning 0) (match-end 0))))
1668 (setq retry nil)))
1518 (setq isearch-just-started nil) 1669 (setq isearch-just-started nil)
1519 (if isearch-success 1670 (when isearch-success
1520 (setq isearch-other-end 1671 (setq isearch-other-end
1521 (if isearch-forward (match-beginning 0) (match-end 0))))) 1672 (if isearch-forward (match-beginning 0) (match-end 0)))
1522 1673 (and isearch-hide-immediately
1523 (quit (setq unread-command-event (character-to-event (quit-char))) 1674 (isearch-restore-invisible-extents (match-beginning 0)
1675 (match-end 0)))))
1676
1677 (quit (setq unread-command-events (nconc unread-command-events
1678 (character-to-event (quit-char))))
1524 (setq isearch-success nil)) 1679 (setq isearch-success nil))
1525 1680
1526 (invalid-regexp 1681 (invalid-regexp
1527 (setq isearch-invalid-regexp (car (cdr lossage))) 1682 (setq isearch-invalid-regexp (car (cdr lossage)))
1683 (setq isearch-within-brackets (string-match "\\`Unmatched \\["
1684 isearch-invalid-regexp))
1528 (if (string-match 1685 (if (string-match
1529 "\\`Premature \\|\\`Unmatched \\|\\`Invalid " 1686 "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
1530 isearch-invalid-regexp) 1687 isearch-invalid-regexp)
1531 (setq isearch-invalid-regexp (gettext "incomplete input"))))) 1688 (setq isearch-invalid-regexp (gettext "incomplete input"))))
1689 (error
1690 ;; stack overflow in regexp search.
1691 (setq isearch-invalid-regexp (car (cdr lossage)))))
1532 1692
1533 (if isearch-success 1693 (if isearch-success
1534 nil 1694 nil
1535 1695
1536 ;; If we're being run inside a keyboard macro, then the call to 1696 ;; If we're being run inside a keyboard macro, then the call to
1546 ;; Ding if failed this time after succeeding last time. 1706 ;; Ding if failed this time after succeeding last time.
1547 (and (nth 3 (car isearch-cmds)) 1707 (and (nth 3 (car isearch-cmds))
1548 (ding nil 'isearch-failed)) 1708 (ding nil 'isearch-failed))
1549 (goto-char (nth 2 (car isearch-cmds))))) 1709 (goto-char (nth 2 (car isearch-cmds)))))
1550 1710
1551 ;;;================================================= 1711 ;; Replaced with isearch-edit-string.
1552 ;; This is called from incremental-search
1553 ;; if the first input character is the exit character.
1554
1555 ;; We store the search string in `isearch-string'
1556 ;; which has been bound already by `isearch-search'
1557 ;; so that, when we exit, it is copied into `search-last-string'.
1558
1559 ;(defun nonincremental-search (forward regexp) 1712 ;(defun nonincremental-search (forward regexp)
1560 ; ;; This may be broken. Anyway, it is replaced by the isearch-edit-string. 1713 ;...
1561 ; ;; Missing features: word search option, command history. 1714
1562 ; (setq isearch-forward forward 1715 (defun isearch-unhide-extent (extent)
1563 ; isearch-regexp regexp) 1716 ;; Store the values for the `invisible' and `intangible'
1564 ; (let (char function 1717 ;; properties, and then set them to nil. This way the text hidden
1565 ; inhibit-quit 1718 ;; by this extent becomes visible.
1566 ; (cursor-in-echo-area t)) 1719 (put extent 'isearch-invisible (get extent 'invisible))
1567 ; ;; Prompt assuming not word search, 1720 (put extent 'isearch-intangible (get extent 'intangible))
1568 ; (setq isearch-message 1721 (put extent 'invisible nil)
1569 ; (if isearch-regexp 1722 (put extent 'intangible nil))
1570 ; (if isearch-forward "Regexp search: " 1723
1571 ; "Regexp search backward: ") 1724 (defun isearch-range-invisible (beg end)
1572 ; (if isearch-forward "Search: " "Search backward: "))) 1725 "Return t if all the text from BEG to END is invisible.
1573 ; (message "%s" isearch-message) 1726 Before that, if search-invisible is `open', unhide the extents with an
1574 ; ;; Read 1 char and switch to word search if it is ^W. 1727 `isearch-open-invisible' property."
1575 ; (setq char (read-char)) 1728 ;; isearch-search uses this to skip the extents that are invisible,
1576 ; (if (eq char search-yank-word-char) 1729 ;; but don't have `isearch-open-invisible' set. It is unclear
1577 ; (setq isearch-message (if isearch-forward "Word search: " 1730 ;; what's supposed to happen if only a part of [BEG, END) overlaps
1578 ; "Word search backward: ")) 1731 ;; the extent.
1579 ; ;; Otherwise let that 1 char be part of the search string. 1732 (let (to-be-unhidden)
1580 ; (setq unread-command-event (character-to-event char)) 1733 (if (map-extents
1581 ; ) 1734 (lambda (extent ignored)
1582 ; (setq function 1735 (if (and (<= (extent-start-position extent) beg)
1583 ; (if (eq char search-yank-word-char) 1736 (>= (extent-end-position extent) end))
1584 ; (if isearch-forward 'word-search-forward 'word-search-backward) 1737 ;; All of the region is covered by the extent.
1585 ; (if isearch-regexp 1738 (if (and (eq search-invisible 'open)
1586 ; (if isearch-forward 're-search-forward 're-search-backward) 1739 (get extent 'isearch-open-invisible))
1587 ; (if isearch-forward 'search-forward 'search-backward)))) 1740 (progn
1588 ; ;; Read the search string with corrected prompt. 1741 (push extent to-be-unhidden)
1589 ; (setq isearch-string (read-string isearch-message isearch-string)) 1742 nil) ; keep mapping
1590 ; ;; Empty means use default. 1743 ;; We can't or won't unhide this extent, so we must
1591 ; (if (= 0 (length isearch-string)) 1744 ;; skip the whole match. We return from map-extents
1592 ; (setq isearch-string search-last-string) 1745 ;; immediately.
1593 ; ;; Set last search string now so it is set even if we fail. 1746 t)
1594 ; (setq search-last-string isearch-string)) 1747 ;; Else, keep looking.
1595 ; ;; Since we used the minibuffer, we should be available for redo. 1748 nil))
1596 ; (setq command-history 1749 nil beg end nil 'all-extents-closed 'invisible)
1597 ; (cons (list function isearch-string) command-history)) 1750 ;; The whole match must be skipped. Signal it by returning t
1598 ; ;; Go ahead and search. 1751 ;; to the caller.
1599 ; (if search-caps-disable-folding 1752 t
1600 ; (setq isearch-case-fold-search 1753 ;; If any extents need to be unhidden, unhide them.
1601 ; (no-upper-case-p isearch-string isearch-regexp))) 1754 (mapc #'isearch-unhide-extent to-be-unhidden)
1602 ; (let ((case-fold-search isearch-case-fold-search)) 1755 ;; Will leave this assert for some time, to catch bugs.
1603 ; (funcall function isearch-string)))) 1756 (assert (null (intersection to-be-unhidden isearch-unhidden-extents)))
1757 (setq isearch-unhidden-extents (nconc to-be-unhidden
1758 isearch-unhidden-extents))
1759 nil)))
1760
1761 (defun isearch-restore-extent (extent)
1762 (put extent 'invisible (get extent 'isearch-invisible))
1763 (put extent 'intangible (get extent 'isearch-intangible))
1764 (remprop extent 'isearch-invisible)
1765 (remprop extent 'isearch-intangible))
1766
1767 ;; FSF calls this function `isearch-clean-overlays'.
1768 (defun isearch-restore-invisible-extents (beg end)
1769 (cond
1770 ((null beg)
1771 ;; Delete all -- this is called at the end of isearch.
1772 (mapc #'isearch-restore-extent isearch-unhidden-extents)
1773 (setq isearch-unhidden-extents nil))
1774 (t
1775 ;; Extents that do not overlap the match area can be safely
1776 ;; restored to their hidden state.
1777 (setq isearch-unhidden-extents
1778 (delete-if (lambda (extent)
1779 (unless (extent-in-region-p extent beg end
1780 'all-extents-closed)
1781 (isearch-restore-extent extent)
1782 t))
1783 isearch-unhidden-extents)))))
1604 1784
1605 (defun isearch-no-upper-case-p (string) 1785 (defun isearch-no-upper-case-p (string)
1606 "Return t if there are no upper case chars in string. 1786 "Return t if there are no upper case chars in string.
1607 But upper case chars preceded by \\ do not count since they 1787 But upper case chars preceded by \\ do not count since they
1608 have special meaning in a regexp." 1788 have special meaning in a regexp."
1609 ;; this incorrectly returns t for "\\\\A" 1789 ;; this incorrectly returns t for "\\\\A"
1610 (let ((case-fold-search nil)) 1790 (let ((case-fold-search nil))
1611 (not (string-match "\\(^\\|[^\\]\\)[A-Z]" string)))) 1791 (not (string-match "\\(^\\|[^\\]\\)[A-Z]" string))))
1612 (make-obsolete 'isearch-no-upper-case-p 'no-upper-case-p) 1792 (make-obsolete 'isearch-no-upper-case-p 'no-upper-case-p)
1793
1794 ;; Portability functions to support various Emacs versions.
1795
1796 (defun isearch-char-to-string (c)
1797 (if (eventp c)
1798 (make-string 1 (event-to-character c nil nil t))
1799 (make-string 1 c)))
1800
1801 ;(defun isearch-text-char-description (c)
1802 ; (isearch-char-to-string c))
1803
1804 (define-function 'isearch-text-char-description 'text-char-description)
1613 1805
1614 ;; Used by etags.el and info.el 1806 ;; Used by etags.el and info.el
1615 (defmacro with-caps-disable-folding (string &rest body) "\ 1807 (defmacro with-caps-disable-folding (string &rest body) "\
1616 Eval BODY with `case-fold-search' let to nil if STRING contains 1808 Eval BODY with `case-fold-search' let to nil if STRING contains
1617 uppercase letters and `search-caps-disable-folding' is t." 1809 uppercase letters and `search-caps-disable-folding' is t."
1622 ,@body)) 1814 ,@body))
1623 (make-obsolete 'with-caps-disable-folding 'with-search-caps-disable-folding) 1815 (make-obsolete 'with-caps-disable-folding 'with-search-caps-disable-folding)
1624 (put 'with-caps-disable-folding 'lisp-indent-function 1) 1816 (put 'with-caps-disable-folding 'lisp-indent-function 1)
1625 (put 'with-caps-disable-folding 'edebug-form-spec '(form body)) 1817 (put 'with-caps-disable-folding 'edebug-form-spec '(form body))
1626 1818
1819
1820 ;;;========================================================
1821 ;;; Advanced highlighting
1822
1823 ;; When active, *every* visible match for the current search string is
1824 ;; highlighted: the current one using the normal isearch match color
1825 ;; and all the others using the `isearch-secondary' face. The extra
1826 ;; highlighting makes it easier to anticipate where the cursor will
1827 ;; land each time you press C-s or C-r to repeat a pending search.
1828 ;; Only the matches visible at any point are highlighted -- when you
1829 ;; move through the buffer, the highlighting is readjusted.
1830
1831 ;; This is based on ideas from Bob Glickstein's `ishl' package. It
1832 ;; has been merged with XEmacs by Darryl Okahata, and then completely
1833 ;; rewritten by Hrvoje Niksic.
1834
1835 ;; The code makes the following assumptions about the rest of this
1836 ;; file, so be careful when modifying it.
1837
1838 ;; * `isearch-highlight-all-update' should get called when the search
1839 ;; string changes, or when the search advances. This is done from
1840 ;; `isearch-update'.
1841 ;; * `isearch-highlight-all-cleanup' should get called when the search
1842 ;; is done. This is performed in `isearch-done'.
1843 ;; * `isearch-string' is expected to contain the current search string
1844 ;; as entered by the user.
1845 ;; * `isearch-opoint' is expected to contain the location where the
1846 ;; current search began.
1847 ;; * the type of the current search is expected to be given by
1848 ;; `isearch-word' and `isearch-regexp'.
1849 ;; * the variable `isearch-invalid-regexp' is expected to be true iff
1850 ;; `isearch-string' is an invalid regexp.
1851
1852 (defcustom isearch-highlight-all-matches search-highlight
1853 "*Non-nil means highlight all visible matches."
1854 :type 'boolean
1855 :group 'isearch)
1856
1857 ;; We can't create this face here, as isearch.el is preloaded.
1858 ;; #### Think up a better name for this!
1859 ;(defface isearch-secondary '((t (:foreground "red3")))
1860 ; "Face to use for highlighting all matches."
1861 ; :group 'isearch)
1862
1863 (defvar isearch-highlight-extents nil)
1864 (defvar isearch-window-start nil)
1865 (defvar isearch-window-end nil)
1866 ;; We compare isearch-string and isearch-case-fold-search to saved
1867 ;; values for better efficiency.
1868 (defvar isearch-highlight-last-string nil)
1869 (defvar isearch-highlight-last-case-fold-search nil)
1870 (defvar isearch-highlight-last-regexp nil)
1871
1872 (defun isearch-delete-extents-in-range (start end)
1873 ;; Delete all highlighting extents that overlap [START, END).
1874 (setq isearch-highlight-extents
1875 (delete-if (lambda (extent)
1876 (when (extent-in-region-p extent start end)
1877 (delete-extent extent)
1878 t))
1879 isearch-highlight-extents)))
1880
1881 (defun isearch-highlight-all-cleanup ()
1882 ;; Stop lazily highlighting and remove extra highlighting from
1883 ;; buffer.
1884 (mapc #'delete-extent isearch-highlight-extents)
1885 (setq isearch-highlight-extents nil)
1886 (setq isearch-highlight-all-start nil
1887 isearch-window-end nil
1888 isearch-highlight-last-string nil))
1889
1890 (defun isearch-highlight-all-update ()
1891 ;; Update the highlighting if necessary. This needs to check if the
1892 ;; search string has changed, or if the window has changed position
1893 ;; in the buffer.
1894 (let ((need-start-over nil))
1895 ;; NB: we don't check for isearch-success because if the point is
1896 ;; after the last match, the search can be unsuccessful, and yet
1897 ;; there are things to highlight.
1898 (cond ((not isearch-highlight-all-matches))
1899 ((or (equal isearch-string "")
1900 isearch-invalid-regexp)
1901 (isearch-highlight-all-cleanup))
1902 ((not (eq isearch-case-fold-search
1903 isearch-highlight-last-case-fold-search))
1904 ;; This case is usually caused by search string being
1905 ;; changed, which would be caught below, but it can also be
1906 ;; tripped using isearch-toggle-case-fold.
1907 (setq need-start-over t))
1908 ((not (eq isearch-regexp isearch-highlight-last-regexp))
1909 ;; Ditto for isearch-toggle-regexp.
1910 (setq need-start-over t))
1911 ((equal isearch-string isearch-highlight-last-string)
1912 ;; The search string is the same. We need to do something
1913 ;; if our position has changed.
1914
1915 ;; It would be nice if we didn't have to do this; however,
1916 ;; window-start doesn't support a GUARANTEE flag, so we must
1917 ;; force redisplay to get the correct value for start and end
1918 ;; of window.
1919 (sit-for 0)
1920
1921 ;; Check whether our location has changed.
1922 (let ((start (window-start))
1923 (end (min (window-end) (point-max))))
1924 (cond ((and (= start isearch-window-start)
1925 (= end isearch-window-end))
1926 ;; Our position is unchanged -- do nothing.
1927 )
1928 ((and (> start isearch-window-start)
1929 (> end isearch-window-end)
1930 (<= start isearch-window-end))
1931 ;; We've migrated downward, but we overlap the old
1932 ;; region. Delete the old non-overlapping extents
1933 ;; and fill in the rest.
1934 (isearch-delete-extents-in-range isearch-window-start start)
1935 (isearch-highlightify-region isearch-window-end end)
1936 (setq isearch-window-start start
1937 isearch-window-end end))
1938 ((and (<= start isearch-window-start)
1939 (<= end isearch-window-end)
1940 (> end isearch-window-start))
1941 ;; We've migrated upward, but we overlap the old
1942 ;; region. Delete the old non-overlapping extents
1943 ;; and fill in the rest.
1944 (isearch-delete-extents-in-range
1945 end isearch-window-end)
1946 (isearch-highlightify-region start isearch-window-start)
1947 (setq isearch-window-start start
1948 isearch-window-end end))
1949 (t
1950 ;; The regions don't overlap, or they overlap in a
1951 ;; weird way.
1952 (setq need-start-over t)))))
1953 (t
1954 ;; The search string has changed.
1955
1956 ;; If more input is pending, don't start over because
1957 ;; starting over forces redisplay, and that slows down
1958 ;; typing.
1959 (unless (input-pending-p)
1960 (setq need-start-over t))))
1961 (when need-start-over
1962 ;; Force redisplay before removing the old extents, in order to
1963 ;; avoid flicker.
1964 (sit-for 0)
1965 (isearch-highlight-all-cleanup)
1966 (setq isearch-window-start (window-start)
1967 isearch-window-end (min (window-end) (point-max)))
1968 (isearch-highlightify-region isearch-window-start isearch-window-end))
1969
1970 (setq isearch-highlight-last-string isearch-string
1971 isearch-highlight-last-case-fold-search isearch-case-fold-search
1972 isearch-highlight-last-regexp isearch-regexp)))
1973
1974 (defun isearch-highlight-advance (string forwardp)
1975 ;; Search ahead for the next or previous match. This is the same as
1976 ;; isearch-search, but without the extra baggage. Maybe it should
1977 ;; be in a separate function.
1978 (let ((case-fold-search isearch-case-fold-search))
1979 (funcall (cond (isearch-word (if forwardp
1980 'word-search-forward
1981 'word-search-backward))
1982 (isearch-regexp (if forwardp
1983 're-search-forward
1984 're-search-backward))
1985 (t (if forwardp
1986 'search-forward
1987 'search-backward)))
1988 string nil t)))
1989
1990 (defun isearch-highlightify-region (start end)
1991 ;; Highlight all occurrences of isearch-string between START and
1992 ;; END. To do this right, we have to search forward as long as
1993 ;; there are matches that overlap [START, END), and then search
1994 ;; backward the same way.
1995 (save-excursion
1996 (goto-char isearch-opoint)
1997 (let ((lastpoint (point)))
1998 (while (and (isearch-highlight-advance isearch-string t)
1999 (/= lastpoint (point))
2000 (< (match-beginning 0) end))
2001 (let ((extent (make-extent (match-beginning 0)
2002 (match-end 0))))
2003 (set-extent-priority extent (1+ mouse-highlight-priority))
2004 (put extent 'face 'isearch-secondary)
2005 (push extent isearch-highlight-extents))
2006 (setq lastpoint (point))))
2007 (goto-char isearch-opoint)
2008 (let ((lastpoint (point)))
2009 (while (and (isearch-highlight-advance isearch-string nil)
2010 (/= lastpoint (point))
2011 (>= (match-end 0) start))
2012 (let ((extent (make-extent (match-beginning 0)
2013 (match-end 0))))
2014 (set-extent-priority extent (1+ mouse-highlight-priority))
2015 (put extent 'face 'isearch-secondary)
2016 (push extent isearch-highlight-extents))
2017 (setq lastpoint (point))))))
2018
1627 ;;; isearch-mode.el ends here 2019 ;;; isearch-mode.el ends here