2

Is there a way to use highlight-regexp in a case-insensitive way? I'm parenthesizing an expression in my regexp and refer to it using \1 later and I want to match this regardless of case. I'm trying to find occurrences of repeated words (with maybe some other words in between), even if they are differently capitalized, e. g. in

One two three.  Four five six four seven eight nine.

I would like to highlight the phrase Four five six four due to the repeated word four. My approach is this regexp:

\b\(\w+\)\b\W+\(\b\w+\b\W+\)\{0,10\}\1\b

I will work fine for repeated words with exactly equal capitalization but it does not work if the capitalization doesn't match.

I also tried setting case-fold-search to various values but it does not seem to be used for highlight-regexp.

Is there any way to highlight my repeated word case?

3 Answers 3

1

You can easily do what you want with library Highlight (highlight.el.

Just set or bind case-fold-search to t and call any of the regexp-highlighting functions:

  • hlt-highlight-regexp-to-end - Matches from point to point-max.
  • hlt-highlight-regexp-region - Matches within the active region (or full buffer if not active).
  • hlt-highlight-regexp-groups-region - Like hlt-highlight-regexp-region, but also highlights each regexp-group match differently, so you can see the group matches.
  • hlt-highlight-regexp-region-in-buffers - Like hlt-highlight-regexp-region, but in each buffer of a list of buffers.

(You also have the same commands, but with unhighlight in the name, for unhighlighting regexp matches - e.g., hlt-unhighlight-regexp-region.)

Actually, you have two ways to do this:

  1. You can use overlays for your highlighting, in which case there is automatically no interference from font-lock. The default value, only, of option hlt-use-overlays-flag does this. To do this you need not customize any option - it is the default behavior.

  2. But if you want to use text properties rather than overlays for your highlighting, you can still do it, by (1) setting option hlt-use-overlays-flag to nil (or to value t) and (2) setting option hlt-face-prop to value face, instead of the default value font-lock-face.

Also, command hlt-highlight combines several commands in one. I bind it to C-x C-y. If I want to do regexp highlighting or unhighlighting I just give it a positive (e.g. M-1) or negative (e.g. M--) prefix arg, respectively.

4
  • I tried that and found that it works. Unfortunately unlike the method I used up to now it does not highlight instantly new stuff I type (which is one relevant aspect for me I omitted in my question). Is there a way to make this instantly reactive on typing?
    – Alfe
    Oct 14, 2018 at 23:17
  • 1
    I guess you're talking about incremental updating as you type a search pattern. No, it does not do that. You enter a regexp as a complete input, and it highlights its matches.
    – Drew
    Oct 15, 2018 at 4:41
  • No, I talk about incremental updates of the highlights while I change the buffer (type new text in the buffer or change the found spots).
    – Alfe
    Oct 15, 2018 at 21:32
  • I see now that you meant that. See my comment for the other answer about that. I don't have another answer for you (other than font-lock). Hopefully someone else will.
    – Drew
    Oct 15, 2018 at 22:46
0

highlight-regexp is typically(*) only a wrapper around font-lock-add-keywords.

For font-lock rules, the variable font-lock-keywords-case-fold-search is used to control whether the search is case sensitive or not. However, setting this affects all font-lock keywords, so in most cases this is not the way to do this.

A better way to do this is the to replace a font-lock rule that highlight-regexp adds, which looks something like:

("my-regexp" (0 'face prepend))

With

(my-matcher-function (0 'face prepend))

In other words, call the following is a suitable hook to add the rule (replacing face with the face you want to use):

(font-lock-add-keywords nil
  '((my-matcher-function (0 'face prepend))))

Where my-matcher-function is a function that search for "my-regexp", but do that in a context where case-font-search is non-nil. For example (untested):

(defun my-matcher-function (limit)
  (let ((case-fold-search t))
    (re-forward-search "\\b\\(\\w+\\)\\b\\W+\\(\\b\\w+\\b\\W+\\)\\{0,10\\}\\1\\b" limit t)))

(*) When a buffer doesn't use font-lock, highlight-regexp use another method.

1
  • Using the default installation on a current Ubuntu, I find neither a variable font-lock-keywords-case-fold-search nor font-lock-add-keywords. Since I want to edit pure prose text, I'm not using any other keyword highlighting, so the global change would be a solution for me.
    – Alfe
    Oct 14, 2018 at 22:05
0

Based on your comment that you would like to see incremental change of highlighting as you type your regexp, rather than entering it all at once before seeing the highlighted matches, here's another possibility:

Set option lazy-highlight-cleanup to nil, and then use Isearch to regexp-search (C-M-s). that highlights incrementally, as you type. And when that variable is nil the highlighting remains when you exit Isearch.

Afterward you can remove that highlighting at any time using M-x lazy-highlight-cleanup.

This highlighting uses overlays, not text properties.

(See also option lazy-highlight-max-at-a-time.)


If you use library Isearch+ (isearch+.el) then you can toggle lazy-highlight-cleanup anytime during Isearch using M-s h l. That can be handy, and it's easier than using M-x lazy-highlight-cleanup to remove any existing highlighting.

2
  • Interesting. But again, this doesn't seem to update when I type new text which would match the search expression. I would still need to re-type C-M-s twice to re-highlight the new stuff.
    – Alfe
    Oct 15, 2018 at 21:29
  • Once again I guess I misinterpreted what you said. You apparently mean have the highlighting update when you change the buffer text, not when you incrementally type the search pattern. Font-lock is about your best bet for that, I guess.
    – Drew
    Oct 15, 2018 at 22:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.