diff options
-rw-r--r-- | doc/emacs/search.texi | 10 | ||||
-rw-r--r-- | etc/NEWS | 4 | ||||
-rw-r--r-- | lisp/isearch.el | 62 |
3 files changed, 47 insertions, 29 deletions
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index d982a9e8787..d25e35635e9 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1984,11 +1984,13 @@ the @code{search-highlight-submatches} variable. If this variable's value is @code{nil}, no special highlighting is done, but if the value is non-@code{nil}, text that matches @samp{\( @dots{} \)} constructs (a.k.a.@: ``subexpressions'') in the regular expression will be -highlighted with distinct faces, named @code{isearch-group-odd} -for the odd group matches, and @code{isearch-group-even} -for the even group matches. For instance, when searching for +highlighted with distinct faces, named @code{isearch-group-1} +and @code{isearch-group-2}. For instance, when searching for @samp{foo-\([0-9]+\)}, the part matched by @samp{[0-9]+} will be -highlighted with the @code{isearch-group-odd} face. +highlighted with the @code{isearch-group-1} face. When there are +more matches than faces, then faces are recycled from beginning, +so the @code{isearch-group-1} face is used for the third match again. +You can define more faces using the same numbering scheme. @cindex lazy highlighting customizations @vindex isearch-lazy-highlight @@ -1106,9 +1106,9 @@ keystrokes. +++ *** Interactive regular expression search now uses faces for sub-groups. -E.g., 'C-M-s foo-\([0-9]+\)' will now use the 'isearch-group-odd' face +E.g., 'C-M-s foo-\([0-9]+\)' will now use the 'isearch-group-1' face on the part of the regexp that matches the sub-expression "[0-9]+". -The even group matches are highlighted with the 'isearch-group-even' face. +By default, there are two group faces, but you can define more. This is controlled by the 'search-highlight-submatches' user option. This feature is available only on terminals that have enough colors to distinguish between sub-expression highlighting. diff --git a/lisp/isearch.el b/lisp/isearch.el index 781a8c5a93a..08d4be3ca82 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -271,8 +271,11 @@ are `word-search-regexp' \(`\\[isearch-toggle-word]'), `isearch-symbol-regexp' (defcustom search-highlight-submatches t "Whether to highlight regexp subexpressions of the current regexp match. -The faces used to do the highlights are named `isearch-group-odd' and -`isearch-group-even'." +The faces used to do the highlights are named `isearch-group-1', +`isearch-group-2'. When there are more matches than faces, then faces are +recycled from beginning, so the `isearch-group-1' face is used for the +third match again. If you want to use more distinctive colors, you have to +define more of these faces using the same numbering scheme." :type 'boolean :version "28.1") @@ -887,7 +890,7 @@ variable by the command `isearch-toggle-lax-whitespace'.") "Stack of search status elements. Each element is an `isearch--state' struct where the slots are [STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD/REGEXP-FUNCTION - ERROR WRAPPED BARRIER CASE-FOLD-SEARCH POP-FUN]") + ERROR WRAPPED BARRIER CASE-FOLD-SEARCH POP-FUN MATCH-DATA]") (defvar isearch-string "") ; The current search string. (defvar isearch-message "") ; text-char-description version of isearch-string @@ -903,6 +906,7 @@ Each element is an `isearch--state' struct where the slots are "Recorded minimum/maximal point for the current search.") (defvar isearch-just-started nil) (defvar isearch-start-hscroll 0) ; hscroll when starting the search. +(defvar isearch-match-data nil) ; match-data of regexp-based search ;; case-fold-search while searching. ;; either nil, t, or 'yes. 'yes means the same as t except that mixed @@ -1221,6 +1225,7 @@ used to set the value of `isearch-regexp-function'." isearch-small-window nil isearch-just-started t isearch-start-hscroll (window-hscroll) + isearch-match-data nil isearch-opoint (point) search-ring-yank-pointer nil @@ -1349,8 +1354,8 @@ The last thing is to trigger a new round of lazy highlighting." (set-window-hscroll (selected-window) current-scroll)))) (if isearch-other-end (if (< isearch-other-end (point)) ; isearch-forward? - (isearch-highlight isearch-other-end (point)) - (isearch-highlight (point) isearch-other-end)) + (isearch-highlight isearch-other-end (point) isearch-match-data) + (isearch-highlight (point) isearch-other-end isearch-match-data)) (isearch-dehighlight)))) (setq ;; quit-flag nil not for isearch-mode isearch-adjusted nil @@ -1508,7 +1513,8 @@ REGEXP if non-nil says use the regexp search ring." (barrier isearch-barrier) (case-fold-search isearch-case-fold-search) (pop-fun (if isearch-push-state-function - (funcall isearch-push-state-function)))))) + (funcall isearch-push-state-function))) + (match-data isearch-match-data)))) (string nil :read-only t) (message nil :read-only t) (point nil :read-only t) @@ -1520,7 +1526,8 @@ REGEXP if non-nil says use the regexp search ring." (wrapped nil :read-only t) (barrier nil :read-only t) (case-fold-search nil :read-only t) - (pop-fun nil :read-only t)) + (pop-fun nil :read-only t) + (match-data nil :read-only t)) (defun isearch--set-state (cmd) (setq isearch-string (isearch--state-string cmd) @@ -1532,7 +1539,8 @@ REGEXP if non-nil says use the regexp search ring." isearch-error (isearch--state-error cmd) isearch-wrapped (isearch--state-wrapped cmd) isearch-barrier (isearch--state-barrier cmd) - isearch-case-fold-search (isearch--state-case-fold-search cmd)) + isearch-case-fold-search (isearch--state-case-fold-search cmd) + isearch-match-data (isearch--state-match-data cmd)) (if (functionp (isearch--state-pop-fun cmd)) (funcall (isearch--state-pop-fun cmd) cmd)) (goto-char (isearch--state-point cmd))) @@ -1624,6 +1632,7 @@ You can update the global isearch variables by setting new values to (isearch-adjusted isearch-adjusted) (isearch-yank-flag isearch-yank-flag) (isearch-error isearch-error) + (isearch-match-data isearch-match-data) (multi-isearch-file-list-new multi-isearch-file-list) (multi-isearch-buffer-list-new multi-isearch-buffer-list) @@ -3432,6 +3441,7 @@ Optional third argument, if t, means if fail just return nil (no error). (match-beginning 0) (match-end 0))) (setq retry nil))) (setq isearch-just-started nil) + (setq isearch-match-data (match-data t)) (if isearch-success (setq isearch-other-end (if isearch-forward (match-beginning 0) (match-end 0))))) @@ -3663,27 +3673,27 @@ since they have special meaning in a regexp." (defvar isearch-overlay nil) (defvar isearch-submatches-overlays nil) -(defface isearch-group-odd +(defface isearch-group-1 '((((class color) (min-colors 88) (background light)) - (:background "#ff00ff" :foreground "lightskyblue1")) + (:background "#f000f0" :foreground "lightskyblue1")) (((class color) (min-colors 88) (background dark)) - (:background "palevioletred3" :foreground "brown4")) + (:background "palevioletred1" :foreground "brown4")) (t (:inherit isearch))) "Face for highlighting Isearch the odd group matches." :group 'isearch :version "28.1") -(defface isearch-group-even +(defface isearch-group-2 '((((class color) (min-colors 88) (background light)) - (:background "#800080" :foreground "lightskyblue1")) + (:background "#a000a0" :foreground "lightskyblue1")) (((class color) (min-colors 88) (background dark)) - (:background "#905070" :foreground "brown4")) + (:background "palevioletred3" :foreground "brown4")) (t (:inherit isearch))) "Face for highlighting Isearch the even group matches." :group 'isearch :version "28.1") -(defun isearch-highlight (beg end) +(defun isearch-highlight (beg end &optional match-data) (if search-highlight (if isearch-overlay ;; Overlay already exists, just move it. @@ -3693,18 +3703,24 @@ since they have special meaning in a regexp." ;; 1001 is higher than lazy's 1000 and ediff's 100+ (overlay-put isearch-overlay 'priority 1001) (overlay-put isearch-overlay 'face isearch-face))) + (when (and search-highlight-submatches isearch-regexp) (mapc 'delete-overlay isearch-submatches-overlays) (setq isearch-submatches-overlays nil) - (dotimes (i (/ (length (match-data)) 2)) - (unless (zerop i) - (let ((ov (make-overlay (match-beginning i) (match-end i)))) - (overlay-put ov 'face (if (zerop (mod i 2)) - 'isearch-group-even - 'isearch-group-odd)) - (overlay-put ov 'priority 1002) - (push ov isearch-submatches-overlays)))))) + (let ((submatch-data (cddr (butlast match-data))) + (group 0) + ov face) + (while submatch-data + (setq group (1+ group)) + (setq ov (make-overlay (pop submatch-data) (pop submatch-data)) + face (intern-soft (format "isearch-group-%d" group))) + ;; Recycle faces from beginning. + (unless (facep face) + (setq group 1 face 'isearch-group-1)) + (overlay-put ov 'face face) + (overlay-put ov 'priority 1002) + (push ov isearch-submatches-overlays))))) (defun isearch-dehighlight () (when isearch-overlay |