Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In VIM, is there any way to define syn region for template angle brackets without clashing with less than sign?

As for {,} and [,] and (, ), I really would like to be able to define syntax region for <, > to be used for C++ template usage like the following:

a<b>

But, is there any way to create such a syntax region without it clashing with something like the following:

if( a < b<c>::d )

The first < is clearly a "less than" operator, and should be discarded as being the beginning of a region for template parameters.

I've tried to use several options but was unable to make it work. Trying to use complex regex to identify the template args region and not a less than operation really seems impossible, it would work only by checking balanced pairs using nested self referential patterns.

like image 500
pepper_chico Avatar asked Nov 29 '12 14:11

pepper_chico


2 Answers

Based on @ingo-karkat answer, I thought a bit further about whitespace usage and I think I got a good enough matching pattern to be happy with (I think this catches 90%+ of the cases).

syn region AngleBrackets matchgroup=AngleBracketContents 
start='[[:space:]<]\@<!<<\@!'
end='>'

start matches < that's not preceded by whitespace nor <. Checking for being or not preceded by whitespace is a key factor because most of the time relational operations will be surrounded by whitespace and also, it is very common practice do not precede template opening brackets with whitespace.

I also check for it not being immediately followed by another <.

Here's a snapshot of what I'm doing (operators inside the region get the color of the region, nested regions change color, it's built upon Rainbow Parentheses Improved with some minor corrections):

VIM snapshot

UPDATE

Just changed my VIM regex to:

\v%(<operator\_s*)@<!%(%(\_i|template\_s*)@<=\<[<=]@!|\<@<!\<[[:space:]<=]@!)

This last one will actually help me enforce good code style.

like image 113
pepper_chico Avatar answered Sep 23 '22 00:09

pepper_chico


As long as you shoot for the 80% solution and restrict the text inside the <...> to non-whitespace identifiers (assuming your coding style surrounds the comparison operators with whitespace), by using :syntax match instead of :syntax region (which already triggers on the start match, without checking for the existence of an end match), that should work (because the single regexp must match both begin and end).

A lot has already been said about the difficulties of parsing C++ (in a real compiler), so don't expect a general-purpose parsing solution using regular expressions to be perfect. (Also, don't forget that syntax highlighting merely is a visual aid, which you shouldn't rely on too much).

like image 29
Ingo Karkat Avatar answered Sep 19 '22 00:09

Ingo Karkat