0
votes

Think about two different highlight match in vim Pattern 1. syn match match1 /\$[^$ ]+\$/ Match $foo$, $bar$, $123$ Pattern 2. syn match match2 /(\w+\|(\$[^\$]+\$)\@=)+__/ I want it match foo$bar$__ but not $bar$ The problem is Pattern1 will conflict with Pattern2. I'm trying to use Positive Lookahead to bypass Pattern1 in Pattern2, but the prefix __ (Double underscores) destroy the behavior of Positive lookahead. How do I solve this issue? or i'm doing something wrong !?


Update:

Sorry for bad explanation.

Pattern 1 match any string surrounded by two dollar signs

syn match match1 /\$[^$ ]\+\$/
-> $foo$, $bar$

Pattern 2 match any string end with double underscores BUT match still but exclude any string that match as Pattern1.

syn match match2 /\(\w\+\|\(\$[^\$]\+\$\)\@=\)\+__/
-> hello__, world__

so the problem is when I add any string related to pattern 1

hello$foo$__

in this case. I want hello AND __ match with pattern 1(Continuous)

but also let $foo$ match with pattern 2.

1
If I give you a PCRE regex, can you convert it to vim ? - user557597
Well, in PCRE, and without any boundary added info, it is this (?:\w+\$[^$ ]+\$__|\$[^$ ]+\$). Don't need a lookahead really. Convert to vim syntax as needed. - user557597
And if you want to totally disallow __ after a $aa$ (unless matched with a foo before it), add the assertion after the \$[^$ ]+\$ clause, like this (?:\w+\$[^$ ]+\$__|\$[^$ ]+\$(?!__)) - user557597
I don't understand your pattern 2. Can you describe in English what it is supposed to match? - melpomene
For the first syntax pattern you could use: /\v\$[^$ ]+\$(_)@!/. This will match words between dollar signs when not followed by underscore (example: $foo$). For the second pattern: /\v\w+\$[^$]+\$__/. This will match a word, followed by a word between dollar signs, followed by double underscore (example: foo$bar$__) - MAGA

1 Answers

1
votes

I don't think you understand what lookahead does. It looks like what you're trying to do is to match a string, but skip over parts of it:

foo$bar$___
^^^~~~~~^^^

... where the parts marked ^ form the match proper (discontinous) and the parts marked ~ are skipped over.

This is not possible with a regex. A regex always matches a continuous piece of string.

What lookahead does is it lets you "peek ahead": It matches a sub-regex as usual, but does not move the current position within the string. Depending on where you put the lookahead, this lets you either check text beyond the end of the match or make sure the same string is matched by two regexes simultaneously (although the latter can also be done with \& in vim).

Example:

\%(foo\)\@=bar

This can never match. It requires the next three characters to be both foo and bar at the same time, which is impossible.


I think what you're looking for is overlapping matches. Vim supports this directly:

syn match match1 /\$[^$ ]\+\$/
syn match match2 /\%(\w\|\$[^$ ]\+\$\)\+__/ contains=match1

Here we're saying matches of match2 can contain matches of match1. This gives you the highlighting you want.