Vim custom syntax, excluding previous match highlighting in a region - vim

I'm writing a vim syntax highlighting script for a file that uses * to denote the start of a comment, except when surrounded by {}. i.e.
* This is a comment, bellow is math
{ x_variable * y_variable + 10.0 }
I would like to highlight only the brackets, and ignore the comment highlighting inside, while still maintaining highlighting for numbers.
So far I have:
syn match mathSym "[{}]"
syn region mathRegion start=+{+ send=+}+ contains=numberHi
syn match commentHi "\*.*$" display contains=#Spell
hi link commentHi Comment
hi link mathSym Statement
hi link mathRegion Normal
I'm not sure if this is the right way to do it. It seem to ignore the * as a comment, and provide number highlighting, but no highlighting for the brackets.
I tried
region mathRegion start=+{+ send=+}+ contains=numberHi, mathSym
but this ends up setting all highlighting in the file to Normal

Your question is missing the numberHi stuff, but this should do the trick:
syn region mathRegion matchgroup=mathSym start=+{+ end=+}+ contains=numberHi,mathSym
syn match commentHi "\*.*$" display contains=#Spell
hi link commentHi Comment
hi link mathSym Statement
Instead of a separate match for mathSym, you can use the matchgroup=mathSym to highlight the start and end.
Also, you don't need to link mathRegion to Normal; just use it for structure.
The x * y won't match inside mathRegion, because it isn't contained in here. I don't see any problem with it.
PS: Do you know the SyntaxAttr.vim - Show syntax highlighting attributes of character under cursor plugin? It's a great help when writing syntaxes.

Related

Custom Vim syntax highlighting only works for some keywords

I'm writing a custom syntax highlighting file for a proprietary language I have to use a lot. I have written a full file but it seems to only use 3 colors. All punctuation is one color, some of the keywords I have specified are another color, and everything else is a third color.
The odd thing is, I removed every match and every redefinition (hi def link) from the file and the highlighting doesn't seem to have changed at all. In fact, I tried adding some other keyword mappings to try to see where it's breaking, but it seems only certain lines are being evaluated for the highlighting. For instance, this line ends up highlighting the proper text:
syn keyword clangImport IMPORT
However, this line (below) doesn't and is a different color despite not even providing any specific highlighting instructions:
syn keyword clangGroupAttributes ?? GN GA GV GL GP GR PV PN SI CN
Why would it only evaluate certain lines of the syn keyword mapping?
Additionally, none of my regex matching worked at all despite using something as simple as "\d\+".

Vim syntax match

I am implementing a syntax highlight for a proprietary C expansion that we use in VIM.
The syntax is this:
int __event(foobar) my_foobar_function()
{
//whatever
if(foobar)
// do something
}
Now what I would like to do is to highlight __event(foobar), so I wrote this:
syn region xREG start=/__event(/ end=/)/ contains=xFOO
syn keyword xFOO foobar contained
hi xREG ctermfg=darkblue
hi xFOO ctermfg=cyan
This highlights the __event() correctly, however, the foobar in if(foobar) also gets highlighted.
My question is how can I restrict the xFOO group to be highlighted ONLY in xREG and nowhere else.
Thank you.
When you extend an existing syntax (like C), you need to consider the existing syntax items. The following line from syntax/c.vim causes the inclusion of your xFOO group via the ALLBUT=:
syn region cParen transparent start='(' end=')' end='}'me=s-1 contains=ALLBUT,cBlock,#cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString,#Spell
Fortunately, it provides an extension point: You have to add your group to the #cParenGroup cluster:
syn cluster cParenGroup add=xFoo
That should do the trick!

highlight sub-match in vim

I'm trying to figure out how to highlight a specific portion of a match in vim.
Given the following example rule (taken from the coffeescript syntax file source):
syn match coffeeExtendedOp /\%(\S\s*\)\#<=[+\-*/%&|\^=!<>?.]\+\|[-=]>\|--\|++\|:/ display
This regular expression matches various coffeescript operators. The operators are highlighted (in my vimrc) like this:
hi Operator guifg=#ff0000
For example, since coffeeExtendedOp is linked to coffeeOperator which is linked to Operator, in the above source file. This all works, but I'm wondering how to specifically highlight the ++ operator matched in the above syn match with a different color, say blue, within my vimrc (that is, without altering the original source file above). I'm simply wondering if this is possible.
EDIT: I think the rules are placed under a cluster, so perhaps that's why it's not affecting anything. Is there a way to access the rule within the cluster?
EDIT: Question was clarified.
Solution:
syn match plusplus /++/ contained containedin=coffeeExtendedOp display
hi plusplus guifg=#0000ff
The problem now is that this only works when I run them as commands in vim, but not when I put it in my vimrc file. Any ideas? Could it be that the stuff is hidden behind the cluster? But then why is it visible in vim through a command? I tried including the syntax file but it didn't seem to have any effect.
Looking at the coffee.vim you linked to it seems like the dot belongs to the coffeeDotAccess syntax item. So you can highlight it just by doing this:
:hi coffeeDotAccess ctermfg=blue
I'm going to guess a bit at what you need. (I don't speak Coffeescript and your sample regex is way too complicated for me to start reading at the moment).
Transparent syntax items
You could have a look at transparent syntax rules: (http://vimdoc.sourceforge.net/htmldoc/usr_44.html)
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
Partial matches in regex
If you really just meant highlighting submatches, have a look at the the
\zs start match
\ze end match
In short,
:match Error /foo\zsbar\zered/
would highlight only 'bar' in 'foobarred'

LaTeX section highlighting in vim

In LaTeX, a section looks like:
\section{Section Title}
I would like to highlight such sections, or section titles. I tried to put the following in ~/.vim/bundle/latexrc/after/syntax/tex.vim:
syn match texSectioning "\\section\>" skipwhite nextgroup=texSectioningTitle
syn region texSectioningTitle contained matchgroup=Delimiter start='{' end='}' contains=#texSectioningGroup
syn cluster texSectioningGroup contains=texMatcher,texComment,texDelimiter
(Note that this kind of syntax is not handled by the default tex.vim syntax file. It only defines "section zones", which are pretty much worthless for me.)
I then define the following in my color scheme:
hi texSectioning gui=bold guifg=red
And nothing happens; that is, section titles do not appear in red in my LaTeX code (even after I reloaded the file completely).
I am totally confused as to how vim's syntax work, and how to debug it.
Edit
Some more information: it sometimes works and sometimes not. Completely unpredictable. What could be the problem? Pathogen? Something else? I'm completely puzzled.
You have defined the new syntax items texSectioning, texSectioningTitle and texSectioningGroup, but you have not linked them to a highlighting group, so Vim doesn't know how to display them. Try adding these lines:
hi def link texSectioning Statement
hi def link texSectioningTitle String
hi def link texSectioningGroup Comment
The Statement, String and Comment colourings are defining by the colourscheme you are using. These are just examples: you can replace them with any group defined in the colourscheme file.
Here is the answer: the tex.vim divides the text in zones, in which the syntax must be explicitly allowed. The key element is that command:
syn cluster texChapterGroup contains=#texSectioningGroup
This says to vim that inside a texChapterGroup, the syntax cluster texSectioningGroup is allowed. The next thing to do is simply to define that cluster as usual.
Another detail is that the region texSectioningTitle must be contained, otherwise it will match arbitrary pairs of {} in LaTeX.
So a complete solution goes like this:
syn match texSectioningCommand '\\section\>' skipwhite nextgroup=texSectioningTitle contains=#texSectioningGroup
syn region texSectioningTitle start='{' end='}' contained
syn cluster texSectioningGroup contains=texSectioningCommand
syn cluster texChapterGroup contains=#texSectioningGroup
Edit Here is why the behaviour was apparently unpredictable: vim does not read the entire file to figure out the syntax. So in a big enough chapter, my section syntax would work because vim did not go far enough to see it was in a chapter zone.
Just to update the information to highlight section easily. Using containedin means that all the other syntax matches contains this new syntax match. Then just define the color you want.
syn match texSectioningCommand '\\section\>' containedin=ALLBUT,texComment
hi texSectioningCommand guifg=#ec5f67 ctermfg=203
Alternatively, a simple new syntax match could be added to the texFoldGroup in order to be evaluated inside the the block document.
syn match texSectioningCommand '\\section\>'
syn cluster texFoldGroup add=texSectioningCommand
hi texSectioningCommand guifg=#ec5f67 ctermfg=203

Sub-match syntax highlighting in Vim

First, I'll show the specific problem I'm having, but I think the problem can be generalized.
I'm working with a language that has explicit parenthesis syntax (like Lisp), but has keywords that are only reserved against the left paren. Example:
(key key)
the former is a reserved word, but the latter is a reference to the variable named "key"
Unfortunately, I find highlighting the left paren annoying, so I end up using
syn keyword classification key
instead of
syn keyword classification (key
but the former triggers on the variable uses as well.
I'd take a hack to get around my problem, but I'd be more interested in a general method to highlight just a subset of a given match.
Using syn keyword alone for this situation doesn't work right because you want your highlighting to be more aware of the surrounding syntax. A combination of syn region, syn match, and syn keyword works well.
hi link lispFuncs Function
hi link lispFunc Identifier
hi link sExpr Statement
syn keyword lispFuncs key foo bar contained containedin=lispFunc
syn match lispFunc "(\#<=\w\+" contained containedin=sExpr contains=lispFuncs
syn region sExpr matchgroup=Special start="(" end=")" contains=sExpr,lispFuncs
The above will only highlight key, foo, and bar using the Function highlight group, only if they're also matched by lispFunc.
If there are any words other than key, foo, and bar which come after a (, they will be highlighted using the Identifier highlight group. This allows you to distinguish between standard function names and user-created ones.
The ( and ) will be highlighted using the Special highlight group, and anything inside the () past the first word will be highlighted using the Statement highlight group.
There does appear to be some capability for layered highlighting, as seen here: Highlighting matches in Vim over an inverted pattern
which gives ex commands
:match myBaseHighlight /foo/
:2match myGroup /./
I haven't been able to get anything like that to work in my syntax files, though. I tried something like:
syn match Keyword "(key"
syn match Normal "("
The highlighting goes to Normal or Keyword over the whole bit depending on what gets picked up first (altered by arrangement in the file)
Vim soundly rejected using "2match" as a keyword after "syn".

Resources