comparison lisp/isearch-mode.el @ 412:697ef44129c6 r21-2-14

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