I'm trying automate some text operations on a large JavaScript project, and wish to jump to the matches using vimgrep
, which I'll follow with various macro invocations.
My target lines look like this:
getText("foo", 1)
But, not like this:
getText("foo")
getText("foo", [1])
I only want to match usages of getText
that have more than one parameter, which is not enclosed in an array.
This search query (/), which uses a negative look-ahead, seems to work:
getText(.*",\(.*[\)\@!
But, running this regular expression with vimgrep
:
:vimgrep /getText(.*",\(.*[\)\@!/ project/src/**/*.js
...fails with this message:
E682: Invalid search pattern or delimiter
I suspect that the look-ahead part of my regex is the cause, as the error goes away when I remove it.
Is there a way to utilize lookaround assertions with vimgrep
?
:vimgrep
loads each searched file into a Vim buffer and then applies Vim's regular expression search to it. So, unlike external tools as 'grepprg'
/ :grep
, you can use the full Vim regular expression syntax here.
As @Matt already commented, the E682
is caused by failing to escape the [
. When you use the expression in a regular /
search, Vim just treats the [
as a literal character, as the collection isn't properly closed - your search works as expected.
In :vimgrep
, the {pattern}
has to be enclosed by /.../
delimiters, however. Apparently the parser continues to look for the ending /
, but cannot find it as the not-yet closed [
collection keeps consuming characters, and this causes the error. This inconsistency isn't nice, and it obviously made you stumble, but it's not necessarily wrong. Now you know :-)
Just properly escape the [
character as \[
, and it'll work:
:vimgrep /getText(.*",\(.*\[\)\@!/ project/src/**/*.js
There are special regexp atoms (\v
and \V
) that change the amount of escaping; some people like to use them (to avoid excessive escaping, or for better readability) - I mostly find the necessary shift in interpretation distracting.