2

I would like to search for a pattern in a range of lines and append additional text on another line that would include part of the search pattern. Something like this:

[range]g/\(foo \)\(\w\{-}\)/normal! 2jibar \2

but the callback to the capture group does not seem to work. It finds the pattern, moves two lines down, and inserts "bar \2" literally instead of "bar " + the result of the second capture group.

1 Answer 1

4

The :global command does not make its capture groups available to the trailing command. The simplest alternative is to use \zs and \ze to target the specific match and grab the pattern using the normal command;

g/foo \zs\w\{-}\ze/normal! ygn2jp
g/foo \zs\w\{-}\ze/normal! ygn2jibar ^R"

where ^R is a literal ctrl-r, which you type ctrl-v ctrl-r to enter. This uses ygn to yank the next match, which is set appropriately due to the pattern in :global.

You can also write your own commands to be used in the trailing command slot. For instance,

function! CaptureNormal(qargs, bang)
    let l:list = matchlist(getline('.'), (&magic?'\m':'\M').@/)
    let l:args = substitute(a:qargs, '\\\(\d\)', '\=l:list[submatch(1)]', 'g')
    execute 'normal'.a:bang l:args
endfunction

command! -bang -nargs=* CapNorm call CaptureNormal(<q-args>, '<bang>')

All this does is 1) match the line using the previous pattern to grab the capture groups, 2) adjust the given string to replace \2 with the groups text, then 3) run the pre-processed normal command.

[range]g/\(foo \)\(\w\{-}\)/CapNorm! 2jibar \2
1
  • The first option nailed it. Thanks. I don't really follow what's going in the function! example, though. Commented Jun 22, 2018 at 2:54

Your Answer

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

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