347
|
1 ;; Incremental search
|
|
2 ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
|
|
3
|
|
4 ;; This file is part of GNU Emacs.
|
|
5
|
|
6 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
7 ;; it under the terms of the GNU General Public License as published by
|
|
8 ;; the Free Software Foundation; either version 1, or (at your option)
|
|
9 ;; any later version.
|
|
10
|
|
11 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 ;; GNU General Public License for more details.
|
|
15
|
|
16 ;; You should have received a copy of the GNU General Public License
|
|
17 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
18 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
19
|
|
20 ;;;###autoload
|
|
21 (defvar search-last-string "" "\
|
|
22 Last string search for by a non-regexp search command.
|
|
23 This does not include direct calls to the primitive search functions,
|
|
24 and does not include searches that are aborted.")
|
|
25
|
|
26 ;;;###autoload
|
|
27 (defvar search-last-regexp "" "\
|
|
28 Last string searched for by a regexp search command.
|
|
29 This does not include direct calls to the primitive search functions,
|
|
30 and does not include searches that are aborted.")
|
|
31
|
|
32
|
|
33 ;;;###autoload
|
|
34 (defconst search-repeat-char ?\C-s "\
|
|
35 *Character to repeat incremental search forwards.")
|
|
36 ;;;###autoload
|
|
37 (defconst search-reverse-char ?\C-r "\
|
|
38 *Character to repeat incremental search backwards.")
|
|
39 ;;;###autoload
|
|
40 (defconst search-exit-char ?\C-m "\
|
|
41 *Character to exit incremental search.")
|
|
42 ;;;###autoload
|
|
43 (defconst search-delete-char ?\177 "\
|
|
44 *Character to delete from incremental search string.")
|
|
45 ;;;###autoload
|
|
46 (defconst search-quote-char ?\C-q "\
|
|
47 *Character to quote special characters for incremental search.")
|
|
48 ;;;###autoload
|
|
49 (defconst search-yank-word-char ?\C-w "\
|
|
50 *Character to pull next word from buffer into search string.")
|
|
51 ;;;###autoload
|
|
52 (defconst search-yank-line-char ?\C-y "\
|
|
53 *Character to pull rest of line from buffer into search string.")
|
|
54 ;;;###autoload
|
|
55 (defconst search-ring-advance-char ?\M-n "\
|
|
56 *Character to pull next (more recent) search string from the ring of same.")
|
|
57 ;;;###autoload
|
|
58 (defconst search-ring-retreat-char ?\M-p "\
|
|
59 *Character to pull previous (older) search string from the ring of same.")
|
|
60
|
|
61 ;;;###autoload
|
|
62 (defconst search-exit-option t "\
|
|
63 *Non-nil means random control characters terminate incremental search.")
|
|
64
|
|
65 ;;;###autoload
|
|
66 (defvar search-slow-window-lines 1 "\
|
|
67 *Number of lines in slow search display windows.
|
|
68 These are the short windows used during incremental search on slow terminals.
|
|
69 Negative means put the slow search window at the top (normally it's at bottom)
|
|
70 and the value is minus the number of lines.")
|
|
71
|
|
72 ;;;###autoload
|
|
73 (defvar search-slow-speed 1200 "\
|
|
74 *Highest terminal speed at which to use \"slow\" style incremental search.
|
|
75 This is the style where a one-line window is created to show the line
|
|
76 that the search has reached.")
|
|
77
|
|
78 (defconst search-upper-case t
|
|
79 "*Non-nil means an upper-case letter as search input means case-sensitive.
|
|
80 Any upper-case letter given explicitly as input to the incremental search
|
|
81 has the effect of turning off `case-fold-search' for the rest of this search.
|
|
82 Deleting the letter from the search string cancels the effect.")
|
|
83
|
|
84 (fset 'search-forward-regexp 're-search-forward)
|
|
85 (fset 'search-backward-regexp 're-search-backward)
|
|
86
|
|
87 (defvar search-ring nil
|
|
88 "List of recent non-regexp incremental searches.
|
|
89 Each element is a cons cell of the form (STRING . UPPERCASE-FLAG).")
|
|
90
|
|
91 (defvar regexp-search-ring nil
|
|
92 "List of recent regexp incremental searches.
|
|
93 Each element is a cons cell of the form (STRING . UPPERCASE-FLAG).")
|
|
94
|
|
95 (defconst search-ring-max 16
|
|
96 "*Maximum length of search ring before oldest elements are thrown away.")
|
|
97
|
|
98 (defvar search-ring-yank-pointer nil
|
|
99 "The tail of the search ring whose car is the last thing searched for.")
|
|
100
|
|
101 (defvar regexp-search-ring-yank-pointer nil
|
|
102 "The tail of the regular expression search ring whose car is the last
|
|
103 thing searched for.")
|
|
104
|
|
105
|
|
106 ;;;###autoload
|
|
107 (defun isearch-forward ()
|
|
108 "Do incremental search forward.
|
|
109 As you type characters, they add to the search string and are found.
|
|
110 Type Delete to cancel characters from end of search string.
|
|
111 Type RET to exit, leaving point at location found.
|
|
112 Type C-s to search again forward, C-r to search again backward.
|
|
113 Type C-w to yank word from buffer onto end of search string and search for it.
|
|
114 Type C-y to yank rest of line onto end of search string, etc.
|
|
115 Type C-q to quote control character to search for it.
|
|
116 Other control and meta characters terminate the search
|
|
117 and are then executed normally.
|
|
118 The above special characters are mostly controlled by parameters;
|
|
119 do M-x apropos on search-.*-char to find them.
|
|
120 C-g while searching or when search has failed
|
|
121 cancels input back to what has been found successfully.
|
|
122 C-g when search is successful aborts and moves point to starting point."
|
|
123 (interactive)
|
|
124 (isearch t))
|
|
125 ;;;###autoload
|
|
126 (define-key global-map "\C-s" 'isearch-forward)
|
|
127
|
|
128 ;;;###autoload
|
|
129 (defun isearch-forward-regexp ()
|
|
130 "Do incremental search forward for regular expression.
|
|
131 Like ordinary incremental search except that your input
|
|
132 is treated as a regexp. See \\[isearch-forward] for more info."
|
|
133 (interactive)
|
|
134 (isearch t t))
|
|
135 ;;;###autoload
|
|
136 (define-key esc-map "\C-s" 'isearch-forward-regexp)
|
|
137
|
|
138 ;;;###autoload
|
|
139 (defun isearch-backward ()
|
|
140 "Do incremental search backward.
|
|
141 See \\[isearch-forward] for more information."
|
|
142 (interactive)
|
|
143 (isearch nil))
|
|
144 ;;;###autoload
|
|
145 (define-key global-map "\C-r" 'isearch-backward)
|
|
146
|
|
147 ;;;###autoload
|
|
148 (defun isearch-backward-regexp ()
|
|
149 "Do incremental search backward for regular expression.
|
|
150 Like ordinary incremental search except that your input
|
|
151 is treated as a regexp. See \\[isearch-forward] for more info."
|
|
152 (interactive)
|
|
153 (isearch nil t))
|
|
154 ;;;###autoload
|
|
155 (define-key esc-map "\C-r" 'isearch-backward-regexp)
|
|
156
|
|
157
|
|
158 ;; This function does all the work of incremental search.
|
|
159 ;; The functions attached to ^R and ^S are trivial,
|
|
160 ;; merely calling this one, but they are always loaded by default
|
|
161 ;; whereas this file can optionally be autoloadable.
|
|
162 ;; This is the only entry point in this file.
|
|
163
|
|
164 ;; OP-FUN is a function to be called after each input character is processed.
|
|
165 ;; (It is not called after characters that exit the search.)
|
|
166
|
|
167 (defun isearch (forward &optional regexp op-fun)
|
|
168 (let ((search-string "")
|
|
169 (search-message "")
|
|
170 ;; List of previous states during this search.
|
|
171 (history nil)
|
|
172 ;; t means search is currently successful.
|
|
173 (success t)
|
|
174 ;; Set once the search has wrapped around the end of the buffer.
|
|
175 (wrapped nil)
|
|
176 ;; Nominal starting point for searching
|
|
177 ;; Usually this is the same as the opoint,
|
|
178 ;; but it is changed by wrapping
|
|
179 ;; and also by repeating the search.
|
|
180 (barrier (point))
|
|
181 ;; Set temporarily when adding a character to a regexp
|
|
182 ;; enables it to match more rather than fewer places in the buffer.
|
|
183 liberalized
|
|
184 ;; Set temporarily by yanking text into the search string.
|
|
185 yank-flag
|
|
186 (invalid-regexp nil)
|
|
187 ;; non-nil means an explicit uppercase letter seen in the input
|
|
188 (uppercase-flag nil)
|
|
189 ;; Non-nil means start using a small window
|
|
190 ;; if the search moves outside what is currently on the screen.
|
|
191 (slow-terminal-mode (and (<= baud-rate search-slow-speed)
|
|
192 (> (window-height)
|
|
193 (* 4 search-slow-window-lines))))
|
|
194 ;; t means a small window is currently in use.
|
|
195 (small-window nil) ;if t, using a small window
|
|
196 ;; These variables preserve information from the small window
|
|
197 ;; through exit from the save-window-excursion.
|
|
198 (found-point nil)
|
|
199 (found-start nil)
|
|
200 ;; Point is at one end of the last match.
|
|
201 ;; This variable records the other end of that match.
|
|
202 (other-end nil)
|
|
203 ;; Value of point at start of search,
|
|
204 ;; for moving the cursor back on quitting.
|
|
205 (opoint (point))
|
|
206 (inhibit-quit t) ;Prevent ^G from quitting, so we can read it.
|
|
207 ;; The screen we're working on; if this changes, we exit isearch.
|
|
208 (screen (if (fboundp 'selected-screen) (selected-screen))))
|
|
209
|
|
210 (isearch-push-state)
|
|
211 (save-window-excursion
|
|
212 (catch 'search-done
|
|
213 (while t
|
|
214 (or (and (numberp unread-command-char) (>= unread-command-char 0))
|
|
215 (progn
|
|
216 (or (input-pending-p)
|
|
217 (isearch-message))
|
|
218 (if (and slow-terminal-mode
|
|
219 (not (or small-window (pos-visible-in-window-p))))
|
|
220 (progn
|
|
221 (setq small-window t)
|
|
222 (setq found-point (point))
|
|
223 (move-to-window-line 0)
|
|
224 (let ((window-min-height 1))
|
|
225 (split-window nil (if (< search-slow-window-lines 0)
|
|
226 (1+ (- search-slow-window-lines))
|
|
227 (- (window-height)
|
|
228 (1+ search-slow-window-lines)))))
|
|
229 (if (< search-slow-window-lines 0)
|
|
230 (progn (vertical-motion (- 1 search-slow-window-lines))
|
|
231 (set-window-start (next-window) (point))
|
|
232 (set-window-hscroll (next-window)
|
|
233 (window-hscroll))
|
|
234 (set-window-hscroll (selected-window) 0))
|
|
235 (other-window 1))
|
|
236 (goto-char found-point)))))
|
|
237 (let ((char (if quit-flag
|
|
238 ?\C-g
|
|
239 (read-event))))
|
|
240 (setq quit-flag nil liberalized nil yank-flag nil)
|
|
241 (cond ((and (or (not (integerp char))
|
|
242 (and (>= char 128)
|
|
243 (not (= char search-ring-advance-char))
|
|
244 (not (= char search-ring-retreat-char))))
|
|
245 search-exit-option)
|
|
246 (setq unread-command-char char)
|
|
247 (throw 'search-done t))
|
|
248
|
|
249 ;; If the user switches to a different screen, exit.
|
|
250 ((not (eq screen last-event-screen))
|
|
251 (setq unread-command-char char)
|
|
252 (throw 'search-done t))
|
|
253
|
|
254 ((eq char search-exit-char)
|
|
255 ;; RET means exit search normally.
|
|
256 ;; Except, if first thing typed, it means do nonincremental
|
|
257 (if (= 0 (length search-string))
|
|
258 (nonincremental-search forward regexp))
|
|
259 (throw 'search-done t))
|
|
260 ((= char ?\C-g)
|
|
261 ;; ^G means the user tried to quit.
|
|
262 (ding)
|
|
263 (discard-input)
|
|
264 (if success
|
|
265 ;; If search is successful, move back to starting point
|
|
266 ;; and really do quit.
|
|
267 (progn (goto-char opoint)
|
|
268 (signal 'quit nil))
|
|
269 ;; If search is failing, rub out until it is once more
|
|
270 ;; successful.
|
|
271 (while (not success) (isearch-pop))))
|
|
272 ((or (eq char search-repeat-char)
|
|
273 (eq char search-reverse-char))
|
|
274 (if (eq forward (eq char search-repeat-char))
|
|
275 ;; C-s in forward or C-r in reverse.
|
|
276 (if (equal search-string "")
|
|
277 ;; If search string is empty, use last one.
|
|
278 (isearch-get-string-from-ring)
|
|
279 ;; If already have what to search for, repeat it.
|
|
280 (or success
|
|
281 (progn (goto-char (if forward (point-min) (point-max)))
|
|
282 (setq wrapped t))))
|
|
283 ;; C-s in reverse or C-r in forward, change direction.
|
|
284 (setq forward (not forward)))
|
|
285 (setq barrier (point)) ; For subsequent \| if regexp.
|
|
286 (setq success t)
|
|
287 (or (equal search-string "")
|
|
288 (progn
|
|
289 ;; If repeating a search that found an empty string,
|
|
290 ;; ensure we advance. Test history to make sure we
|
|
291 ;; actually have done a search already; otherwise,
|
|
292 ;; the match data will be random.
|
|
293 (if (and (cdr history)
|
|
294 (= (match-end 0) (match-beginning 0)))
|
|
295 (forward-char (if forward 1 -1)))
|
|
296 (isearch-search)))
|
|
297 (isearch-push-state))
|
|
298 ((= char search-delete-char)
|
|
299 ;; Rubout means discard last input item and move point
|
|
300 ;; back. If buffer is empty, just beep.
|
|
301 (if (null (cdr history))
|
|
302 (ding)
|
|
303 (isearch-pop)))
|
|
304 ((= char search-ring-advance-char)
|
|
305 (isearch-pop)
|
|
306 (if regexp
|
|
307 (let ((length (length regexp-search-ring)))
|
|
308 (if (zerop length)
|
|
309 ()
|
|
310 (setq regexp-search-ring-yank-pointer
|
|
311 (nthcdr (% (+ 1 (- length (length regexp-search-ring-yank-pointer)))
|
|
312 length)
|
|
313 regexp-search-ring))
|
|
314 (isearch-get-string-from-ring)))
|
|
315 (let ((length (length search-ring)))
|
|
316 (if (zerop length)
|
|
317 ()
|
|
318 (setq search-ring-yank-pointer
|
|
319 (nthcdr (% (+ 1 (- length (length search-ring-yank-pointer)))
|
|
320 length)
|
|
321 search-ring))
|
|
322 (isearch-get-string-from-ring))))
|
|
323 (isearch-push-state)
|
|
324 (isearch-search))
|
|
325 ((= char search-ring-retreat-char)
|
|
326 (isearch-pop)
|
|
327 (if regexp
|
|
328 (let ((length (length regexp-search-ring)))
|
|
329 (if (zerop length)
|
|
330 ()
|
|
331 (setq regexp-search-ring-yank-pointer
|
|
332 (nthcdr (% (+ (- length (length regexp-search-ring-yank-pointer))
|
|
333 (1- length))
|
|
334 length)
|
|
335 regexp-search-ring))
|
|
336 (isearch-get-string-from-ring)))
|
|
337 (let ((length (length search-ring)))
|
|
338 (if (zerop length)
|
|
339 ()
|
|
340 (setq search-ring-yank-pointer
|
|
341 (nthcdr (% (+ (- length (length search-ring-yank-pointer))
|
|
342 (1- length))
|
|
343 length)
|
|
344 search-ring))
|
|
345 (isearch-get-string-from-ring))))
|
|
346 (isearch-push-state)
|
|
347 (isearch-search))
|
|
348 (t
|
|
349 (cond ((or (eq char search-yank-word-char)
|
|
350 (eq char search-yank-line-char))
|
|
351 ;; ^W means gobble next word from buffer.
|
|
352 ;; ^Y means gobble rest of line from buffer.
|
|
353 (let ((word (save-excursion
|
|
354 (and (not forward) other-end
|
|
355 (goto-char other-end))
|
|
356 (buffer-substring
|
|
357 (point)
|
|
358 (save-excursion
|
|
359 (if (eq char search-yank-line-char)
|
|
360 (end-of-line)
|
|
361 (forward-word 1))
|
|
362 (point))))))
|
|
363 (if regexp
|
|
364 (setq word (regexp-quote word)))
|
|
365 (setq search-string (concat search-string word)
|
|
366 search-message
|
|
367 (concat search-message
|
|
368 (mapconcat 'text-char-description
|
|
369 word ""))
|
|
370 ;; Don't move cursor in reverse search.
|
|
371 yank-flag t)))
|
|
372 ;; Any other control char =>
|
|
373 ;; unread it and exit the search normally.
|
|
374 ((and search-exit-option
|
|
375 (/= char search-quote-char)
|
|
376 (or (>= char ?\177)
|
|
377 (and (< char ? )
|
|
378 (/= char ?\t)
|
|
379 (/= char ?\n))))
|
|
380 (setq unread-command-char char)
|
|
381 (throw 'search-done t))
|
|
382 (t
|
|
383 ;; Any other character => add it to the
|
|
384 ;; search string and search.
|
|
385 (cond ((= char search-quote-char)
|
|
386 (setq char (read-quoted-char
|
|
387 (isearch-message t))))
|
|
388 ((= char ?\r)
|
|
389 ;; RET translates to newline.
|
|
390 (setq char ?\n)))
|
|
391 (setq search-string (concat search-string
|
|
392 (char-to-string char))
|
|
393 search-message (concat search-message
|
|
394 (text-char-description char))
|
|
395 uppercase-flag (or uppercase-flag
|
|
396 (not (= char (downcase char)))))))
|
|
397 (if (and (not success)
|
|
398 ;; unsuccessful regexp search may become
|
|
399 ;; successful by addition of characters which
|
|
400 ;; make search-string valid
|
|
401 (not regexp))
|
|
402 nil
|
|
403 ;; Check for chars that can make a regexp more liberal.
|
|
404 ;; They can make a regexp match sooner
|
|
405 ;; or make it succeed instead of failing.
|
|
406 ;; So go back to place last successful search started
|
|
407 ;; or to the last ^S/^R (barrier), whichever is nearer.
|
|
408 (and regexp history
|
|
409 (cond ((and (memq char '(?* ??))
|
|
410 ;; Don't treat *, ? as special
|
|
411 ;; within [] or after \.
|
|
412 (not (nth 6 (car history))))
|
|
413 (setq liberalized t)
|
|
414 ;; This used to use element 2
|
|
415 ;; in a reverse search, but it seems that 5
|
|
416 ;; (which is the end of the old match)
|
|
417 ;; is better in that case too.
|
|
418 (let ((cs (nth 5 ; old other-end.
|
|
419 (car (cdr history)))))
|
|
420 ;; (car history) is after last search;
|
|
421 ;; (car (cdr history)) is from before it.
|
|
422 (setq cs (or cs barrier))
|
|
423 (goto-char
|
|
424 (if forward
|
|
425 (max cs barrier)
|
|
426 (min cs barrier)))))
|
|
427 ((eq char ?\|)
|
|
428 (setq liberalized t)
|
|
429 (goto-char barrier))))
|
|
430 ;; Turn off case-sensitivity if string requests it.
|
|
431 (let ((case-fold-search
|
|
432 (and case-fold-search
|
|
433 (not (and uppercase-flag
|
|
434 search-upper-case)))))
|
|
435 ;; In reverse search, adding stuff at
|
|
436 ;; the end may cause zero or many more chars to be
|
|
437 ;; matched, in the string following point.
|
|
438 ;; Allow all those possibilities without moving point as
|
|
439 ;; long as the match does not extend past search origin.
|
|
440 (if (and (not forward) (not liberalized)
|
|
441 (condition-case ()
|
|
442 (looking-at (if regexp search-string
|
|
443 (regexp-quote search-string)))
|
|
444 (error nil))
|
|
445 (or yank-flag
|
|
446 ;; Used to have (min opoint barrier)
|
|
447 ;; instead of barrier.
|
|
448 ;; This lost when wrapping.
|
|
449 (<= (match-end 0) barrier)))
|
|
450 (setq success t invalid-regexp nil
|
|
451 other-end (match-end 0))
|
|
452 ;; Not regexp, not reverse, or no match at point.
|
|
453 (if (and other-end (not liberalized))
|
|
454 (goto-char (if forward other-end
|
|
455 ;; Used to have opoint inside the min.
|
|
456 ;; This lost when wrapping.
|
|
457 (min barrier (1+ other-end)))))
|
|
458 (isearch-search))))
|
|
459 (isearch-push-state))))
|
|
460 (if op-fun (funcall op-fun))))
|
|
461 (setq found-start (window-start (selected-window)))
|
|
462 (setq found-point (point)))
|
|
463 (if (> (length search-string) 0)
|
|
464 (if (and regexp (not (member search-string regexp-search-ring)))
|
|
465 (progn
|
|
466 (setq regexp-search-ring (cons (cons search-string uppercase-flag)
|
|
467 regexp-search-ring)
|
|
468 regexp-search-ring-yank-pointer regexp-search-ring)
|
|
469 (if (> (length regexp-search-ring) regexp-search-ring-max)
|
|
470 (setcdr (nthcdr (1- search-ring-max) regexp-search-ring) nil)))
|
|
471 (if (not (member search-string search-ring))
|
|
472 (progn
|
|
473 (setq search-ring (cons (cons search-string uppercase-flag)
|
|
474 search-ring)
|
|
475 search-ring-yank-pointer search-ring)
|
|
476 (if (> (length search-ring) search-ring-max)
|
|
477 (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
|
|
478 ;; If we displayed a single-line window, set point in this window.
|
|
479 (if small-window
|
|
480 (goto-char found-point))
|
|
481 ;; If there was movement, mark the starting position.
|
|
482 ;; Maybe should test difference between and set mark iff > threshold.
|
|
483 (if (/= (point) opoint)
|
|
484 (push-mark opoint)
|
|
485 (message ""))
|
|
486 (or small-window
|
|
487 ;; Exiting the save-window-excursion clobbers this; restore it.
|
|
488 (set-window-start (selected-window) found-start t))))
|
|
489
|
|
490 (defun isearch-message (&optional c-q-hack ellipsis)
|
|
491 ;; If about to search, and previous search regexp was invalid,
|
|
492 ;; check that it still is. If it is valid now,
|
|
493 ;; let the message we display while searching say that it is valid.
|
|
494 (and invalid-regexp ellipsis
|
|
495 (condition-case ()
|
|
496 (progn (re-search-forward search-string (point) t)
|
|
497 (setq invalid-regexp nil))
|
|
498 (error nil)))
|
|
499 ;; If currently failing, display no ellipsis.
|
|
500 (or success (setq ellipsis nil))
|
|
501 (let ((m (concat (if success "" "failing ")
|
|
502 (if wrapped "wrapped ")
|
|
503 (if (or (not case-fold-search)
|
|
504 (and uppercase-flag search-upper-case))
|
|
505 "case-sensitive ")
|
|
506 (if regexp "regexp " "")
|
|
507 "I-search"
|
|
508 (if forward ": " " backward: ")
|
|
509 search-message
|
|
510 (if c-q-hack "^Q" "")
|
|
511 (if invalid-regexp
|
|
512 (concat " [" invalid-regexp "]")
|
|
513 ""))))
|
|
514 (aset m 0 (upcase (aref m 0)))
|
|
515 (let ((cursor-in-echo-area ellipsis))
|
|
516 (if c-q-hack m (message "%s" m)))))
|
|
517
|
|
518 ;; Get the search string from the "front" of the ring of previous searches.
|
|
519 (defun isearch-get-string-from-ring ()
|
|
520 (let ((elt (car (if regexp
|
|
521 (or regexp-search-ring-yank-pointer regexp-search-ring)
|
|
522 (or search-ring-yank-pointer search-ring)))))
|
|
523 ;; ELT describes the most recent search or where we have rotated the ring.
|
|
524 (if elt
|
|
525 (setq search-string (car elt)
|
|
526 uppercase-flag (cdr elt))
|
|
527 (setq search-string "" uppercase-flag nil)))
|
|
528 ;; Let's give this one the benefit of the doubt.
|
|
529 (setq invalid-regexp nil)
|
|
530 (setq search-message (mapconcat 'text-char-description search-string "")))
|
|
531
|
|
532 (defun isearch-pop ()
|
|
533 (setq history (cdr history))
|
|
534 (let ((cmd (car history)))
|
|
535 (setq search-string (car cmd)
|
|
536 search-message (car (cdr cmd))
|
|
537 success (nth 3 cmd)
|
|
538 forward (nth 4 cmd)
|
|
539 other-end (nth 5 cmd)
|
|
540 invalid-regexp (nth 6 cmd)
|
|
541 wrapped (nth 7 cmd)
|
|
542 barrier (nth 8 cmd)
|
|
543 uppercase-flag (nth 9 cmd))
|
|
544 (goto-char (car (cdr (cdr cmd))))))
|
|
545
|
|
546 (defun isearch-push-state ()
|
|
547 (setq history (cons (list search-string search-message (point)
|
|
548 success forward other-end invalid-regexp
|
|
549 wrapped barrier uppercase-flag)
|
|
550 history)))
|
|
551
|
|
552 (defun isearch-search ()
|
|
553 (let ((case-fold-search
|
|
554 (and case-fold-search
|
|
555 (not (and uppercase-flag
|
|
556 search-upper-case)))))
|
|
557 (isearch-message nil t)
|
|
558 (condition-case lossage
|
|
559 (let ((inhibit-quit nil))
|
|
560 (if regexp (setq invalid-regexp nil))
|
|
561 (setq success
|
|
562 (funcall
|
|
563 (if regexp
|
|
564 (if forward 're-search-forward 're-search-backward)
|
|
565 (if forward 'search-forward 'search-backward))
|
|
566 search-string nil t))
|
|
567 (if success
|
|
568 (setq other-end
|
|
569 (if forward (match-beginning 0) (match-end 0)))))
|
|
570 (quit (setq unread-command-char ?\C-g)
|
|
571 (setq success nil))
|
|
572 (invalid-regexp (setq invalid-regexp (car (cdr lossage)))
|
|
573 (if (string-match "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
|
|
574 invalid-regexp)
|
|
575 (setq invalid-regexp "incomplete input"))))
|
|
576 (if success
|
|
577 nil
|
|
578 ;; Ding if failed this time after succeeding last time.
|
|
579 (and (nth 3 (car history))
|
|
580 (ding))
|
|
581 (goto-char (nth 2 (car history))))))
|
|
582
|
|
583 ;; This is called from incremental-search
|
|
584 ;; if the first input character is the exit character.
|
|
585 ;; The interactive-arg-reader uses free variables `forward' and `regexp'
|
|
586 ;; which are bound by `incremental-search'.
|
|
587
|
|
588 ;; We store the search string in `search-string'
|
|
589 ;; which has been bound already by `incremental-search'
|
|
590 ;; so that, when we exit, it is copied into `search-last-string'.
|
|
591
|
|
592 (defun nonincremental-search (forward regexp)
|
|
593 (let (message char function string inhibit-quit)
|
|
594 (let ((cursor-in-echo-area t))
|
|
595 ;; Prompt assuming not word search,
|
|
596 (setq message (if regexp
|
|
597 (if forward "Regexp search: "
|
|
598 "Regexp search backward: ")
|
|
599 (if forward "Search: " "Search backward: ")))
|
|
600 (message "%s" message)
|
|
601 ;; Read 1 char and switch to word search if it is ^W.
|
|
602 (setq char (read-event)))
|
|
603 (if (and (numberp char) (eq char search-yank-word-char))
|
|
604 (setq message (if forward "Word search: " "Word search backward: "))
|
|
605 ;; Otherwise let that 1 char be part of the search string.
|
|
606 (setq unread-command-char char))
|
|
607 (setq function
|
|
608 (if (eq char search-yank-word-char)
|
|
609 (if forward 'word-search-forward 'word-search-backward)
|
|
610 (if regexp
|
|
611 (if forward 're-search-forward 're-search-backward)
|
|
612 (if forward 'search-forward 'search-backward))))
|
|
613 ;; Read the search string with corrected prompt.
|
|
614 (setq string (read-string message))
|
|
615 ;; Empty means use default.
|
|
616 (if (= 0 (length string))
|
|
617 (setq string search-last-string)
|
|
618 ;; Set last search string now so it is set even if we fail.
|
|
619 (setq search-last-string string))
|
|
620 ;; Since we used the minibuffer, we should be available for redo.
|
|
621 (setq command-history (cons (list function string) command-history))
|
|
622 ;; Go ahead and search.
|
|
623 (funcall function string)))
|