Search code examples
regexvimselected

regexp in vim visual selection, up to the last character selected


Given this line in vim:

The cat is sleepy.

I want to replace "sleepy" by "black" (of course this is for sake of simplicity, i'm actually editing C code)

When cursor is at the beginning of the line, i type "/sle" to make it go to the beginning of "sleepy"
Then v, then e

The word "sleepy" is now fully selected. Then i type ":s/\%V.*\%V/black/"

And instead of having:

The cat is black.

It gives:

The cat is blacky.

The last character visually selected is not considered as part of the selection, or maybe i'm not using \%V correctly.

How can i make pattern matching works in exactly my visual selection ?


Solution

  • You have to add one character after \%V:

    /\%V.*\%V.
    

    . If selection contains more then one line you will have to use \%V\_.*\%V\_..

    There is also another trick:

    /\%V\_.\{-}\%V\@!
    

    (multiline version). This makes use of non-greedy matches and negative look-ahead: first (\{-}) to make sure it operates only on selection, second (\@!, specifically \%V\@!) to make sure there is no visual selection after the last character.

    If you have more complex pattern and cannot make it non-greedy or put one character after last \%V there is another solution, which is way to slow though:

    /\%V\_.*\%(\%V\_.\)\@<=
    

    (multiline version again). It uses positive look-behind to make sure that last character is still inside visual selection.