Stefano Borini
Stefano Borini

Reputation: 143765

matching regexp with contained keyword in vim

I am using vim, and I want to highlight the following construct (which is accepted in ifort, but rejected by xlf)

write(5,*), foo

note the comma before the foo variable. I tried the following

syn match fortranWriteComma "write\s*\(.?*,.?*\),"

This works well as long as instead of "write" I use anything else. Example

syn match fortranWriteComma "whatever\s*\(.?*,.?*\),"

this matches and correctly highlights

whatever(5,*),

If I use write, the keyword recognition of write kicks in and does not perform any highlighting. How can I set vim to have the match prevail over the keyword recognition ?

Upvotes: 3

Views: 1009

Answers (2)

sehe
sehe

Reputation: 392853

Q. If I use write, the keyword recognition of write kicks in and does not perform any highlighting. How can I set vim to have the match prevail over the keyword recognition

A. I believe you should be able to have it both ways using a transparent syntax region:

TRANSPARENT

In a C language file you would like to highlight the () text after a "while" differently from the () text after a "for". In both of these there can be nested () items, which should be highlighted in the same way. You must make sure the () highlighting stops at the matching ). This is one way to do this:

:syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/
  \ contains=cCondNest
:syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/
  \ contains=cCondNest
:syntax region cCondNest start=/(/ end=/)/ contained transparent

Now you can give cWhile and cFor different highlighting. The cCondNest item can appear in either of them, but take over the highlighting of the item it is contained in. The "transparent" argument causes this. Notice that the "matchgroup" argument has the same group as the item itself. Why define it then? Well, the side effect of using a matchgroup is that contained items are not found in the match with the start item then. This avoids that the cCondNest group matches the ( just after the "while" or "for". If this would happen, it would span the whole text until the matching ) and the region would continue after it. Now cCondNest only matches after the match with the start pattern, thus after the first (.

Upvotes: 1

Stefano Borini
Stefano Borini

Reputation: 143765

I partially solved by redefining the keyword as a match

syn clear fortranReadWrite 
syn keyword fortranReadWrite backspace close endfile inquire open print read rewind 
syn match fortranWrite "write" contained
hi def link fortranWrite Keyword
syn match fortranWriteComma "write\s*(.*,.*)," contains=fortranWrite
hi def link fortranWriteComma Error

Unfortunately, this is still not perfect, as the "write" remains yellow, and only the parenthesized stuff becomes highlighted.

enter image description here

I could not fix this, but it's ok for my purposes. If anyone has a way of getting write in yellow in normal conditions, but everything red if the comma is added, please add it in comments so I can refine it.

Upvotes: 1

Related Questions