Subject: bug#32365: Interactive Highlighting: prefix arg as subexp selector

From: Grégory Mounié <[email-masked]>
Date: Wed, 8 Aug 2018 16:12:36 +0200

Here the patch for modifying Automatic Interactive Highlighting 
(hi-lock.el) for adding prefix-argument to highlight-regexp

  I add a line documenting the option in the corresponding 
hightlight-regexp documentation in doc/emacs/display.texi and a section 
in NEWS.

  Thanks a lot for the feedback and comments.
  Grégory Mounié

PS: it is even better with the patch
>From 64c0e757d57854ddc57a6a9e763f6132e6da1d23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9gory=20Mouni=C3=A9?= <[email-masked]>
Date: Fri, 3 Aug 2018 23:08:10 +0200
Subject: [PATCH] Interactive Highlighting: prefix argument to select subexp

* doc/emacs/display.texi (Highlight Interactively):
* etc/NEWS:
Document the change.
* lisp/hi-lock.el (hi-lock-face-buffer, hi-lock-set-pattern): Use
the prefix argument to highlight only the corresponding sub-expression
of the regexp.

Copyright-paperwork-exempt: yes
---
 doc/emacs/display.texi |  3 ++-
 etc/NEWS               |  5 +++++
 lisp/hi-lock.el        | 28 ++++++++++++++++------------
 3 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 2f5ce80d60..ec79f71e9b 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -975,7 +975,8 @@ Highlight Interactively
 @kbd{M-s h r whim @key{RET} @key{RET}}.  Any face can be used for
 highlighting, Hi Lock provides several of its own and these are
 pre-loaded into a list of default values.  While being prompted
-for a face use @kbd{M-n} and @kbd{M-p} to cycle through them.
+for a face use @kbd{M-n} and @kbd{M-p} to cycle through them. A prefix
+argument limits the highlighting to the corresponding subexpression.
 
 @vindex hi-lock-auto-select-face
 Setting the option @code{hi-lock-auto-select-face} to a non-@code{nil}
diff --git a/etc/NEWS b/etc/NEWS
index 21887f5bfd..07ed8be112 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -687,6 +687,11 @@ to signal the main thread, e.g., when they encounter an error.
 +++
 *** 'thread-join' returns the result of the finished thread now.
 
+** Interactive automatic highlighting
+
+*** prefix argument for function 'highlight-regexp'
+limits the highlighting to the corresponding subexpression
+
 
 * New Modes and Packages in Emacs 27.1
 
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index 13ebffb1af..2dc4f0f519 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -429,10 +429,11 @@ hi-lock-line-face-buffer
 ;;;###autoload
 (defalias 'highlight-regexp 'hi-lock-face-buffer)
 ;;;###autoload
-(defun hi-lock-face-buffer (regexp &optional face)
+(defun hi-lock-face-buffer (regexp &optional face subexp)
   "Set face of each match of REGEXP to FACE.
 Interactively, prompt for REGEXP using `read-regexp', then FACE.
-Use the global history list for FACE.
+Use the global history list for FACE. Limit face setting to the
+corresponding SUBEXP of REGEXP.
 
 Use Font lock mode, if enabled, to highlight REGEXP.  Otherwise,
 use overlays for highlighting.  If overlays are used, the
@@ -441,10 +442,11 @@ hi-lock-face-buffer
    (list
     (hi-lock-regexp-okay
      (read-regexp "Regexp to highlight" 'regexp-history-last))
-    (hi-lock-read-face-name)))
+    (hi-lock-read-face-name)
+    current-prefix-arg))
   (or (facep face) (setq face 'hi-yellow))
   (unless hi-lock-mode (hi-lock-mode 1))
-  (hi-lock-set-pattern regexp face))
+  (hi-lock-set-pattern regexp face subexp))
 
 ;;;###autoload
 (defalias 'highlight-phrase 'hi-lock-face-phrase-buffer)
@@ -686,20 +688,21 @@ hi-lock-read-face-name
       (add-to-list 'hi-lock-face-defaults face t))
     (intern face)))
 
-(defun hi-lock-set-pattern (regexp face)
-  "Highlight REGEXP with face FACE."
+(defun hi-lock-set-pattern (regexp face &optional subexp)
+  "Highlight SUBEXP of REGEXP with face FACE."
   ;; Hashcons the regexp, so it can be passed to remove-overlays later.
   (setq regexp (hi-lock--hashcons regexp))
-  (let ((pattern (list regexp (list 0 (list 'quote face) 'prepend)))
-        (no-matches t))
+  (setq subexp (or subexp 0))
+  (let ((pattern (list regexp (list subexp (list 'quote face) 'prepend)))
+         (no-matches t))
     ;; Refuse to highlight a text that is already highlighted.
     (if (assoc regexp hi-lock-interactive-patterns)
         (add-to-list 'hi-lock--unused-faces (face-name face))
       (push pattern hi-lock-interactive-patterns)
       (if (and font-lock-mode (font-lock-specified-p major-mode))
-	  (progn
-	    (font-lock-add-keywords nil (list pattern) t)
-	    (font-lock-flush))
+          (progn
+            (font-lock-add-keywords nil (list pattern) t)
+            (font-lock-flush))
         (let* ((range-min (- (point) (/ hi-lock-highlight-range 2)))
                (range-max (+ (point) (/ hi-lock-highlight-range 2)))
                (search-start
@@ -712,7 +715,8 @@ hi-lock-set-pattern
             (goto-char search-start)
             (while (re-search-forward regexp search-end t)
               (when no-matches (setq no-matches nil))
-              (let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
+              (let ((overlay (make-overlay (match-beginning subexp)
+                                           (match-end subexp))))
                 (overlay-put overlay 'hi-lock-overlay t)
                 (overlay-put overlay 'hi-lock-overlay-regexp regexp)
                 (overlay-put overlay 'face face))
-- 
2.18.0