Question

I have a custom config that involves the following syntax:

  • key=value
  • $(var) represents a variable

The $(var) part can appear in both key and value, i.e. message="hello $(FirsName) $(LastName)". The value part must be surrounded by double quote " if it contains space characters.

I want to match key, value and $(var) and highlight them separately in vim.

Here is what in my vim syntax file:

syn match configValue "\(\S\+=\)\@<=\"[^\"]*\"\|\(\S\+=\)\@<=\S\+"
syn match configKey "^\s*[a-zA-Z0-9_.]\+\(\s*=\)\@="
syn match configVar "\$(.*)"

The code successfully matches configValue and configKey, but not configVar if it is within key=value. This is ruled by the syntax match priority (h:syn-priority):

  1. When multiple Match or Region items start in the same position, the item defined last has priority.
  2. A Keyword has priority over Match and Region items.
  3. An item that starts in an earlier position has priority over items that start in later positions.

Rule 3 gives the other two matches higher priority than that of configVar.

My problem is that, how to match the three patterns separately, with configVar having the highest priority?

Was it helpful?

Solution

To have configVar match inside configValue, you have to contain it; this is done via the contained (leave this off if the var can also match anywhere, not just inside key=value) and contains=... attributes:

syn match configValue "\(\S\+=\)\@<=\"[^\"]*\"\|\(\S\+=\)\@<=\S\+" contains=configVar
syn match configVar "\$([^)]*)" contained

Note that I've changed the pattern for configVar to avoid matching $(foo) and $(bar) as one element.


You said that configVar can also appear in configKey, but for that, the range of allowed characters needs to include $(), too. Then, the containment works just as well:

syn match configKey "^\s*[a-zA-Z0-9_.$()]\+\(\s*=\)\@=" contains=configVar
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top