comparison lisp/isearch.el @ 56668:99e8e40ec202

Remove accidental changes of March 4. Fix backing up when a regexp isearch is made more general. Use symbolic accessor functions for isearch stack frames to make usage clearer. (search-whitespace-regexp): Made groups in documentation shy (as is the group in the default value). (isearch-fallback): New function, addresses problems with regexps liberalized by `\|', adds support for liberalization by `\}' (the general repetition construct), and incorporates behavior for `*'/`?'. (isearch-}-char): New command, calls `isearch-fallback' with arguments appropriate to a typed `}'. (isearch-*-char, isearch-|-char): Now just call `isearch-fallback' appropriately. (isearch-mode-map): Bind `}' to `isearch-}-char'. (isearch-string, isearch-message,string, isearch-point, isearch-success, isearch-forward-flag, isearch-other-end, isearch-word, isearch-invalid-regexp, isearch-wrapped, isearch-barrier, isearch-within-brackets, isearch-case-fold-search): New inline functions to read fields of a stack frame.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 14 Aug 2004 12:48:39 +0000
parents f0e5e08dd63e
children 1f4ff211cbeb
comparison
equal deleted inserted replaced
56667:00e5170987b5 56668:99e8e40ec202
151 :group 'isearch) 151 :group 'isearch)
152 152
153 (defcustom search-whitespace-regexp "\\(?:\\s-+\\)" 153 (defcustom search-whitespace-regexp "\\(?:\\s-+\\)"
154 "*If non-nil, regular expression to match a sequence of whitespace chars. 154 "*If non-nil, regular expression to match a sequence of whitespace chars.
155 This applies to regular expression incremental search. 155 This applies to regular expression incremental search.
156 You might want to use something like \"[ \\t\\r\\n]+\" instead. 156 You might want to use something like \"\\\\(?:[ \\t\\r\\n]+\\\\)\" instead.
157 In the Customization buffer, that is `[' followed by a space, 157 In the Customization buffer, that is `\\(?:[' followed by a space,
158 a tab, a carriage return (control-M), a newline, and `]+'." 158 a tab, a carriage return (control-M), a newline, and `]+\\)'."
159 :type 'regexp 159 :type 'regexp
160 :group 'isearch) 160 :group 'isearch)
161 161
162 (defcustom search-highlight t 162 (defcustom search-highlight t
163 "*Non-nil means incremental search highlights the current match." 163 "*Non-nil means incremental search highlights the current match."
296 (define-key map "\C-w" 'isearch-yank-word-or-char) 296 (define-key map "\C-w" 'isearch-yank-word-or-char)
297 (define-key map "\M-\C-w" 'isearch-del-char) 297 (define-key map "\M-\C-w" 'isearch-del-char)
298 (define-key map "\M-\C-y" 'isearch-yank-char) 298 (define-key map "\M-\C-y" 'isearch-yank-char)
299 (define-key map "\C-y" 'isearch-yank-line) 299 (define-key map "\C-y" 'isearch-yank-line)
300 300
301 ;; Define keys for regexp chars * ? |. 301 ;; Define keys for regexp chars * ? } |.
302 ;; Nothing special for + because it matches at least once. 302 ;; Nothing special for + because it matches at least once.
303 (define-key map "*" 'isearch-*-char) 303 (define-key map "*" 'isearch-*-char)
304 (define-key map "?" 'isearch-*-char) 304 (define-key map "?" 'isearch-*-char)
305 (define-key map "{" 'isearch-{-char) 305 (define-key map "}" 'isearch-}-char)
306 (define-key map "|" 'isearch-|-char) 306 (define-key map "|" 'isearch-|-char)
307 307
308 ;; Turned off because I find I expect to get the global definition--rms. 308 ;; Turned off because I find I expect to get the global definition--rms.
309 ;; ;; Instead bind C-h to special help command for isearch-mode. 309 ;; ;; Instead bind C-h to special help command for isearch-mode.
310 ;; (define-key map "\C-h" 'isearch-mode-help) 310 ;; (define-key map "\C-h" 'isearch-mode-help)
370 (defvar isearch-word nil) ; Searching for words. 370 (defvar isearch-word nil) ; Searching for words.
371 (defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible. 371 (defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible.
372 372
373 (defvar isearch-cmds nil 373 (defvar isearch-cmds nil
374 "Stack of search status sets. 374 "Stack of search status sets.
375 Each set is a list of the form: 375 Each set is a vector of the form:
376 (STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD 376 [STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD
377 INVALID-REGEXP WRAPPED BARRIER WITHIN-BRACKETS CASE-FOLD-SEARCH)") 377 INVALID-REGEXP WRAPPED BARRIER WITHIN-BRACKETS CASE-FOLD-SEARCH]")
378 378
379 (defvar isearch-string "") ; The current search string. 379 (defvar isearch-string "") ; The current search string.
380 (defvar isearch-message "") ; text-char-description version of isearch-string 380 (defvar isearch-message "") ; text-char-description version of isearch-string
381 381
382 (defvar isearch-success t) ; Searching is currently successful. 382 (defvar isearch-success t) ; Searching is currently successful.
770 ;; (interactive) ;; Is this necessary? 770 ;; (interactive) ;; Is this necessary?
771 ;; ;; First terminate isearch-mode. 771 ;; ;; First terminate isearch-mode.
772 ;; (isearch-done) 772 ;; (isearch-done)
773 ;; (isearch-clean-overlays) 773 ;; (isearch-clean-overlays)
774 ;; (handle-switch-frame (car (cdr last-command-char)))) 774 ;; (handle-switch-frame (car (cdr last-command-char))))
775
776
777 ;; The search status structure and stack.
778
779 (defsubst isearch-string (frame)
780 "Return the search string in FRAME."
781 (aref 0 frame))
782 (defsubst isearch-message-string (frame)
783 "Return the search string to display to the user in FRAME."
784 (aref 1 frame))
785 (defsubst isearch-point (frame)
786 "Return the point in FRAME."
787 (aref 2 frame))
788 (defsubst isearch-success (frame)
789 "Return the success flag in FRAME."
790 (aref 3 frame))
791 (defsubst isearch-forward-flag (frame)
792 "Return the searching-forward flag in FRAME."
793 (aref 4 frame))
794 (defsubst isearch-other-end (frame)
795 "Return the other end of the match in FRAME."
796 (aref 5 frame))
797 (defsubst isearch-word (frame)
798 "Return the search-by-word flag in FRAME."
799 (aref 6 frame))
800 (defsubst isearch-invalid-regexp (frame)
801 "Return the regexp error message in FRAME, or nil if its regexp is valid."
802 (aref 7 frame))
803 (defsubst isearch-wrapped (frame)
804 "Return the search-wrapped flag in FRAME."
805 (aref 8 frame))
806 (defsubst isearch-barrier (frame)
807 "Return the barrier value in FRAME."
808 (aref 9 frame))
809 (defsubst isearch-within-brackets (frame)
810 "Return the in-character-class flag in FRAME."
811 (aref 10 frame))
812 (defsubst isearch-case-fold-search (frame)
813 "Return the case-folding flag in FRAME."
814 (aref 11 frame))
815
816 (defun isearch-top-state ()
817 (let ((cmd (car isearch-cmds)))
818 (setq isearch-string (isearch-string cmd)
819 isearch-message (isearch-message-string cmd)
820 isearch-success (isearch-success cmd)
821 isearch-forward (isearch-forward-flag cmd)
822 isearch-other-end (isearch-other-end cmd)
823 isearch-word (isearch-word cmd)
824 isearch-invalid-regexp (isearch-invalid-regexp cmd)
825 isearch-wrapped (isearch-wrapped cmd)
826 isearch-barrier (isearch-barrier cmd)
827 isearch-within-brackets (isearch-within-brackets cmd)
828 isearch-case-fold-search (isearch-case-fold-search cmd))
829 (goto-char (isearch-point cmd))))
830
831 (defun isearch-pop-state ()
832 (setq isearch-cmds (cdr isearch-cmds))
833 (isearch-top-state))
834
835 (defun isearch-push-state ()
836 (setq isearch-cmds
837 (cons (vector isearch-string isearch-message (point)
838 isearch-success isearch-forward isearch-other-end
839 isearch-word
840 isearch-invalid-regexp isearch-wrapped isearch-barrier
841 isearch-within-brackets isearch-case-fold-search)
842 isearch-cmds)))
775 843
776 844
777 ;; Commands active while inside of the isearch minor mode. 845 ;; Commands active while inside of the isearch minor mode.
778 846
779 (defun isearch-exit () 847 (defun isearch-exit ()
1247 (isearch-push-state) 1315 (isearch-push-state)
1248 (if isearch-op-fun (funcall isearch-op-fun)) 1316 (if isearch-op-fun (funcall isearch-op-fun))
1249 (isearch-update)) 1317 (isearch-update))
1250 1318
1251 1319
1252 (defun isearch-{-char () 1320 ;; *, ?, }, and | chars can make a regexp more liberal.
1253 "Handle \{ specially in regexps."
1254 (interactive)
1255 (isearch-*-char t))
1256
1257 ;; *, ?, and | chars can make a regexp more liberal.
1258 ;; They can make a regexp match sooner or make it succeed instead of failing. 1321 ;; They can make a regexp match sooner or make it succeed instead of failing.
1259 ;; So go back to place last successful search started 1322 ;; So go back to place last successful search started
1260 ;; or to the last ^S/^R (barrier), whichever is nearer. 1323 ;; or to the last ^S/^R (barrier), whichever is nearer.
1261 ;; + needs no special handling because the string must match at least once. 1324 ;; + needs no special handling because the string must match at least once.
1262 1325
1263 (defun isearch-*-char (&optional want-backslash) 1326 (defun isearch-backslash (str)
1264 "Handle * and ? specially in regexps. 1327 "Return t if STR ends in an odd number of backslashes."
1265 When WANT-BACKSLASH is non-nil, do special handling for \{." 1328 (= (mod (- (length str) (string-match "\\\\*\\'" str)) 2) 1))
1266 (interactive) 1329
1267 (if isearch-regexp 1330 (defun isearch-fallback (want-backslash &optional allow-invalid to-barrier)
1268 (let ((idx (length isearch-string))) 1331 "Return point to previous successful match to allow regexp liberalization.
1269 (while (and (> idx 0) 1332 \\<isearch-mode-map>
1270 (eq (aref isearch-string (1- idx)) ?\\)) 1333 Respects \\[isearch-repeat-forward] and \\[isearch-repeat-backward] by
1271 (setq idx (1- idx))) 1334 stopping at `isearch-barrier' as needed.
1272 ;; * and ? are special when not preceded by \. 1335
1273 ;; { is special when it is preceded by \. 1336 Do nothing if a backslash is escaping the liberalizing character. If
1274 (when (= (mod (- (length isearch-string) idx) 2) 1337 WANT-BACKSLASH is non-nil, invert this behavior (for \\} and \\|).
1275 (if want-backslash 1 0)) 1338
1276 (setq isearch-adjusted t) 1339 Do nothing if regexp has recently been invalid unless optional ALLOW-INVALID
1277 ;; Get the isearch-other-end from before the last search. 1340 non-nil.
1278 ;; We want to start from there, 1341
1279 ;; so that we don't retreat farther than that. 1342 If optional TO-BARRIER non-nil, ignore previous matches and go exactly to the
1280 ;; (car isearch-cmds) is after last search; 1343 barrier."
1281 ;; (car (cdr isearch-cmds)) is from before it. 1344 ;; (eq (not a) (not b)) makes all non-nil values equivalent
1282 (let ((cs (nth 5 (car (cdr isearch-cmds))))) 1345 (when (and isearch-regexp (eq (not (isearch-backslash isearch-string))
1283 (setq cs (or cs isearch-barrier)) 1346 (not want-backslash))
1284 (goto-char 1347 ;; We have to check 2 stack frames because the last might be
1285 (if isearch-forward 1348 ;; invalid just because of a backslash.
1286 (max cs isearch-barrier) 1349 (or (not isearch-invalid-regexp)
1287 (min cs isearch-barrier))))))) 1350 (not (isearch-invalid-regexp (cadr isearch-cmds)))
1351 allow-invalid))
1352 (if to-barrier
1353 (progn (goto-char isearch-barrier)
1354 (setq isearch-adjusted t))
1355 (let* ((stack isearch-cmds)
1356 (previous (cdr stack)) ; lookbelow in the stack
1357 (frame (car stack)))
1358 ;; Walk down the stack looking for a valid regexp (as of course only
1359 ;; they can be the previous successful match); this conveniently
1360 ;; removes all bracket-sets and groups that might be in the way, as
1361 ;; well as partial \{\} constructs that the code below leaves behind.
1362 ;; Also skip over postfix operators -- though horrid,
1363 ;; 'ab?\{5,6\}+\{1,2\}*' is perfectly legal.
1364 (while (and previous
1365 (or (isearch-invalid-regexp frame)
1366 (let* ((string (isearch-string frame))
1367 (lchar (aref string (1- (length string)))))
1368 ;; The operators aren't always operators; check
1369 ;; backslashes. This doesn't handle the case of
1370 ;; operators at the beginning of the regexp not
1371 ;; being special, but then we should fall back to
1372 ;; the barrier anyway because it's all optional.
1373 (if (isearch-backslash
1374 (isearch-string (car previous)))
1375 (eq lchar ?\})
1376 (memq lchar '(?* ?? ?+))))))
1377 (setq stack previous previous (cdr previous) frame (car stack)))
1378 (when stack
1379 ;; `stack' now refers the most recent valid regexp that is not at
1380 ;; all optional in its last term. Now dig one level deeper and find
1381 ;; what matched before that.
1382 (let ((last-other-end (or (isearch-other-end (car previous))
1383 isearch-barrier)))
1384 (goto-char (if isearch-forward
1385 (max last-other-end isearch-barrier)
1386 (min last-other-end isearch-barrier)))
1387 (setq isearch-adjusted t))))))
1288 (isearch-process-search-char last-command-char)) 1388 (isearch-process-search-char last-command-char))
1289 1389
1290 1390 ;; * and ? are special when not preceded by \.
1391 (defun isearch-*-char ()
1392 "Maybe back up to handle * and ? specially in regexps."
1393 (interactive)
1394 (isearch-fallback nil))
1395
1396 ;; } is special when it is preceded by \.
1397 (defun isearch-}-char ()
1398 "Handle \\} specially in regexps."
1399 (interactive)
1400 (isearch-fallback t t))
1401
1402 ;; | is special when it is preceded by \.
1291 (defun isearch-|-char () 1403 (defun isearch-|-char ()
1292 "If in regexp search, jump to the barrier." 1404 "If in regexp search, jump to the barrier unless in a group."
1293 (interactive) 1405 (interactive)
1294 (if isearch-regexp 1406 (isearch-fallback t nil t))
1295 (progn
1296 (setq isearch-adjusted t)
1297 (goto-char isearch-barrier)))
1298 (isearch-process-search-char last-command-char))
1299 1407
1300 (defun isearch-unread-key-sequence (keylist) 1408 (defun isearch-unread-key-sequence (keylist)
1301 "Unread the given key-sequence KEYLIST. 1409 "Unread the given key-sequence KEYLIST.
1302 Scroll-bar or mode-line events are processed appropriately." 1410 Scroll-bar or mode-line events are processed appropriately."
1303 (cancel-kbd-macro-events) 1411 (cancel-kbd-macro-events)
1773 (progn 1881 (progn
1774 (delete-field) 1882 (delete-field)
1775 (insert isearch-string)))) 1883 (insert isearch-string))))
1776 1884
1777 1885
1778 ;; The search status stack (and isearch window-local variables, not used).
1779 ;; Need a structure for this.
1780
1781 (defun isearch-top-state ()
1782 (let ((cmd (car isearch-cmds)))
1783 (setq isearch-string (car cmd)
1784 isearch-message (car (cdr cmd))
1785 isearch-success (nth 3 cmd)
1786 isearch-forward (nth 4 cmd)
1787 isearch-other-end (nth 5 cmd)
1788 isearch-word (nth 6 cmd)
1789 isearch-invalid-regexp (nth 7 cmd)
1790 isearch-wrapped (nth 8 cmd)
1791 isearch-barrier (nth 9 cmd)
1792 isearch-within-brackets (nth 10 cmd)
1793 isearch-case-fold-search (nth 11 cmd))
1794 (goto-char (car (cdr (cdr cmd))))))
1795
1796 (defun isearch-pop-state ()
1797 (setq isearch-cmds (cdr isearch-cmds))
1798 (isearch-top-state))
1799
1800 (defun isearch-push-state ()
1801 (setq isearch-cmds
1802 (cons (list isearch-string isearch-message (point)
1803 isearch-success isearch-forward isearch-other-end
1804 isearch-word
1805 isearch-invalid-regexp isearch-wrapped isearch-barrier
1806 isearch-within-brackets isearch-case-fold-search)
1807 isearch-cmds)))
1808
1809
1810 ;; Message string 1886 ;; Message string
1811 1887
1812 (defun isearch-message (&optional c-q-hack ellipsis) 1888 (defun isearch-message (&optional c-q-hack ellipsis)
1813 ;; Generate and print the message string. 1889 ;; Generate and print the message string.
1814 (let ((cursor-in-echo-area ellipsis) 1890 (let ((cursor-in-echo-area ellipsis)
1934 (setq isearch-invalid-regexp (format "%s" lossage)))) 2010 (setq isearch-invalid-regexp (format "%s" lossage))))
1935 2011
1936 (if isearch-success 2012 (if isearch-success
1937 nil 2013 nil
1938 ;; Ding if failed this time after succeeding last time. 2014 ;; Ding if failed this time after succeeding last time.
1939 (and (nth 3 (car isearch-cmds)) 2015 (and (isearch-success (car isearch-cmds))
1940 (ding)) 2016 (ding))
1941 (goto-char (nth 2 (car isearch-cmds))))) 2017 (goto-char (isearch-point (car isearch-cmds)))))
1942 2018
1943 2019
1944 ;; Called when opening an overlay, and we are still in isearch. 2020 ;; Called when opening an overlay, and we are still in isearch.
1945 (defun isearch-open-overlay-temporary (ov) 2021 (defun isearch-open-overlay-temporary (ov)
1946 (if (not (null (overlay-get ov 'isearch-open-invisible-temporary))) 2022 (if (not (null (overlay-get ov 'isearch-open-invisible-temporary)))