0

By :set hl, the search result of a / expression is highlighted, for example:

Vim search highlight in action

And if one wants to replace one substring distinguished by its surrounding, one can do so elegantly using regex capture groups:

replace not with and

However, the search highlight does not reflect this capture group. Sometimes, it would be very helpful if it did, so you can feel more confident about your attempted regex. Does Vim have such a feature?

3
  • 2
    You can't. The whole point of the hls setting is to give a visual clue what regex matches in your buffer. For highlighting capturing groups you would need 9 additional highlighting groups. Aug 11, 2018 at 15:53
  • 9 more groups does not seem excessive to me. But alright. :/ Wanna post that as an answer?
    – lindhe
    Aug 11, 2018 at 15:54
  • 2
    XY problem, but neovim's inccommand would make this kind of feature unnecessary.
    – Lie Ryan
    Aug 29, 2019 at 10:59

2 Answers 2

5
+50

I think the quick answer is "no".

Partial solution: with a little extra typing, you can control what part of your search term gets hilighted: \zs to mark the start of highlighting, and \ze to mark the end.

This works nicely for searches:

/"\zs\(foo\|bar\)\ze"

But breaks search-and-replace, eg with:

:%s/"\zs\(foo\|bar\)\ze"/'\1'/gc

because it only replaces the highlighted part.

I've tested on this text:

"foo", "bar", "ba'z", 'foo', 'bar'
0

This command GL meant to run python on a matched group. In this case, we run a search on the matched pattern.

if has('python3')
    command! -nargs=* -range PY <line1>,<line2>python3 <args>
elseif has('python')
    command! -nargs=* -range PY <line1>,<line2>python <args>
endif 

function! RunPython2(match,run)
PY << EOF
import vim
try:
    match=vim.eval("a:match")
    retval=eval(vim.eval("a:run"),globals())
except Exception as e:
    import traceback
    exp=traceback.format_exc()
    retval=None
    try:
        vim.command("echom \"" + str(exp).replace("\"","\\\"") + "\"")
    except:
        pass

if retval==None: retval=match
vim.command("let retInVim=\"" + str(retval).replace("\"","\\\"") + "\"")
EOF
return retInVim
endfunction

function! RunPython(match,run)
PY << EOF
import vim
try:
    match=vim.eval("a:match")
    vim.command(' exec "PY " . a:run')
except Exception as e:
    import traceback
    exp=traceback.format_exc()
    try:
        vim.command("echom \"" + str(exp).replace("\"","\\\"") + "\"")
    except:
        pass
EOF
return ""
endfunction

function! GL(arg) range
    let lst=matchlist(a:arg,'/\(.\{-\}\)/\(.\{-}\) \(.*\)$')
    if lst[2]==#"rpy"
        exec a:firstline. "," . a:lastline . ":s\/" . lst[1] . "/\\=RunPython2(submatch(1),\"". escape(lst[3],"\"//") . "\")"
    elseif lst[2]==#"py"
        exec a:firstline. "," . a:lastline . ":s\/" . lst[1] . "/\\=submatch(0) . RunPython(submatch(1),\"". escape(lst[3],"\"//") . "\")"
    endif
endfunction

command! -nargs=1 -range GL <line1>,<line2>call GL(<f-args>)

To execute:

:%GL/pattern/py vim.command('call feedkeys("/'+match+'\\<CR>")')

Be aware of some nasty escaping in the match.

It assume only one pattern found to be highlighted (or it will highlight the last one).

6
  • 1
    This can be done somehow simpler, using :g/pattern/\=submatch(0) . feedkeys('/'.submatch(1).'\<cr>')
    – eyal karni
    Aug 28, 2019 at 22:38
  • Sorry, what does this have to do with highlighting capture groups?
    – D. Ben Knoble
    Aug 29, 2019 at 4:48
  • It highlights the capture group, only the last 1. You can develop this to highlight gradually, highlight more, or to do confirm and replace.
    – eyal karni
    Aug 29, 2019 at 9:25
  • So how would you make this work, if you want to use :s to replace at the same time? And BTW: why are you using python for this? Aug 29, 2019 at 9:36
  • I already had this command, that uses python so I have used it it is simpler one-liner. I also seized the opportunity to share it. If you want to replace the pattern for sure, you don't need to highlight it. That is why I would use the "rpy" option to replace. I would write a function in python to confirm after the feedkeys and that would return the replaced pattern(possible asking the user).
    – eyal karni
    Aug 29, 2019 at 11:43

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.