diff options
| author | Eli Zaretskii | 2004-08-14 12:48:39 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2004-08-14 12:48:39 +0000 |
| commit | 08e3de6956fcee57077a2f8fe9e51add6b3d0aae (patch) | |
| tree | bf6c236495c108111cf912c8a053ad7eef0d281f | |
| parent | d35c2489f7f05a1648c0293182b00088b3b2880e (diff) | |
| download | emacs-08e3de6956fcee57077a2f8fe9e51add6b3d0aae.tar.gz emacs-08e3de6956fcee57077a2f8fe9e51add6b3d0aae.zip | |
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.
| -rw-r--r-- | lisp/isearch.el | 234 |
1 files changed, 155 insertions, 79 deletions
diff --git a/lisp/isearch.el b/lisp/isearch.el index a5261d2530c..3ec972a39ec 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el | |||
| @@ -153,9 +153,9 @@ string, and RET terminates editing and does a nonincremental search." | |||
| 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 | ||
| @@ -298,11 +298,11 @@ Default value, nil, means edit the string instead." | |||
| 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. |
| @@ -372,9 +372,9 @@ Default value, nil, means edit the string instead." | |||
| 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 |
| @@ -774,6 +774,74 @@ REGEXP says which ring to use." | |||
| 774 | ;; (handle-switch-frame (car (cdr last-command-char)))) | 774 | ;; (handle-switch-frame (car (cdr last-command-char)))) |
| 775 | 775 | ||
| 776 | 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))) | ||
| 843 | |||
| 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 () |
| @@ -1249,53 +1317,93 @@ might return the position of the end of the line." | |||
| 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 | ||
| 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)) | ||
| 1290 | 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. |
| @@ -1775,38 +1883,6 @@ If there is no completion possible, say so and continue searching." | |||
| 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) |
| @@ -1936,9 +2012,9 @@ Can be changed via `isearch-search-fun-function' for special needs." | |||
| 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. |