Mercurial > emacs
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))) |