aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1992-09-14 22:31:47 +0000
committerRichard M. Stallman1992-09-14 22:31:47 +0000
commit082005103aea5d73c38eb73fe510c184987c6ea0 (patch)
tree2d8c26c4b91287e78f23450f02cb808dc7d53d6c
parent3005da00b926340ae41df29ce170f5b331d0a6c4 (diff)
downloademacs-082005103aea5d73c38eb73fe510c184987c6ea0.tar.gz
emacs-082005103aea5d73c38eb73fe510c184987c6ea0.zip
*** empty log message ***
-rw-r--r--lisp/isearch.el1365
1 files changed, 877 insertions, 488 deletions
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 0a0fc946be1..8542cd9beb8 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1,11 +1,13 @@
1;; isearch-mode.el --- incremental search minor mode. 1;; Incremental search minor mode.
2
3;; Copyright (C) 1992 Free Software Foundation, Inc. 2;; Copyright (C) 1992 Free Software Foundation, Inc.
4 3
5;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu> 4;; LCD Archive Entry:
6;; Version: 1.2 5;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu
6;; |A minor mode replacement for isearch.el.
7;; |$Date: 92/09/14 16:26:02 $|$Revision: 1.4 $|~/modes/isearch-mode.el
7 8
8;; This file is part of GNU Emacs. 9;; This file is not yet part of GNU Emacs, but it is based almost
10;; entirely on isearch.el which is part of GNU Emacs.
9 11
10;; GNU Emacs is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY. No author or distributor 13;; but WITHOUT ANY WARRANTY. No author or distributor
@@ -22,8 +24,6 @@
22;; file named COPYING. Among other things, the copyright notice 24;; file named COPYING. Among other things, the copyright notice
23;; and this notice must be preserved on all copies. 25;; and this notice must be preserved on all copies.
24 26
25;;; Commentary:
26
27;;;==================================================================== 27;;;====================================================================
28;; Instructions 28;; Instructions
29 29
@@ -39,48 +39,105 @@
39;; (fset 'isearch 'isearch-mode) 39;; (fset 'isearch 'isearch-mode)
40;; (autoload 'isearch-mode "isearch-mode") 40;; (autoload 'isearch-mode "isearch-mode")
41 41
42;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
43;; isearch-mode behaves modally and does not return until the search
44;; is completed. It uses a recursive-edit to behave this way. Note:
45;; gnus does it wrong: (call-interactively 'isearch-forward).
46
47;; If any package you use invokes isearching non-interactively to get
48;; the modal behavior described above, you must use the redefinitions
49;; of isearch-forward, etc. found in this file instead of those in
50;; loaddefs.el. The simplest way to ensure this is to just load
51;; isearch-mode explicitly in your .emacs instead of using the above
52;; fset and autoload.
53
54;; (load "isearch-mode")
55
42;; The key bindings active within isearch-mode are defined below in 56;; The key bindings active within isearch-mode are defined below in
43;; `isearch-mode-map' and `isearch-mode-meta-map' which are given 57;; `isearch-mode-map' which is given bindings close to the default
44;; bindings close to the default characters of isearch.el for 58;; characters of the original isearch.el. With `isearch-mode',
45;; version 19. With `isearch-mode', however, you can bind 59;; however, you can bind multi-character keys and it should be easier
46;; multi-character keys and it should be easier to add new commands. 60;; to add new commands. One bug though: keys with meta-prefix cannot
47 61;; be longer than two chars. Also see minibuffer-local-isearch-map
48;; Note to epoch and emacs version 19 users: isearch-mode should 62;; for bindings active during `isearch-edit-string'.
49;; work even if you switch windows with the mouse. However, if 63
50;; you isearch in a buffer that is also displayed in another window, 64;; Note to emacs version 19 users: isearch-mode should work even if
51;; when you switch to that other window you will still be in 65;; you switch windows with the mouse, in which case isearch-mode is
52;; isearch mode but not necessarily in the right state for it to work. 66;; terminated automatically before the switch. This is true of lemacs
53;; So ... don't do it unless you are in an experimental mood. 67;; too, with a few more cleanups I've neglected in this release.
54;; You can also experiment with the window-local-variable routines 68;; No one has supplied patches for epoch yet.
55;; contained in this package but not yet used. 69
56;; Also, I am not sure what happens when you return to an isearching 70;; The search ring and completion commands automatically put you in
57;; buffer; ideally, the echo area should redisplay the searching status. 71;; the minibuffer to edit the string. This gives you a chance to
58;; A select-window-hook might be useful. 72;; modify the search string before executing the search. There are
59 73;; three commands to terminate the editing: C-s and C-r exit the
60;;; Change Log: 74;; minibuffer and search forward and reverse respectively, while C-m
75;; exits and does a nonincremental search.
76
77;; Exiting immediately from isearch uses isearch-edit-string instead
78;; of nonincremental-search, if search-nonincremental-instead is non-nil.
79;; The name of this option should probably be changed if we decide to
80;; keep the behavior. No point in forcing nonincremental search until
81;; the last possible moment.
82
83;; TODO
84;; - Integrate the emacs 19 generalized commmand history.
85;; - Think about incorporating query-replace.
86;; - Hooks and options for failed search.
61 87
62;;;==================================================================== 88;;;====================================================================
63 89;;; Change History
64;;; Revision 1.2 92/05/27 11:33:57 liberte 90
65;;; Several new commands and features have been added. Emacs version 91;;; $Header: /import/kaplan/kaplan/liberte/Isearch/RCS/isearch-mode.el,v 1.4 92/09/14 16:26:02 liberte Exp Locker: liberte $
66;;; 19 has a search ring, which is supported here. Other fixes found 92;;; $Log: isearch-mode.el,v $
67;;; in the version 19 isearch are included here. Also see variables 93;;; Revision 1.4 92/09/14 16:26:02 liberte
68;;; search-caps-disable-folding, search-nonincremental-instead, 94;;; Added prefix args to isearch-forward, etc. to switch between
69;;; search-whitespace-regexp, and commands isearch-toggle-regexp, 95;;; string and regular expression searching.
70;;; isearch-edit-string, 96;;; Added some support for lemacs.
71;;; 97;;; Added general isearch-highlight option - but only for lemacs so far.
72;;; Semi-modal searching is supported, using a recursive edit. If 98;;; Added support for frame switching in emacs 19.
73;;; isearching is started non-interactively by calling one of the 99;;; Added word search option to isearch-edit-string.
74;;; isearch commands (e.g. isearch-forward), it does not return 100;;; Renamed isearch-quit to isearch-abort.
75;;; until the search is completed. You should still be able switch 101;;; Numerous changes to comments and doc strings.
76;;; buffers, so be careful not to get things confused.
77;;; 102;;;
103;;; Revision 1.3 92/06/29 13:10:08 liberte
104;;; Moved modal isearch-mode handling into isearch-mode.
105;;; Got rid of buffer-local isearch variables.
106;;; isearch-edit-string used by ring adjustments, completion, and
107;;; nonincremental searching. C-s and C-r are additional exit commands.
108;;; Renamed all regex to regexp.
109;;; Got rid of found-start and found-point globals.
110;;; Generalized handling of upper-case chars.
111
112;;; Revision 1.2 92/05/27 11:33:57 liberte
113;;; Emacs version 19 has a search ring, which is supported here.
114;;; Other fixes found in the version 19 isearch are included here.
115;;;
116;;; Also see variables search-caps-disable-folding,
117;;; search-nonincremental-instead, search-whitespace-regexp, and
118;;; commands isearch-toggle-regexp, isearch-edit-string.
119;;;
120;;; semi-modal isearching is supported.
78 121
79;;; Changes for 1.1 122;;; Changes for 1.1
80;;; 3/18/92 Fixed invalid-regexp. 123;;; 3/18/92 Fixed invalid-regexp.
81;;; 3/18/92 Fixed yanking in regexps. 124;;; 3/18/92 Fixed yanking in regexps.
82 125
83;;; Code: 126
127
128;;;=========================================================================
129;;; Emacs features
130
131;; isearch-mode takes advantage of the features provided by several
132;; different versions of emacs. Rather than testing the version of
133;; emacs, several constants are defined, one for each of the features.
134;; Each of the tests below must work on any version of emacs.
135;; (Perhaps provide and featurep could be used for this purpose.)
136
137(defconst isearch-frames-exist nil) ;; emacs 19
138(defconst isearch-pre-command-hook-exists (boundp 'pre-command-hook)) ;; lemacs
139(defconst isearch-events-exist nil) ;; lemacs
140
84 141
85;;;========================================================================= 142;;;=========================================================================
86;;; The following, defined in loaddefs.el, are still used with isearch-mode. 143;;; The following, defined in loaddefs.el, are still used with isearch-mode.
@@ -111,180 +168,202 @@
111 168
112(defvar search-caps-disable-folding t 169(defvar search-caps-disable-folding t
113 "*If non-nil, upper case chars disable case fold searching. 170 "*If non-nil, upper case chars disable case fold searching.
114This does not yet apply to yanked strings, however.") 171That is, upper and lower case chars must match exactly.
172This applies no matter where the chars come from, but does not
173apply to chars prefixed with \\, for regexps.
174If this value is 'not-yanks, yanked text is always downcased.")
115 175
116(defvar search-nonincremental-instead t 176(defvar search-nonincremental-instead t
117 "*If non-nil, do a nonincremental search instead if exiting immediately. 177 "*If non-nil, do a nonincremental search instead if exiting immediately.
118The default value of t reflects the default behavior of old 178Actually, `isearch-edit-string' is called to let you enter the search
119isearch.") 179string, and RET terminates editing and does a nonincremental search.")
120 180
121(defconst search-whitespace-regexp "\\s-+" 181(defconst search-whitespace-regexp "\\s-+"
122 "*If non-nil, regular expression to match a sequence of whitespace chars. 182 "*If non-nil, regular expression to match a sequence of whitespace chars.
123You might want to use something like \"[ \\t\\r\\n]+\" instead.") 183You might want to use something like \"[ \\t\\r\\n]+\" instead.")
124 184
185(defvar search-highlight nil
186 "*Whether isearch and query-replace should highlight the text which
187currently matches the search-string.")
188
189
190(defvar isearch-mode-hook nil
191 "Function(s) to call after starting up an incremental search.")
192
193(defvar isearch-mode-end-hook nil
194 "Function(s) to call after terminating an incremental search.")
195
125;;;================================================================== 196;;;==================================================================
126;;; Search ring. 197;;; Search ring.
127;;; "regex" == "regexp". One should become the standard term.
128 198
129(defvar search-ring nil 199(defvar search-ring nil
130 "List of search string sequences.") 200 "List of search string sequences.")
131(defvar regex-search-ring nil ;; Is `regex' the new spelling? 201(defvar regexp-search-ring nil
132 "List of regular expression search string sequences.") 202 "List of regular expression search string sequences.")
133 203
134(defconst search-ring-max 16 204(defconst search-ring-max 16
135 "*Maximum length of search ring before oldest elements are thrown away.") 205 "*Maximum length of search ring before oldest elements are thrown away.")
136(defconst regex-search-ring-max 16 206(defconst regexp-search-ring-max 16
137 "*Maximum length of regex search ring before oldest elements are thrown away.") 207 "*Maximum length of regexp search ring before oldest elements are thrown away.")
138 208
139(defvar search-ring-yank-pointer nil 209(defvar search-ring-yank-pointer nil
140 "The tail of the search ring whose car is the last thing searched for.") 210 "The tail of the search ring whose car is the last thing searched for.")
141(defvar regex-search-ring-yank-pointer nil 211(defvar regexp-search-ring-yank-pointer nil
142 "The tail of the regular expression search ring whose car is the last 212 "The tail of the regular expression search ring whose car is the last
143thing searched for.") 213thing searched for.")
144 214
215(defvar search-ring-update nil
216 "*Non-nil if advancing or retreating in the search ring should cause search.
217Default value, nil, means edit the string instead.")
218
145;;;==================================================== 219;;;====================================================
146;;; Define isearch-mode keymap. 220;;; Define isearch-mode keymap.
147 221
148(defvar isearch-mode-map nil 222(defvar isearch-mode-map nil
149 "Keymap for isearch-mode.") 223 "Keymap for isearch-mode.")
150 224
151(defvar isearch-mode-meta-map nil 225(or isearch-mode-map
152 "Keymap for isearch-mode for keys with meta char prefix.") 226 (let* ((i 0)
153 227 (map (make-keymap))
154 228 (len (length map)))
155;; To handle meta char prefix keys, define another full keymap. 229
156;; The same must be done for any other prefix keys. 230 ;; Control chars, by default, end isearch mode transparently.
157;; It would be simpler to disable to global keymap, and/or 231 (while (< i ?\ )
158;; have a default local key binding for any key not otherwise bound. 232 (define-key map (make-string 1 i) 'isearch-other-control-char)
159(if isearch-mode-meta-map 233 (setq i (1+ i)))
160 nil 234
161 (setq isearch-mode-meta-map 235 ;; Printing chars extend the selection by default.
162 (list 'keymap (make-vector 128 'isearch-other-meta-char))) 236 ;; This assumes that all remaining chars are printable.
163 (define-key isearch-mode-meta-map "n" 'isearch-ring-advance) 237 (while (< i len)
164 (define-key isearch-mode-meta-map "p" 'isearch-ring-retreat) 238 (define-key map (make-string 1 i) 'isearch-printing-char)
165 (define-key isearch-mode-meta-map " " 'isearch-whitespace-chars) 239 (setq i (1+ i)))
166;for regexps 240
167 241 ;; Several non-printing chars change the searching behavior.
168;; (define-key isearch-mode-meta-map "?" nil) ; my help key is M-? 242 (define-key map "\C-s" 'isearch-repeat-forward)
169 ) 243 (define-key map "\C-r" 'isearch-repeat-backward)
170 244 (define-key map "\177" 'isearch-delete-char)
171(if isearch-mode-map 245 (define-key map "\C-g" 'isearch-abort)
172 nil
173 (let ((i 0)
174
175 ;; Printing chars extend the selection by default.
176 (array (make-vector 128 'isearch-printing-char)))
177
178 ;; Non-printing chars by default suspend isearch mode transparently
179 (while (< i ?\ )
180 (aset array i 'isearch-other-control-char)
181 (setq i (1+ i)))
182
183 (setq i ?A)
184 (while (<= i ?Z)
185 (aset array i 'isearch-upper-case-char)
186 (setq i (1+ i)))
187
188 (setq isearch-mode-map (list 'keymap array))
189
190 ;; You can reenable global keys by unbinding them locally.
191
192 ;; For the help char this doesnt work quite as expected because
193 ;; isearch-mode is not a major mode, and the echo area is not
194 ;; restored after the help command.
195 ;; Also, we should not assume that the help-command is on C-h.
196 ;; If it is not, and the prefix is not the meta-char, we would
197 ;; have to create another map for its prefix.
198; (define-key isearch-mode-map "\C-h" nil)
199
200 ;; Several non-printing chars change the searching behavior.
201 (define-key isearch-mode-map "\C-s" 'isearch-repeat-forward)
202 (define-key isearch-mode-map "\C-r" 'isearch-repeat-backward)
203 (define-key isearch-mode-map "\177" 'isearch-delete-char)
204 (define-key isearch-mode-map "\C-g" 'isearch-quit)
205 246
206 247 (define-key map "\C-q" 'isearch-quote-char)
207 (define-key isearch-mode-map "\C-q" 'isearch-quote-char) 248
208 249 ;; (define-key map "\r" 'isearch-return-char)
209 ;; (define-key isearch-mode-map "\r" 'isearch-return-char) 250 ;; For version 19, RET (C-m) terminates search and LFD (C-j) matches eol.
210 ;; For version 19, CR (C-m) terminates search and LFD (C-j) matches eol. 251 ;; We could make this conditional.
211 (define-key isearch-mode-map "\r" 'isearch-exit) 252 (define-key map "\r" 'isearch-exit)
212 (define-key isearch-mode-map "\C-j" 'isearch-printing-char) 253 (define-key map "\C-j" 'isearch-printing-char)
254 (define-key map "\t" 'isearch-printing-char)
255 (define-key map " " 'isearch-whitespace-chars)
213 256
257 (define-key map "\C-w" 'isearch-yank-word)
258 (define-key map "\C-y" 'isearch-yank-line)
259
260 ;; Define keys for regexp chars * ? |.
261 ;; Nothing special for + because it matches at least once.
262 (define-key map "*" 'isearch-*-char)
263 (define-key map "?" 'isearch-*-char)
264 (define-key map "|" 'isearch-|-char)
265
266 ;; You can reenable global keys by binding them locally to nil.
267 ;; For the help char this doesnt work quite as expected because
268 ;; isearch-mode is not a major mode. Also the echo area is not
269 ;; restored after the help command while isearch-mode is
270 ;; still active. Furthermore, we should not assume that the
271 ;; help-command is on C-h. But here is how it would be done:
272 ;; (define-key map "\C-h" nil)
273
274 ;; Instead bind C-h to special help command for isearch-mode.
275 (define-key map "\C-h" 'isearch-mode-help)
276
277 ;; To handle local bindings with meta char prefix keys, define
278 ;; another full keymap. This must be done for any other prefix
279 ;; keys as well, one full keymap per char of the prefix key. It
280 ;; would be simpler to disable the global keymap, and/or have a
281 ;; default local key binding for any key not otherwise bound.
282 (define-key map (char-to-string meta-prefix-char) (make-keymap))
283 (setq i 0)
284 (while (< i len)
285 (define-key map (char-to-string (+ 128 i)) ;; Needs to be generalized.
286 'isearch-other-meta-char)
287 (setq i (1+ i)))
288
289 (define-key map "\M-n" 'isearch-ring-advance)
290 (define-key map "\M-p" 'isearch-ring-retreat)
291 (define-key map "\M-\t" 'isearch-complete)
292
293 ;; For emacs 19, switching frames should terminate isearch-mode
294 (if isearch-frames-exist
295 (define-key map [switch-frame] 'isearch-switch-frame-handler))
296
297 (setq isearch-mode-map map)
298 ))
214 299
215 (define-key isearch-mode-map "\C-w" 'isearch-yank-word) 300;; Some bindings you may want to put in your isearch-mode-hook.
216 (define-key isearch-mode-map "\C-y" 'isearch-yank-line) 301;; Suggest some alternates...
302;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
303;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
217 304
218 (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
219 (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
220 305
221 ;; define keys for regexp chars * ? | 306(defvar minibuffer-local-isearch-map nil
222 (define-key isearch-mode-map "*" 'isearch-*-char) 307 "Keymap for editing isearch strings in the minibuffer.")
223 (define-key isearch-mode-map "?" 'isearch-*-char)
224 (define-key isearch-mode-map "|" 'isearch-|-char)
225 308
226 ;; Assumes meta-prefix-char is \e. 309(or minibuffer-local-isearch-map
227 ;; isearch-mode-meta-map must be a keymap before this. 310 (let ((map (copy-keymap minibuffer-local-map)))
228 (define-key isearch-mode-map "\e" isearch-mode-meta-map) 311 (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
229 )) 312 (define-key map "\M-n" 'isearch-ring-advance-edit)
313 (define-key map "\M-p" 'isearch-ring-retreat-edit)
314 (define-key map "\M-\t" 'isearch-complete-edit)
315 (define-key map "\C-s" 'isearch-forward-exit-minibuffer)
316 (define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
317 (setq minibuffer-local-isearch-map map)
318 ))
230 319
231;;;======================================================== 320;;;========================================================
232;; Internal variables declared globally for byte-compiler. 321;; Internal variables declared globally for byte-compiler.
233;; These are all made buffer-local during searching. 322;; These are all set with setq while isearching
234 323;; and bound locally while editing the search string.
235(defvar isearch-cmds nil 324
236 "Stack of search status sets.") 325(defvar isearch-forward nil) ; Searching in the forward direction.
237(defvar isearch-string "" 326(defvar isearch-regexp nil) ; Searching for a regexp.
238 "The current search string.") 327(defvar isearch-word nil) ; Searching for words.
239(defvar isearch-message "" 328
240 "The text-char-description version of isearch-string") 329(defvar isearch-cmds nil) ; Stack of search status sets.
241(defvar isearch-success t) 330(defvar isearch-string "") ; The current search string.
242(defvar isearch-forward nil) 331(defvar isearch-message "") ; text-char-description version of isearch-string
243(defvar isearch-other-end nil 332
244 "Start of last match if forward, end if backward.") 333(defvar isearch-success t) ; Searching is currently successful.
245(defvar isearch-invalid-regexp nil) 334(defvar isearch-invalid-regexp nil) ; Regexp not well formed.
246(defvar isearch-wrapped nil) 335(defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
336(defvar isearch-wrapped nil) ; Searching restarted from the top (bottom).
247(defvar isearch-barrier 0) 337(defvar isearch-barrier 0)
248 338
249(defvar isearch-regexp nil) 339(defvar isearch-case-fold-search nil) ; case-fold-search while searching.
250(defvar isearch-case-fold-search nil
251 "Value of case-fold-search while actually searching.")
252 340
253(defvar isearch-adjusted nil) 341(defvar isearch-adjusted nil)
254(defvar isearch-slow-terminal-mode nil) 342(defvar isearch-slow-terminal-mode nil)
255(defvar isearch-small-window nil 343;;; If t, using a small window.
256 "If t, using a small window.") 344(defvar isearch-small-window nil)
257(defvar isearch-found-point nil
258 "to restore point from a small window.")
259
260(defvar isearch-found-start nil
261 "This is the window-start value found by the search.")
262(defvar isearch-opoint 0) 345(defvar isearch-opoint 0)
263(defvar isearch-window-configuration nil 346;;; The window configuration active at the beginning of the search.
264 "The window configuration active at the beginning of the search.") 347(defvar isearch-window-configuration nil)
265(defvar isearch-old-local-map []) 348(defvar isearch-old-local-map nil)
266 349
267(defvar isearch-yank-flag nil 350;; Flag to indicate a yank occurred, so don't move the cursor.
268 "Flag to indicate a yank occurred, so don't move the cursor.") 351(defvar isearch-yank-flag nil)
269 352
270(defvar isearch-op-fun nil 353;;; A function to be called after each input character is processed.
271 "A function to be called after each input character is processed. 354;;; (It is not called after characters that exit the search.)
272(It is not called after characters that exit the search.) 355;;; It is only set from an optional argument to `isearch-mode'.
273It is only set from an optional argument to `isearch-mode'.") 356(defvar isearch-op-fun nil)
274 357
275;; This is a global variable to avoid byte-compile warnings. 358;;; Is isearch-mode in a recursive edit for modal searching.
276(defvar isearch-last-command-char -1 359(defvar isearch-recursive-edit nil)
277 "Last command char.")
278 360
279(defvar isearch-mode-hook nil 361;;; Should isearch be terminated after doing one search?
280 "List of functions to call after starting up an incremental search. 362(defvar isearch-nonincremental nil)
281See `isearch-modal' for an example. 363
282Set with `(setq isearch-mode-hook (cons 'myhook isearch-mode-hook)) 364;; New value of isearch-forward after isearch-edit-string.
283where myhook can be a function name or lambda expression.") 365(defvar isearch-new-forward nil)
284 366
285(defvar isearch-mode-end-hook nil
286 "List of functions to call after terminating an incremental search.
287See `isearch-mode-hook' for more details.")
288 367
289;;;============================================================== 368;;;==============================================================
290;; Minor-mode-alist changes - kind of redundant with the 369;; Minor-mode-alist changes - kind of redundant with the
@@ -294,117 +373,107 @@ See `isearch-mode-hook' for more details.")
294 (nconc minor-mode-alist 373 (nconc minor-mode-alist
295 (list '(isearch-mode isearch-mode)))) 374 (list '(isearch-mode isearch-mode))))
296 375
297(defvar isearch-mode nil) 376(defvar isearch-mode nil) ;; Name of the minor mode, if non-nil.
298(make-variable-buffer-local 'isearch-mode) 377(make-variable-buffer-local 'isearch-mode)
299 378
300;;;=============================================================== 379;;;===============================================================
301;;; Entry points to isearch-mode. 380;;; Entry points to isearch-mode.
302;;; These four functions should be moved to loaddefs.el 381;;; These four functions should replace those in loaddefs.el
382;;; An alternative is to fset isearch-forward etc to isearch-mode,
383;;; and look at this-command to set the options accordingly.
303 384
304(defun isearch-forward () 385(defun isearch-forward (&optional regexp-p)
305 "\ 386 "\
306Do incremental search forward. 387Do incremental search forward.
388With a prefix argument, do an incremental regular expression search instead.
389\\<isearch-mode-map>
307As you type characters, they add to the search string and are found. 390As you type characters, they add to the search string and are found.
391The following non-printing keys are bound in `isearch-mode-map'.
308 392
309\\<isearch-mode-map> 393Type \\[isearch-delete-char] to cancel characters from end of search string.
310Type \\[isearch-delete-char] to cancel characters from end of search
311string.
312Type \\[isearch-exit] to exit, leaving point at location found. 394Type \\[isearch-exit] to exit, leaving point at location found.
313Type \\[isearch-repeat-forward] to search again forward, 395Type LFD (C-j) to match end of line.
314\\[isearch-repeat-backward] to search again backward. 396Type \\[isearch-repeat-forward] to search again forward,\
315Type \\[isearch-toggle-regexp] to toggle regular expression with normal searching. 397 \\[isearch-repeat-backward] to search again backward.
316Type \\[isearch-yank-word] to yank word from buffer onto end of 398Type \\[isearch-yank-word] to yank word from buffer onto end of search\
317search string and search for it. 399 string and search for it.
318Type \\[isearch-yank-line] to yank rest of line onto end of search string, etc. 400Type \\[isearch-yank-line] to yank rest of line onto end of search string\
401 and search for it.
319Type \\[isearch-quote-char] to quote control character to search for it. 402Type \\[isearch-quote-char] to quote control character to search for it.
320Type C-j to match end of line. 403Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp.
404\\[isearch-abort] while searching or when search has failed cancels input\
405 back to what has
406 been found successfully.
407\\[isearch-abort] when search is successful aborts and moves point to\
408 starting point.
321 409
322Also supported is a search ring of the previous 16 search strings. 410Also supported is a search ring of the previous 16 search strings.
323Type \\[isearch-ring-advance] to search for the next item in the search ring. 411Type \\[isearch-ring-advance] to search for the next item in the search ring.
324Type \\[isearch-ring-retreat] to search for the previous item in the search ring. 412Type \\[isearch-ring-retreat] to search for the previous item in the search\
413 ring.
414Type \\[isearch-complete] to complete the search string using the search ring.
325 415
416The above keys, bound in `isearch-mode-map', are often controlled by
417 options; do M-x apropos on search-.* to find them.
326Other control and meta characters terminate the search 418Other control and meta characters terminate the search
327 and are then executed normally. 419 and are then executed normally (depending on `search-exit-option').
328 420
329\\[isearch-quit] while searching or when search has failed 421If this function is called non-interactively, it does not return to
330 cancels input back to what has been found successfully. 422the calling function until the search is done."
331\\[isearch-quit] when search is successful aborts and moves point to starting point.
332 423
333All of these keys are bound in `isearch-mode-map' and 424 (interactive "P")
334`isearch-mode-meta-map'. If `isearch-forward' is called 425 (isearch-mode t (not (null regexp-p)) nil (not (interactive-p))))
335non-interactively, it does not return to the calling function until
336the search is done."
337 (interactive)
338 (if (interactive-p)
339 (isearch-mode t)
340 (isearch-modal t)))
341 426
342(defun isearch-forward-regexp () 427(defun isearch-forward-regexp (&optional regexp-p)
343 "\ 428 "\
344Do incremental search forward for regular expression. 429Do incremental search forward for regular expression.
430With a prefix argument, do a regular string search instead.
345Like ordinary incremental search except that your input 431Like ordinary incremental search except that your input
346is treated as a regexp. See \\[isearch-forward] for more info." 432is treated as a regexp. See \\[isearch-forward] for more info."
347 (interactive) 433 (interactive)
348 (if (interactive-p) 434 (isearch-mode t (null regexp-p) nil (not (interactive-p))))
349 (isearch-mode t t)
350 (isearch-modal t t)))
351 435
352(defun isearch-backward () 436(defun isearch-backward (&optional regexp-p)
353 "\ 437 "\
354Do incremental search backward. 438Do incremental search backward.
439With a prefix argument, do a regular expression search instead.
355See \\[isearch-forward] for more information." 440See \\[isearch-forward] for more information."
356 (interactive) 441 (interactive)
357 (if (interactive-p) 442 (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p))))
358 (isearch-mode nil)
359 (isearch-modal nil)))
360 443
361(defun isearch-backward-regexp () 444(defun isearch-backward-regexp (&optional regexp-p)
362 "\ 445 "\
363Do incremental search backward for regular expression. 446Do incremental search backward for regular expression.
447With a prefix argument, do a regular string search instead.
364Like ordinary incremental search except that your input 448Like ordinary incremental search except that your input
365is treated as a regexp. See \\[isearch-forward] for more info." 449is treated as a regexp. See \\[isearch-forward] for more info."
366 (interactive) 450 (interactive)
367 (if (interactive-p) 451 (isearch-mode nil (null regexp-p) nil (not (interactive-p))))
368 (isearch-mode nil t) 452
369 (isearch-modal nil t))) 453
370 454(defun isearch-mode-help ()
371 455 (interactive)
372(defun isearch-modal (forward &optional regexp op-fun) 456 (describe-function 'isearch-forward)
373 ;; As an example of using the hooks, isearch-mode can be made 457 (isearch-update))
374 ;; modal (in the sense of not returning to the calling function
375 ;; until searching is completed) by entering a recursive-edit.
376 ;; This is used if the above functions are called non-interactively.
377 (let ((isearch-mode-hook
378 (cons (function (lambda () (recursive-edit)))
379 isearch-mode-hook))
380 (isearch-mode-end-hook
381 (cons (function (lambda () (exit-recursive-edit)))
382 isearch-mode-end-hook)))
383 (isearch-mode forward regexp op-fun)))
384 458
385 459
386;;;================================================================== 460;;;==================================================================
387;; isearch-mode only sets up incremental search for the minor mode. 461;; isearch-mode only sets up incremental search for the minor mode.
388;; All the work is done by the isearch-mode commands. 462;; All the work is done by the isearch-mode commands.
389 463
390(defun isearch-mode (forward &optional regexp op-fun) 464;; Not used yet:
465;;(defconst isearch-commands '(isearch-forward isearch-backward
466;; isearch-forward-regexp isearch-backward-regexp)
467;; "List of commands for which isearch-mode does not recursive-edit.")
468
469
470(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
391 "Start isearch minor mode. Called by isearch-forward, etc." 471 "Start isearch minor mode. Called by isearch-forward, etc."
392 ;; Make buffer-local variables for isearching.
393 ;; We really need window-local variables.
394 (mapcar
395 'make-local-variable
396 '(isearch-forward
397 isearch-regexp isearch-string isearch-message
398 isearch-case-fold-search
399 isearch-cmds isearch-success isearch-wrapped
400 isearch-barrier isearch-adjusted isearch-invalid-regexp
401 isearch-slow-terminal-mode isearch-other-end isearch-small-window
402 isearch-found-point isearch-found-start isearch-opoint
403 isearch-window-configuration isearch-old-local-map))
404 472
405 ;; Initialize global vars. 473 ;; Initialize global vars.
406 (setq isearch-forward forward 474 (setq isearch-forward forward
407 isearch-regexp regexp 475 isearch-regexp regexp
476 isearch-word word-p
408 isearch-op-fun op-fun 477 isearch-op-fun op-fun
409 isearch-case-fold-search case-fold-search 478 isearch-case-fold-search case-fold-search
410 isearch-string "" 479 isearch-string ""
@@ -416,20 +485,17 @@ is treated as a regexp. See \\[isearch-forward] for more info."
416 isearch-adjusted nil 485 isearch-adjusted nil
417 isearch-yank-flag nil 486 isearch-yank-flag nil
418 isearch-invalid-regexp nil 487 isearch-invalid-regexp nil
419 isearch-slow-terminal-mode (and (<= (baud-rate) search-slow-speed) 488 isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
420 (> (window-height) 489 (> (window-height)
421 (* 4 search-slow-window-lines))) 490 (* 4 search-slow-window-lines)))
422 isearch-other-end nil 491 isearch-other-end nil
423 isearch-small-window nil 492 isearch-small-window nil
424 isearch-found-point nil
425 493
426 isearch-found-start nil
427 isearch-opoint (point) 494 isearch-opoint (point)
428 isearch-window-configuration (current-window-configuration) 495 isearch-window-configuration (current-window-configuration)
429 isearch-old-local-map (current-local-map) 496 isearch-old-local-map (current-local-map))
430 497 (if isearch-pre-command-hook-exists
431;; inhibit-quit t 498 (add-hook 'pre-command-hook 'isearch-pre-command-hook))
432 )
433 (setq isearch-mode " Isearch") ;; forward? regexp? 499 (setq isearch-mode " Isearch") ;; forward? regexp?
434 (set-buffer-modified-p (buffer-modified-p)) ; update modeline 500 (set-buffer-modified-p (buffer-modified-p)) ; update modeline
435 501
@@ -438,6 +504,11 @@ is treated as a regexp. See \\[isearch-forward] for more info."
438 (use-local-map isearch-mode-map) 504 (use-local-map isearch-mode-map)
439 (isearch-update) 505 (isearch-update)
440 (run-hooks 'isearch-mode-hook) 506 (run-hooks 'isearch-mode-hook)
507
508 ;; isearch-mode can be made modal (in the sense of not returning to
509 ;; the calling function until searching is completed) by entering
510 ;; a recursive-edit and exiting it when done isearching.
511 (if recursive-edit (recursive-edit))
441 ) 512 )
442 513
443 514
@@ -446,16 +517,19 @@ is treated as a regexp. See \\[isearch-forward] for more info."
446 517
447(defun isearch-update () 518(defun isearch-update ()
448 ;; Called after each command to update the display. 519 ;; Called after each command to update the display.
449 (or unread-command-char 520 (if (if isearch-events-exist
521 (null unread-command-event)
522 (if isearch-frames-exist
523 (null unread-command-char)
524 (< unread-command-char 0)))
450 (progn 525 (progn
451 (if (not (input-pending-p)) 526 (if (not (input-pending-p))
452 (isearch-message)) 527 (isearch-message))
453 (if (and isearch-slow-terminal-mode 528 (if (and isearch-slow-terminal-mode
454 (not (or isearch-small-window 529 (not (or isearch-small-window
455 (pos-visible-in-window-p)))) 530 (pos-visible-in-window-p))))
456 (progn 531 (let ((found-point (point)))
457 (setq isearch-small-window t) 532 (setq isearch-small-window t)
458 (setq isearch-found-point (point))
459 (move-to-window-line 0) 533 (move-to-window-line 0)
460 (let ((window-min-height 1)) 534 (let ((window-min-height 1))
461 (split-window nil (if (< search-slow-window-lines 0) 535 (split-window nil (if (< search-slow-window-lines 0)
@@ -469,7 +543,12 @@ is treated as a regexp. See \\[isearch-forward] for more info."
469 (window-hscroll)) 543 (window-hscroll))
470 (set-window-hscroll (selected-window) 0)) 544 (set-window-hscroll (selected-window) 0))
471 (other-window 1)) 545 (other-window 1))
472 (goto-char isearch-found-point))))) 546 (goto-char found-point)))
547 (if isearch-other-end
548 (if (< isearch-other-end (point)) ; isearch-forward?
549 (isearch-highlight isearch-other-end (point))
550 (isearch-highlight (point) isearch-other-end)))
551 ))
473 (setq ;; quit-flag nil not for isearch-mode 552 (setq ;; quit-flag nil not for isearch-mode
474 isearch-adjusted nil 553 isearch-adjusted nil
475 isearch-yank-flag nil) 554 isearch-yank-flag nil)
@@ -479,55 +558,65 @@ is treated as a regexp. See \\[isearch-forward] for more info."
479(defun isearch-done () 558(defun isearch-done ()
480 ;; Called by all commands that terminate isearch-mode. 559 ;; Called by all commands that terminate isearch-mode.
481 (use-local-map isearch-old-local-map) 560 (use-local-map isearch-old-local-map)
482 (setq isearch-found-start (window-start (selected-window))) 561 ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
483 (setq isearch-found-point (point)) 562 (isearch-dehighlight t)
484 (set-window-configuration isearch-window-configuration) 563 (let ((found-start (window-start (selected-window)))
564 (found-point (point)))
565 (set-window-configuration isearch-window-configuration)
566
567 ;; If there was movement, mark the starting position.
568 ;; Maybe should test difference between and set mark iff > threshold.
569 (if (/= (point) isearch-opoint)
570 (push-mark isearch-opoint)
571 ;; (message "") why is this needed?
572 )
573 (if isearch-small-window
574 (goto-char found-point)
575 ;; Exiting the save-window-excursion clobbers window-start; restore it.
576 (set-window-start (selected-window) found-start t)))
577
578 (setq isearch-mode nil)
579 (set-buffer-modified-p (buffer-modified-p)) ;; update modeline
485 580
486 (if (> (length isearch-string) 0) 581 (if (> (length isearch-string) 0)
487 ;; Update the ring data. 582 ;; Update the ring data.
488 (if isearch-regexp 583 (if isearch-regexp
489 (if (not (setq regex-search-ring-yank-pointer 584 (if (not (setq regexp-search-ring-yank-pointer
490 (memq isearch-string regex-search-ring))) 585 ;; really need equal test instead of eq.
586 (isearch-member-equal
587 isearch-string regexp-search-ring)))
491 (progn 588 (progn
492 (setq regex-search-ring (cons isearch-string regex-search-ring) 589 (setq regexp-search-ring
493 regex-search-ring-yank-pointer regex-search-ring) 590 (cons isearch-string regexp-search-ring)
494 (if (> (length regex-search-ring) regex-search-ring-max) 591 regexp-search-ring-yank-pointer regexp-search-ring)
495 (setcdr (nthcdr (1- search-ring-max) regex-search-ring) 592 (if (> (length regexp-search-ring) regexp-search-ring-max)
593 (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
496 nil)))) 594 nil))))
497 (if (not (setq search-ring-yank-pointer 595 (if (not (setq search-ring-yank-pointer
498 (memq isearch-string search-ring))) 596 ;; really need equal test instead of eq.
597 (isearch-member-equal isearch-string search-ring)))
499 (progn 598 (progn
500 (setq search-ring (cons isearch-string search-ring) 599 (setq search-ring (cons isearch-string search-ring)
501 search-ring-yank-pointer search-ring) 600 search-ring-yank-pointer search-ring)
502 (if (> (length search-ring) search-ring-max) 601 (if (> (length search-ring) search-ring-max)
503 (setcdr (nthcdr (1- search-ring-max) search-ring) nil)))))) 602 (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
504 603
505 ;; If there was movement, mark the starting position.
506 ;; Maybe should test difference between and set mark iff > threshold.
507 (if (/= (point) isearch-opoint)
508 (push-mark isearch-opoint)
509 (message ""))
510 (if isearch-small-window
511 (goto-char isearch-found-point)
512 ;; Exiting the save-window-excursion clobbers window-start; restore it.
513 (set-window-start (selected-window) isearch-found-start t))
514
515 ;; Kill buffer-local variables for isearching
516 (mapcar
517 'kill-local-variable
518 '(isearch-forward
519 isearch-regexp isearch-string isearch-message
520 isearch-case-fold-search
521 isearch-cmds isearch-success isearch-wrapped
522 isearch-barrier isearch-adjusted isearch-invalid-regexp
523 isearch-slow-terminal-mode isearch-other-end isearch-small-window
524 isearch-found-point isearch-found-start isearch-opoint
525 isearch-window-configuration isearch-old-local-map))
526
527 (setq isearch-mode nil)
528 (set-buffer-modified-p (buffer-modified-p))
529 (run-hooks 'isearch-mode-end-hook) 604 (run-hooks 'isearch-mode-end-hook)
530 ) 605 (if isearch-recursive-edit (exit-recursive-edit)))
606
607;;;=======================================================
608;;; Switching buffers should first terminate isearch-mode.
609;;; This is done quite differently for each varient of emacs.
610;;; For lemacs, see Exiting in lemacs below
611
612;; For Emacs 19, the frame switch event is handled.
613(defun isearch-switch-frame-handler ()
614 (interactive) ;; Is this necessary?
615 ;; First terminate isearch-mode.
616 (isearch-done)
617 (select-frame (car (cdr (isearch-last-command-char)))))
618
619;;;========================================================
531 620
532 621
533;;;==================================================== 622;;;====================================================
@@ -537,40 +626,168 @@ is treated as a regexp. See \\[isearch-forward] for more info."
537 "Exit search normally. 626 "Exit search normally.
538However, if this is the first command after starting incremental 627However, if this is the first command after starting incremental
539search and `search-nonincremental-instead' is non-nil, do a 628search and `search-nonincremental-instead' is non-nil, do a
540nonincremental search instead." 629nonincremental search instead via `isearch-edit-string'."
541
542 (interactive) 630 (interactive)
543 (if (and search-nonincremental-instead 631 (if (and search-nonincremental-instead
544 (= 0 (length isearch-string))) 632 (= 0 (length isearch-string)))
545 (nonincremental-search isearch-forward isearch-regexp)) 633 (let ((isearch-nonincremental t))
634 (isearch-edit-string)))
546 (isearch-done)) 635 (isearch-done))
547 636
548 637
549(defun isearch-edit-string () 638(defun isearch-edit-string ()
550 "Edit the search string in the minibuffer and return to incremental search." 639 "Edit the search string in the minibuffer.
551 ;; This doesnt back up the search point. 640The following additional command keys are active while editing.
641\\<minibuffer-local-isearch-map>
642\\[exit-minibuffer] to resume incremental searching with the edited string.
643\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
644\\[isearch-forward-exit-minibuffer] to resume isearching forward.
645\\[isearch-backward-exit-minibuffer] to resume isearching backward.
646\\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring.
647\\[isearch-ring-retreat-edit] to replace the search string with the previou item in the search ring.
648\\[isearch-complete-edit] to complete the search string using the search ring.
649
650If first char entered is \\[isearch-yank-word], then do word search instead."
651
652 ;; This code is very hairy for several reasons, explained in the code.
653 ;; Mainly, isearch-mode must be terminated while editing and then restarted.
654 ;; If there were a way to catch any change of buffer from the minibuffer,
655 ;; this could be simplified greatly.
656 ;; Editing doesnt back up the search point. Should it?
552 (interactive) 657 (interactive)
553 (setq isearch-string (read-string (isearch-message-prefix) isearch-string) 658 (condition-case err
554 isearch-message (mapconcat 'text-char-description 659 (let ((minibuffer-local-map minibuffer-local-isearch-map)
555 isearch-string "")) 660 isearch-nonincremental ; should search nonincrementally?
556 (isearch-push-state) 661
557 (isearch-search) 662 ;; Locally bind all isearch global variables to protect them
558 (isearch-update)) 663 ;; from recursive isearching.
664 ;; isearch-string -message and -forward are not bound
665 ;; so they may be changed. Instead, save the values.
666 (isearch-new-string isearch-string)
667 (isearch-new-message isearch-message)
668 (isearch-new-forward isearch-forward)
669 (isearch-new-word isearch-word)
670
671 (isearch-regexp isearch-regexp)
672 (isearch-op-fun isearch-op-fun)
673 (isearch-cmds isearch-cmds)
674 (isearch-success isearch-success)
675 (isearch-wrapped isearch-wrapped)
676 (isearch-barrier isearch-barrier)
677 (isearch-adjusted isearch-adjusted)
678 (isearch-yank-flag isearch-yank-flag)
679 (isearch-invalid-regexp isearch-invalid-regexp)
680 (isearch-other-end isearch-other-end)
681 (isearch-opoint isearch-opoint)
682 (isearch-slow-terminal-mode isearch-slow-terminal-mode)
683 (isearch-small-window isearch-small-window)
684 (isearch-recursive-edit isearch-recursive-edit)
685 ;; Save current configuration so we can restore it here.
686 (isearch-window-configuration (current-window-configuration))
687 )
688
689 ;; Actually terminate isearching until editing is done.
690 ;; This is so that the user can do anything without failure,
691 ;; like switch buffers and start another isearch, and return.
692 (condition-case err
693 (isearch-done)
694 (exit nil)) ; was recursive editing
695
696 (isearch-message) ;; for read-char
697 (unwind-protect
698 (let* (;; Why does following read-char echo?
699 ;;(echo-keystrokes 0) ;; not needed with above message
700 (cursor-in-echo-area t)
701 (e (if isearch-events-exist (allocate-event) (read-char)))
702 ;; Binding minibuffer-history-symbol to nil is a work-around
703 ;; for some incompatibility with gmhist.
704 (minibuffer-history-symbol))
705 ;; If the first character the user types when we prompt them
706 ;; for a string is the yank-word character, then go into
707 ;; word-search mode. Otherwise unread that character and
708 ;; read a key the normal way.
709 ;; Word search does not apply (yet) to regexp searches,
710 ;; no check is made here.
711 (message (isearch-message-prefix nil nil t))
712 (if (eq 'isearch-yank-word
713 (lookup-key
714 isearch-mode-map
715 (char-to-string
716 (if isearch-events-exist
717 (or (event-to-character (next-command-event e)) 0)
718 e))))
719 (setq isearch-word t ;; so message-prefix is right
720 isearch-new-word t)
721 (isearch-unread e))
722 (setq isearch-new-string (read-string (isearch-message-prefix)
723 isearch-string)
724 isearch-new-message (mapconcat 'text-char-description
725 isearch-new-string "")))
726 ;; Always resume isearching by restarting it.
727 (isearch-mode isearch-forward
728 isearch-regexp
729 isearch-op-fun
730 isearch-recursive-edit
731 isearch-word)
732
733 ;; Copy new local values to isearch globals
734 (setq isearch-string isearch-new-string
735 isearch-message isearch-new-message
736 isearch-forward isearch-new-forward
737 isearch-word isearch-new-word))
738
739 ;; Empty isearch-string means use default.
740 (if (= 0 (length isearch-string))
741 (setq isearch-string (if isearch-regexp search-last-regexp
742 search-last-string))
743 ;; Set last search string now so it is set even if we fail.
744 (if search-last-regexp
745 (setq search-last-regexp isearch-string)
746 (setq search-last-string isearch-string)))
747
748 ;; Reinvoke the pending search.
749 (isearch-push-state)
750 (isearch-search)
751 (isearch-update)
752 (if isearch-nonincremental
753 (progn
754 ;; (sit-for 1) ;; needed if isearch-done does: (message "")
755 (isearch-done))))
559 756
757 (quit ; handle abort-recursive-edit
758 (isearch-abort) ;; outside of let to restore outside global values
759 )))
760
761(defun isearch-nonincremental-exit-minibuffer ()
762 (interactive)
763 (setq isearch-nonincremental t)
764 (exit-minibuffer))
765
766(defun isearch-forward-exit-minibuffer ()
767 (interactive)
768 (setq isearch-new-forward t)
769 (exit-minibuffer))
560 770
561(defun isearch-quit () 771(defun isearch-reverse-exit-minibuffer ()
562 "Quit incremental search mode if searching is successful.
563Otherwise, revert to previous successful search and continue searching."
564 (interactive) 772 (interactive)
565 (ding) 773 (setq isearch-new-forward nil)
774 (exit-minibuffer))
775
776
777(defun isearch-abort ()
778 "Abort incremental search mode if searching is successful, signalling quit.
779Otherwise, revert to previous successful search and continue searching.
780Use `isearch-exit' to quit without signalling."
781 (interactive)
782;; (ding) signal instead below, if quiting
566 (discard-input) 783 (discard-input)
567 (if isearch-success 784 (if isearch-success
568 ;; If search is successful, move back to starting point 785 ;; If search is successful, move back to starting point
569 ;; and really do quit. 786 ;; and really do quit.
570 (progn (goto-char isearch-opoint) 787 (progn (goto-char isearch-opoint)
571 (isearch-done)) ; exit and quit 788 (isearch-done) ; exit isearch
572 ;; If search is failing, rub out until it is once more 789 (signal 'quit '(isearch))) ; and pass on quit signal
573 ;; successful. 790 ;; If search is failing, rub out until it is once more successful.
574 (while (not isearch-success) (isearch-pop-state)) 791 (while (not isearch-success) (isearch-pop-state))
575 (isearch-update))) 792 (isearch-update)))
576 793
@@ -582,18 +799,16 @@ Otherwise, revert to previous successful search and continue searching."
582 (if (equal isearch-string "") 799 (if (equal isearch-string "")
583 ;; If search string is empty, use last one. 800 ;; If search string is empty, use last one.
584 (setq isearch-string 801 (setq isearch-string
585;; (if isearch-regexp
586;; search-last-regexp search-last-string)
587 (or (if isearch-regexp 802 (or (if isearch-regexp
588 (if regex-search-ring-yank-pointer 803 (if regexp-search-ring-yank-pointer
589 (car regex-search-ring-yank-pointer) 804 (car regexp-search-ring-yank-pointer)
590 (car regex-search-ring)) 805 (car regexp-search-ring))
591 (if search-ring-yank-pointer 806 (if search-ring-yank-pointer
592 (car search-ring-yank-pointer) 807 (car search-ring-yank-pointer)
593 (car search-ring))) 808 (car search-ring)))
594 "") 809 "")
595 isearch-message 810 isearch-message
596 (mapconcat 'text-char-description 811 (mapconcat 'isearch-text-char-description
597 isearch-string "")) 812 isearch-string ""))
598 ;; If already have what to search for, repeat it. 813 ;; If already have what to search for, repeat it.
599 (or isearch-success 814 (or isearch-success
@@ -631,6 +846,7 @@ Otherwise, revert to previous successful search and continue searching."
631 ;; The status stack is left unchanged. 846 ;; The status stack is left unchanged.
632 (interactive) 847 (interactive)
633 (setq isearch-regexp (not isearch-regexp)) 848 (setq isearch-regexp (not isearch-regexp))
849 (if isearch-regexp (setq isearch-word nil))
634 (isearch-update)) 850 (isearch-update))
635 851
636(defun isearch-delete-char () 852(defun isearch-delete-char ()
@@ -645,24 +861,28 @@ If no previous match was done, just beep."
645 861
646(defun isearch-yank (chunk) 862(defun isearch-yank (chunk)
647 ;; Helper for isearch-yank-word and isearch-yank-line 863 ;; Helper for isearch-yank-word and isearch-yank-line
648 (let ((word (save-excursion 864 (let ((string (save-excursion
649 (and (not isearch-forward) isearch-other-end 865 (and (not isearch-forward) isearch-other-end
650 (goto-char isearch-other-end)) 866 (goto-char isearch-other-end))
651 (buffer-substring 867 (buffer-substring
652 (point) 868 (point)
653 (save-excursion 869 (save-excursion
654 (cond 870 (cond
655 ((eq chunk 'word) 871 ((eq chunk 'word)
656 (forward-word 1)) 872 (forward-word 1))
657 ((eq chunk 'line) 873 ((eq chunk 'line)
658 (end-of-line))) 874 (end-of-line)))
659 (point)))))) 875 (point))))))
660 (if isearch-regexp (setq word (regexp-quote word))) 876 ;; Downcase the string if not supposed to case-fold yanked strings.
661 (setq isearch-string (concat isearch-string word) 877 (if (and isearch-case-fold-search
878 (eq 'not-yanks search-caps-disable-folding))
879 (setq string (downcase string)))
880 (if isearch-regexp (setq string (regexp-quote string)))
881 (setq isearch-string (concat isearch-string string)
662 isearch-message 882 isearch-message
663 (concat isearch-message 883 (concat isearch-message
664 (mapconcat 'text-char-description 884 (mapconcat 'isearch-text-char-description
665 word "")) 885 string ""))
666 ;; Don't move cursor in reverse search. 886 ;; Don't move cursor in reverse search.
667 isearch-yank-flag t)) 887 isearch-yank-flag t))
668 (isearch-search-and-update)) 888 (isearch-search-and-update))
@@ -717,10 +937,10 @@ If no previous match was done, just beep."
717 937
718 938
719;; *, ?, and | chars can make a regexp more liberal. 939;; *, ?, and | chars can make a regexp more liberal.
720;; They can make a regexp match sooner 940;; They can make a regexp match sooner or make it succeed instead of failing.
721;; or make it succeed instead of failing.
722;; So go back to place last successful search started 941;; So go back to place last successful search started
723;; or to the last ^S/^R (barrier), whichever is nearer. 942;; or to the last ^S/^R (barrier), whichever is nearer.
943;; + needs no special handling because the string must match at least once.
724 944
725(defun isearch-*-char () 945(defun isearch-*-char ()
726 "Handle * and ? specially in regexps." 946 "Handle * and ? specially in regexps."
@@ -740,10 +960,9 @@ If no previous match was done, just beep."
740 (if isearch-forward 960 (if isearch-forward
741 (max cs isearch-barrier) 961 (max cs isearch-barrier)
742 (min cs isearch-barrier)))))) 962 (min cs isearch-barrier))))))
743 (isearch-process-search-char last-command-char)) 963 (isearch-process-search-char (isearch-last-command-char)))
744 964
745 965
746
747(defun isearch-|-char () 966(defun isearch-|-char ()
748 "If in regexp search, jump to the barrier." 967 "If in regexp search, jump to the barrier."
749 (interactive) 968 (interactive)
@@ -751,20 +970,25 @@ If no previous match was done, just beep."
751 (progn 970 (progn
752 (setq isearch-adjusted t) 971 (setq isearch-adjusted t)
753 (goto-char isearch-barrier))) 972 (goto-char isearch-barrier)))
754 (isearch-process-search-char last-command-char)) 973 (isearch-process-search-char (isearch-last-command-char)))
755
756 974
757 975
758(defun isearch-other-control-char () 976(defun isearch-other-control-char ()
759 "Any other control char => unread it and exit the search normally. 977 "Any other control char => unread it and exit the search normally.
760But only if `search-exit-option' is non-nil." 978But only if `search-exit-option' is non-nil, the default.
979If it is the symbol `edit', the search string is edited in the minibuffer
980and the control char is unread so that it is applied to the editing."
761 (interactive) 981 (interactive)
762 (if search-exit-option 982 (cond
763 (progn 983 ((eq search-exit-option 'edit)
764 (setq unread-command-char last-command-char) 984 (isearch-unread (isearch-last-command-char))
765 (isearch-done)) 985 (isearch-edit-string))
766 ;; otherwise 986 (search-exit-option ;; any other non-nil value
767 (isearch-search-and-update))) 987 (isearch-unread (isearch-last-command-char))
988 (isearch-done))
989 (t ;; search-exit-option is nil
990 (isearch-process-search-char (isearch-last-command-char)))
991 ))
768 992
769 993
770(defun isearch-other-meta-char () 994(defun isearch-other-meta-char ()
@@ -774,13 +998,24 @@ But only if `search-exit-option' is non-nil."
774 ;; but here we use unwind-protect and command-execute since it is 998 ;; but here we use unwind-protect and command-execute since it is
775 ;; a multi-char key we would want to unread. 999 ;; a multi-char key we would want to unread.
776 (interactive) 1000 (interactive)
777 (if search-exit-option 1001 (cond
778 (unwind-protect 1002 (search-exit-option
779 (isearch-done) ;; this exits recursive edit 1003 (unwind-protect
780 ;; Reexecute the key. 1004 ;; Exit recursive edit and restore the outside keymap.
781 (command-execute (this-command-keys))) 1005 (isearch-done)
782 ;; otherwise 1006 ;; Reexecute the key with the outside keymap.
783 (isearch-search-and-update))) 1007 ;; Note: this doesnt work unless the entered key is the same
1008 ;; as some outside key since command-execute only takes whole keys.
1009 ;; So three character keys typically will not work!
1010 ;; Also, executing the command here may not work if isearch was
1011 ;; invoked non-interactively, since other input may be expected.
1012 ;; We also can't do isearch-edit-string as in -other-control-char.
1013 ;; because we need to set unread-command-key, if that existed.
1014 ;; So a new unread-command-key would solve all these problems.
1015 (command-execute (this-command-keys))))
1016 (t ;; otherwise nil
1017 (isearch-process-search-string (this-command-keys) (this-command-keys))
1018 )))
784 1019
785 1020
786(defun isearch-quote-char () 1021(defun isearch-quote-char ()
@@ -788,42 +1023,37 @@ But only if `search-exit-option' is non-nil."
788 (interactive) 1023 (interactive)
789 (isearch-process-search-char (read-quoted-char (isearch-message t)))) 1024 (isearch-process-search-char (read-quoted-char (isearch-message t))))
790 1025
791
792(defun isearch-return-char () 1026(defun isearch-return-char ()
793 "Convert return into newline for incremental search. 1027 "Convert return into newline for incremental search.
794Obsolete." 1028Obsolete."
795 (interactive) 1029 (interactive)
796 (isearch-process-search-char ?\n)) 1030 (isearch-process-search-char ?\n))
797 1031
798
799(defun isearch-printing-char () 1032(defun isearch-printing-char ()
800 "Any other printing character => add it to the search string and search." 1033 "Any other printing character => add it to the search string and search."
801 (interactive) 1034 (interactive)
802 (isearch-process-search-char last-command-char)) 1035 (isearch-process-search-char (isearch-last-command-char)))
803
804
805(defun isearch-upper-case-char ()
806 "Any upper case char => turn off case fold search for remainder of search."
807 ;; This feature only applies to interactively entered chars,
808 ;; but not yanked chars, repeat default searches, or search ring searches.
809 ;; Support for these should be easy to add.
810 (interactive)
811 (if search-caps-disable-folding
812 (setq isearch-case-fold-search nil))
813 (isearch-printing-char))
814 1036
815(defun isearch-whitespace-chars () 1037(defun isearch-whitespace-chars ()
816 "Match all whitespace chars, if in regexp mode." 1038 "Match all whitespace chars, if in regexp mode.
1039If not in regexp mode, activate word search."
817 (interactive) 1040 (interactive)
818 (if (and isearch-regexp search-whitespace-regexp) 1041 (if isearch-regexp
819 (isearch-process-search-string search-whitespace-regexp " ") 1042 (if search-whitespace-regexp
820 (isearch-other-meta-char))) 1043 (isearch-process-search-string search-whitespace-regexp " ")
1044 (isearch-printing-char))
1045 (progn
1046 ;; This way of doing word search doesnt correctly extend current search.
1047 ;; (setq isearch-word t)
1048 ;; (setq isearch-adjusted t)
1049 ;; (goto-char isearch-barrier)
1050 (isearch-printing-char))))
821 1051
822(defun isearch-process-search-char (char) 1052(defun isearch-process-search-char (char)
823 ;; Append the char to the search string, update the message and re-search. 1053 ;; Append the char to the search string, update the message and re-search.
824 (isearch-process-search-string (char-to-string char) 1054 (isearch-process-search-string
825 1055 (isearch-char-to-string char)
826 (text-char-description char))) 1056 (isearch-text-char-description char)))
827 1057
828(defun isearch-process-search-string (string message) 1058(defun isearch-process-search-string (string message)
829 (setq isearch-string (concat isearch-string string) 1059 (setq isearch-string (concat isearch-string string)
@@ -834,14 +1064,12 @@ Obsolete."
834;;=========================================================== 1064;;===========================================================
835;; Search Ring 1065;; Search Ring
836 1066
837(defun isearch-ring-adjust (advance) 1067(defun isearch-ring-adjust1 (advance)
838 ;; helper for isearch-ring-advance and isearch-ring-retreat 1068 ;; Helper for isearch-ring-adjust
839 (if (cdr isearch-cmds) 1069 (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
840 (isearch-pop-state))
841 (let* ((ring (if isearch-regexp regex-search-ring search-ring))
842 (length (length ring)) 1070 (length (length ring))
843 (yank-pointer-name (if isearch-regexp 1071 (yank-pointer-name (if isearch-regexp
844 'regex-search-ring-yank-pointer 1072 'regexp-search-ring-yank-pointer
845 'search-ring-yank-pointer)) 1073 'search-ring-yank-pointer))
846 (yank-pointer (eval yank-pointer-name))) 1074 (yank-pointer (eval yank-pointer-name)))
847 (if (zerop length) 1075 (if (zerop length)
@@ -852,14 +1080,25 @@ Obsolete."
852 (if advance (1- length) 1)) 1080 (if advance (1- length) 1))
853 length) ring))) 1081 length) ring)))
854 (setq isearch-string (car yank-pointer) 1082 (setq isearch-string (car yank-pointer)
855 isearch-message (mapconcat 'text-char-description 1083 isearch-message (mapconcat 'isearch-text-char-description
856 isearch-string "")))) 1084 isearch-string "")))))
1085
1086(defun isearch-ring-adjust (advance)
1087 ;; Helper for isearch-ring-advance and isearch-ring-retreat
1088 (if (cdr isearch-cmds) ;; is there more than one thing on stack?
1089 (isearch-pop-state))
1090 (isearch-ring-adjust1 advance)
857 (isearch-push-state) 1091 (isearch-push-state)
858 (isearch-search) 1092 (if search-ring-update
859 (isearch-update)) 1093 (progn
1094 (isearch-search)
1095 (isearch-update))
1096 (isearch-edit-string)
1097 ))
860 1098
861(defun isearch-ring-advance () 1099(defun isearch-ring-advance ()
862 "Advance to the next search string in the ring." 1100 "Advance to the next search string in the ring."
1101 ;; This could be more general to handle a prefix arg, but who would use it.
863 (interactive) 1102 (interactive)
864 (isearch-ring-adjust 'advance)) 1103 (isearch-ring-adjust 'advance))
865 1104
@@ -868,75 +1107,85 @@ Obsolete."
868 (interactive) 1107 (interactive)
869 (isearch-ring-adjust nil)) 1108 (isearch-ring-adjust nil))
870 1109
871 1110(defun isearch-ring-adjust-edit (advance)
872;;;============================================================= 1111 "Use the next or previous search string in the ring while in minibuffer."
873;; Window-local variables 1112 (isearch-ring-adjust1 advance)
874;; (not used yet - and maybe never) 1113 (erase-buffer)
875 1114 (insert isearch-string))
876(defvar window-local-variable-alist nil
877 "An alist of windows associated with window local variables and values.
878The cdr of each item is another alist of variables and values.")
879
880(defvar last-local-window nil)
881(defvar last-window-local-vars nil)
882
883(defun kill-window-local-variables ()
884 "Remove the old variable list, if any."
885 (setq window-local-variable-alist
886 (delq window-local-variable-alist
887 (assq (selected-window)
888 window-local-variable-alist))))
889 1115
890;; Assume that window-local variables are not buffer-local 1116(defun isearch-ring-advance-edit ()
891;; so we can delay storing until absolutely necessary. 1117 (interactive)
892 1118 (isearch-ring-adjust-edit 'advance))
893(defun store-window-local-variables (&rest vars-and-vals)
894 "Store the window local variables for selected window."
895 (setq last-local-window (selected-window))
896 (setq last-window-local-vars vars-and-vals))
897 1119
1120(defun isearch-ring-retreat-edit ()
1121 "Retreat to the previous search string in the ring while in the minibuffer."
1122 (interactive)
1123 (isearch-ring-adjust-edit nil))
1124
1125
1126(defun isearch-complete1 ()
1127 ;; Helper for isearch-complete and isearch-complete-edit
1128 ;; Return t if completion OK, nil if no completion exists.
1129 (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
1130 (alist (mapcar (function (lambda (string) (list string))) ring))
1131 (completion-ignore-case case-fold-search)
1132 (completion (try-completion isearch-string alist)))
1133 (cond
1134 ((eq completion t)
1135 ;; isearch-string stays the same
1136 t)
1137 ((or completion ; not nil, must be a string
1138 (= 0 (length isearch-string))) ; shouldnt have to say this
1139 (if (equal completion isearch-string) ;; no extension?
1140 (if completion-auto-help
1141 (with-output-to-temp-buffer "*Isearch completions*"
1142 (display-completion-list
1143 (all-completions isearch-string alist))))
1144 (setq isearch-string completion))
1145 t)
1146 (t
1147 (message "No completion") ; waits a second if in minibuffer
1148 nil))))
1149
1150(defun isearch-complete ()
1151 "Complete the search string from the strings on the search ring.
1152The completed string is then editable in the minibuffer.
1153If there is no completion possible, say so and continue searching."
1154 (interactive)
1155 (if (isearch-complete1)
1156 (isearch-edit-string)
1157 ;; else
1158 (sit-for 1)
1159 (isearch-update)))
898 1160
899(defun fetch-window-local-variables () 1161(defun isearch-complete-edit ()
900 "Fetch the window local variables for selected window. 1162 "Same as `isearch-complete' except in the minibuffer."
901Does nothing if the last store was for the same window." 1163 (interactive)
902 (if (not (eq (selected-window) last-local-window)) 1164 (setq isearch-string (buffer-string))
1165 (if (isearch-complete1)
903 (progn 1166 (progn
904 ;; First store the previous values. 1167 (erase-buffer)
905 (setq window-local-variable-alist 1168 (insert isearch-string))))
906 (cons (cons last-local-window
907 last-window-local-vars)
908 (delq window-local-variable-alist
909 (assq last-local-window
910 window-local-variable-alist))))
911 ;; Now fetch the values for the selected-window.
912 (setq last-local-window (selected-window))
913 (setq last-window-local-vars
914 (cdr (assq last-local-window window-local-variable-alist)))
915 (let ((vars-and-vals last-window-local-vars))
916 (while vars-and-vals
917 (set (car vars-and-vals) (car (cdr vars-and-vals)))
918 (setq vars-and-vals (cdr (cdr vars-and-vals))))))))
919
920 1169
921 1170
922;;;============================================================== 1171;;;==============================================================
923;; The search status stack (and isearch window-local variables, not used). 1172;; The search status stack (and isearch window-local variables, not used).
1173;; Need a structure for this.
924 1174
925(defun isearch-top-state () 1175(defun isearch-top-state ()
926;; (fetch-window-local-variables)
927 (let ((cmd (car isearch-cmds))) 1176 (let ((cmd (car isearch-cmds)))
928 (setq isearch-string (car cmd) 1177 (setq isearch-string (car cmd)
929 isearch-message (car (cdr cmd)) 1178 isearch-message (car (cdr cmd))
930 isearch-success (nth 3 cmd) 1179 isearch-success (nth 3 cmd)
931 isearch-forward (nth 4 cmd) 1180 isearch-forward (nth 4 cmd)
932 isearch-other-end (nth 5 cmd) 1181 isearch-other-end (nth 5 cmd)
933 isearch-invalid-regexp (nth 6 cmd) 1182 isearch-word (nth 6 cmd)
934 isearch-wrapped (nth 7 cmd) 1183 isearch-invalid-regexp (nth 7 cmd)
935 isearch-barrier (nth 8 cmd)) 1184 isearch-wrapped (nth 8 cmd)
1185 isearch-barrier (nth 9 cmd))
936 (goto-char (car (cdr (cdr cmd)))))) 1186 (goto-char (car (cdr (cdr cmd))))))
937 1187
938(defun isearch-pop-state () 1188(defun isearch-pop-state ()
939;; (fetch-window-local-variables)
940 (setq isearch-cmds (cdr isearch-cmds)) 1189 (setq isearch-cmds (cdr isearch-cmds))
941 (isearch-top-state) 1190 (isearch-top-state)
942 ) 1191 )
@@ -945,23 +1194,10 @@ Does nothing if the last store was for the same window."
945 (setq isearch-cmds 1194 (setq isearch-cmds
946 (cons (list isearch-string isearch-message (point) 1195 (cons (list isearch-string isearch-message (point)
947 isearch-success isearch-forward isearch-other-end 1196 isearch-success isearch-forward isearch-other-end
1197 isearch-word
948 isearch-invalid-regexp isearch-wrapped isearch-barrier) 1198 isearch-invalid-regexp isearch-wrapped isearch-barrier)
949 isearch-cmds))) 1199 isearch-cmds)))
950 1200
951(defun isearch-store-variables ()
952 (store-window-local-variables
953 'isearch-cmds isearch-cmds
954 'isearch-regexp isearch-regexp
955 'isearch-adjusted isearch-adjusted
956 'isearch-slow-terminal-mode isearch-slow-terminal-mode
957 'isearch-small-window isearch-small-window
958 'isearch-found-point isearch-found-point
959 'isearch-found-start isearch-found-start
960 'isearch-opoint isearch-opoint
961 'isearch-window-configuration isearch-window-configuration
962 'isearch-old-local-map isearch-old-local-map
963 ))
964
965 1201
966;;;================================================================== 1202;;;==================================================================
967;; Message string 1203;; Message string
@@ -970,13 +1206,13 @@ Does nothing if the last store was for the same window."
970 ;; Generate and print the message string. 1206 ;; Generate and print the message string.
971 (let ((cursor-in-echo-area ellipsis) 1207 (let ((cursor-in-echo-area ellipsis)
972 (m (concat 1208 (m (concat
973 (isearch-message-prefix c-q-hack ellipsis) 1209 (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
974 isearch-message 1210 isearch-message
975 (isearch-message-suffix c-q-hack ellipsis) 1211 (isearch-message-suffix c-q-hack ellipsis)
976 ))) 1212 )))
977 (if c-q-hack m (message "%s" m)))) 1213 (if c-q-hack m (message "%s" m))))
978 1214
979(defun isearch-message-prefix (&optional c-q-hack ellipsis) 1215(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
980 ;; If about to search, and previous search regexp was invalid, 1216 ;; If about to search, and previous search regexp was invalid,
981 ;; check that it still is. If it is valid now, 1217 ;; check that it still is. If it is valid now,
982 ;; let the message we display while searching say that it is valid. 1218 ;; let the message we display while searching say that it is valid.
@@ -989,8 +1225,9 @@ Does nothing if the last store was for the same window."
989 (or isearch-success (setq ellipsis nil)) 1225 (or isearch-success (setq ellipsis nil))
990 (let ((m (concat (if isearch-success "" "failing ") 1226 (let ((m (concat (if isearch-success "" "failing ")
991 (if isearch-wrapped "wrapped ") 1227 (if isearch-wrapped "wrapped ")
1228 (if isearch-word "word " "")
992 (if isearch-regexp "regexp " "") 1229 (if isearch-regexp "regexp " "")
993 "I-search" 1230 (if nonincremental "search" "I-search")
994 (if isearch-forward ": " " backward: ") 1231 (if isearch-forward ": " " backward: ")
995 ))) 1232 )))
996 (aset m 0 (upcase (aref m 0))) 1233 (aset m 0 (upcase (aref m 0)))
@@ -1010,21 +1247,28 @@ Does nothing if the last store was for the same window."
1010(defun isearch-search () 1247(defun isearch-search ()
1011 ;; Do the search with the current search string. 1248 ;; Do the search with the current search string.
1012 (isearch-message nil t) 1249 (isearch-message nil t)
1250 (if search-caps-disable-folding
1251 (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string)))
1013 (condition-case lossage 1252 (condition-case lossage
1014 (let ((inhibit-quit nil) 1253 (let ((inhibit-quit nil)
1015 (case-fold-search isearch-case-fold-search)) 1254 (case-fold-search isearch-case-fold-search))
1016 (if isearch-regexp (setq isearch-invalid-regexp nil)) 1255 (if isearch-regexp (setq isearch-invalid-regexp nil))
1017 (setq isearch-success 1256 (setq isearch-success
1018 (funcall 1257 (funcall
1019 (if isearch-regexp 1258 (cond (isearch-word
1020 (if isearch-forward 're-search-forward 're-search-backward) 1259 (if isearch-forward
1021 (if isearch-forward 'search-forward 'search-backward)) 1260 'word-search-forward 'word-search-backward))
1261 (isearch-regexp
1262 (if isearch-forward
1263 're-search-forward 're-search-backward))
1264 (t
1265 (if isearch-forward 'search-forward 'search-backward)))
1022 isearch-string nil t)) 1266 isearch-string nil t))
1023 (if isearch-success 1267 (if isearch-success
1024 (setq isearch-other-end 1268 (setq isearch-other-end
1025 (if isearch-forward (match-beginning 0) (match-end 0))))) 1269 (if isearch-forward (match-beginning 0) (match-end 0)))))
1026 1270
1027 (quit (setq unread-command-char ?\C-g) 1271 (quit (isearch-unread ?\C-g)
1028 (setq isearch-success nil)) 1272 (setq isearch-success nil))
1029 1273
1030 (invalid-regexp 1274 (invalid-regexp
@@ -1041,56 +1285,201 @@ Does nothing if the last store was for the same window."
1041 (ding)) 1285 (ding))
1042 (goto-char (nth 2 (car isearch-cmds))))) 1286 (goto-char (nth 2 (car isearch-cmds)))))
1043 1287
1288
1289
1290;;;========================================================
1291;;; Highlighting
1292
1293(defun isearch-highlight (begin end))
1294(defun isearch-dehighlight (totally))
1295
1296;; lemacs uses faces
1297'(progn
1298(defvar isearch-extent nil)
1299
1300(or (find-face 'isearch) ;; this face is initialized by x-faces.el
1301 (make-face 'isearch)) ;; since isearch is preloaded
1302
1303(defun isearch-lemacs-highlight (begin end)
1304 (if (null isearch-highlight)
1305 nil
1306 (if (and (extentp isearch-extent)
1307 (eq (extent-buffer isearch-extent) (current-buffer)))
1308 (set-extent-endpoints isearch-extent begin end)
1309 (if (and (extentp isearch-extent)
1310 (bufferp (extent-buffer isearch-extent))
1311 (buffer-name (extent-buffer isearch-extent)))
1312 (delete-extent isearch-extent))
1313 (setq isearch-extent (make-extent begin end (current-buffer))))
1314 (set-extent-face isearch-extent 'isearch)))
1315
1316(defun isearch-lemacs-dehighlight (totally)
1317 (if (and isearch-highlight isearch-extent)
1318 (if totally
1319 (let ((inhibit-quit t))
1320 (if (and (extentp isearch-extent)
1321 (bufferp (extent-buffer isearch-extent))
1322 (buffer-name (extent-buffer isearch-extent)))
1323 (delete-extent isearch-extent))
1324 (setq isearch-extent nil))
1325 (if (and (extentp isearch-extent)
1326 (bufferp (extent-buffer isearch-extent))
1327 (buffer-name (extent-buffer isearch-extent)))
1328 (set-extent-face isearch-extent 'default)
1329 (isearch-dehighlight t)))))
1330
1331(fset 'isearch-highlight (symbol-function 'isearch-lemacs-highlight))
1332(fset 'isearch-dehighlight (symbol-function 'isearch-lemacs-dehighlight))
1333)
1334
1335;;;===========================================================
1336;;; General utilities
1337
1338;; (fset 'isearch-member-equal (symbol-function 'member)) ; for emacs 19
1339
1340(defun isearch-member-equal (item list)
1341 "Return non-nil if ITEM is `equal' to some item in LIST.
1342Actually return the list whose car is that item."
1343 (while (and list (not (equal item (car list))))
1344 (setq list (cdr list)))
1345 list)
1346
1347
1348(defun isearch-no-upper-case-p (string)
1349 "Return t if there are no upper case chars in string.
1350But upper case chars preceeded by \\ (but not \\\\) do not count since they
1351have special meaning in a regexp."
1352 (let ((case-fold-search nil))
1353 (not (string-match "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]" string))))
1354
1355
1044;;;================================================= 1356;;;=================================================
1045;; This is called from incremental-search 1357;;; Special functions for lemacs events.
1046;; if the first input character is the exit character.
1047 1358
1048;; We store the search string in `isearch-string' 1359;; To quiet the byte-compiler.
1049;; which has been bound already by `isearch-search' 1360(defvar unread-command-event)
1050;; so that, when we exit, it is copied into `search-last-string'. 1361(defvar last-command-event)
1051 1362
1052(defun nonincremental-search (forward regexp) 1363(defun isearch-char-to-string (c)
1053 ;; This may be broken. Anyway, it could be replaced by the 1364 (if (integerp c)
1054 ;; isearch-edit-string command instead. 1365 (make-string 1 c)
1055 (setq isearch-forward forward 1366 (make-string 1 (event-to-character c))))
1056 isearch-regexp regexp) 1367
1057 (let (char function 1368(defun isearch-text-char-description (c)
1058 inhibit-quit 1369 (isearch-char-to-string c))
1059 (cursor-in-echo-area t)) 1370
1060 ;; Prompt assuming not word search, 1371(defun isearch-unread (char-or-event)
1061 (setq isearch-message 1372 ;; General function to unread a character or event.
1062 1373 (if isearch-events-exist
1063 (if isearch-regexp 1374 (setq unread-command-event char-or-event)
1064 1375 (setq unread-command-char char-or-event)))
1065 (if isearch-forward "Regexp search: " 1376
1066 "Regexp search backward: ") 1377(defun isearch-last-command-char ()
1067 (if isearch-forward "Search: " "Search backward: "))) 1378 ;; General function to return the last command character.
1068 (message "%s" isearch-message) 1379 (if isearch-events-exist
1069 ;; Read 1 char and switch to word search if it is ^W. 1380 last-command-event
1070 (setq char (read-char)) 1381 last-command-char))
1071 (if (eq char search-yank-word-char) 1382
1072 (setq isearch-message (if isearch-forward "Word search: " 1383
1073 1384
1074 "Word search backward: ")) 1385
1075 ;; Otherwise let that 1 char be part of the search string. 1386;;;========================================================
1076 (setq unread-command-char char)) 1387;;; Exiting in lemacs
1077 (setq function 1388
1078 (if (eq char search-yank-word-char) 1389;; This is a large amount of code to support automatic termination of
1079 (if isearch-forward 'word-search-forward 'word-search-backward) 1390;; isearch-mode when a command (however it is invoked) is not an
1080 (if isearch-regexp 1391;; isearch command, or the buffer is switched out from under
1081 (if isearch-forward 're-search-forward 're-search-backward) 1392;; isearch-mode. Only later versions of lemacs have the pre-command-hook.
1082 (if isearch-forward 'search-forward 'search-backward)))) 1393
1083 ;; Read the search string with corrected prompt. 1394;;(if isearch-pre-command-hook-exists
1084 (setq isearch-string (read-string isearch-message isearch-string)) 1395;;(progn
1085 ;; Empty means use default. 1396
1086 (if (= 0 (length isearch-string)) 1397;;;; This list must be modified whenever the available commands are modified.
1087 (setq isearch-string search-last-string) 1398;;(mapcar (function (lambda (command)
1088 ;; Set last search string now so it is set even if we fail. 1399;; (put command 'isearch-command t)))
1089 (setq search-last-string isearch-string)) 1400;; '(isearch-printing-char
1090 ;; Since we used the minibuffer, we should be available for redo. 1401;; isearch-return-char
1091 (setq command-history 1402;; isearch-repeat-forward
1092 1403;; isearch-repeat-backward
1093 (cons (list function isearch-string) command-history)) 1404;; isearch-delete-char
1094 ;; Go ahead and search. 1405;; isearch-abort
1095 (let ((case-fold-search isearch-case-fold-search)) 1406;; isearch-quote-char
1096 (funcall function isearch-string)))) 1407;; isearch-exit
1408;; isearch-printing-char
1409;; isearch-printing-char
1410;; isearch-yank-word
1411;; isearch-yank-line
1412;; isearch-*-char
1413;; isearch-*-char
1414;; isearch-|-char
1415;; isearch-toggle-regexp
1416;; isearch-edit-string
1417;; isearch-mode-help
1418;; isearch-ring-advance
1419;; isearch-ring-retreat
1420;; isearch-ring-advance-edit
1421;; isearch-ring-retreat-edit
1422;; isearch-whitespace-chars
1423;; isearch-complete
1424;; isearch-complete-edit
1425;; isearch-edit-string
1426;; isearch-toggle-regexp
1427;; ;; The following may not be needed since isearch-mode is off already.
1428;; isearch-forward-exit-minibuffer
1429;; isearch-reverse-exit-minibuffer
1430;; isearch-nonincremental-exit-minibuffer))
1431
1432;;(defun isearch-pre-command-hook ()
1433;; ;;
1434;; ;; For use as the value of `pre-command-hook' when isearch-mode is active.
1435;; ;; If the command about to be executed is not one of the isearch commands,
1436;; ;; then isearch-mode is turned off before that command is executed.
1437;; ;;
1438;; ;; If the command about to be executed is self-insert-command, or is a
1439;; ;; keyboard macro of a single key sequence which is bound to self-insert-
1440;; ;; command, then we add those chars to the search ring instead of inserting
1441;; ;; them in the buffer. In this way, the set of self-searching characters
1442;; ;; need not be exhaustively enumerated, but is derived from other maps.
1443;; ;;
1444;; (isearch-maybe-frob-keyboard-macros)
1445;; (if (and (symbolp this-command)
1446;; (get this-command 'isearch-command))
1447;; nil
1448;; (isearch-done)))
1449
1450;;(defun isearch-maybe-frob-keyboard-macros ()
1451;; ;;
1452;; ;; If the command about to be executed is `self-insert-command' then change
1453;; ;; the command to `isearch-printing-char' instead, meaning add the last-
1454;; ;; typed character to the search string.
1455;; ;;
1456;; ;; If `this-command' is a string or a vector (that is, a keyboard macro)
1457;; ;; and it contains only one command, which is bound to self-insert-command,
1458;; ;; then do the same thing as for self-inserting commands: arrange for that
1459;; ;; character to be added to the search string. If we didn't do this, then
1460;; ;; typing a compose sequence (a la x-compose.el) would terminate the search
1461;; ;; and insert the character, instead of searching for that character.
1462;; ;;
1463;; (cond ((eq this-command 'self-insert-command)
1464;; (setq this-command 'isearch-printing-char))
1465;; ((and (stringp this-command)
1466;; (eq (key-binding this-command) 'self-insert-command))
1467;; (setq last-command-char (aref this-command 0)
1468;; last-command-event (character-to-event last-command-char)
1469;; this-command 'isearch-printing-char))
1470;; ((and (vectorp this-command)
1471;; (eq (key-binding this-command) 'self-insert-command))
1472;; (let* ((desc (aref this-command 0))
1473;; (code (cond ((integerp desc) desc)
1474;; ((symbolp desc) (get desc character-set-property))
1475;; ((consp desc)
1476;; (and (null (cdr desc))
1477;; (get (car desc) character-set-property)))
1478;; (t nil))))
1479;; (if code
1480;; (setq last-command-char code
1481;; last-command-event (character-to-event last-command-char)
1482;; this-command 'isearch-printing-char))))
1483;; ))
1484
1485;;))