I'm writing a vim syntax highlighting script to determine if a global param is in uppercase only. If its not - I want to highlight it.
The problem is that the global params is in a specific part in the page.
The code looks something like this:
***VARS***
${VAR1}
${var2}
***OTHERS***
${var3}
So I want that all the variables under VARS which contains lowercase to be highlighted - in my example, only ${var2} should be highlighted.
I tried to do this:
syn match global_var_match "\${.*[a-z][^}]+}" contained
syn region global_variables start="\(\*\*\*VARS\*\*\*\)\#<=" end="\(\*\*\* OTHERS\*\*\*\)\#=" contains=global_var_match
hi link global_variables ErrorMsg
But then also ${VAR1} and ${var2} is highlighted.
One problem is the simple typo in:
hi link global_variables ErrorMsg
This should be
hi link global_var_match ErrorMsg
I.e. the bad match, not the containing region. However, with this change, variables containing lower case are still matched under ***OTHERS***.
That issue is caused by a spurious space you have in your match for ***OTHERS***.
I also chhanged your global_var_match regex. I have it as:
syn match global_var_match "\${[^}]*[a-z][^}]*}" contained
This behaves very well for me in test cases like
${VAR} blah ${VAr} ${vAR}
and others: only the vars containing lower case are flagged. Still investigating why the region is incorrect.
Here is what I have:
syn match global_var_match "\${[^}]*[a-z][^}]*}" contained
syn region global_variables start="\(\*\*\*VARS\*\*\*\)\#<=" end="\(\*\*\*OTHERS
\*\*\*\)\#=" contains=global_var_match
hi link global_var_match ErrorMsg
Related
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!
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
In VIM syntax files one can write a syntax region match like this:
syn region xqString start=+'+ end=+'+
syn region xqString start=+"+ end=+"+
What I want to write instead is
syn region xqString start=+(['"])+ end=+\1+
where \1 is the match found in start. Any answers on how to do this or if it's not possible?
See :help :syn-ext-match
External matches :syn-ext-match
These extra regular expression items are available in region patterns:
*/\z(* */\z(\)* *E50* *E52*
\z(\) Marks the sub-expression as "external", meaning that it is can
be accessed from another pattern match. Currently only usable
in defining a syntax region start pattern.
*/\z1* */\z2* */\z3* */\z4* */\z5*
\z1 ... \z9 */\z6* */\z7* */\z8* */\z9* *E66* *E67*
Matches the same string that was matched by the corresponding
sub-expression in a previous start pattern match.
So you could do syn region xqString start=+\z(['"]\)+ skip=+\\.+ end=+\z1+
I like that vim 7.0 supports spell checking via :set spell, and I like that it by default only checks comments and text strings in my C code. But I wanted to find a way to change the behavior so that vim will know that when I write words containing underscores, I don't want that word spell checked.
The problem is that I often will refer to variable or function names in my comments, and so right now vim thinks that each piece of text that isn't a complete correct word is a spelling error. Eg.
/* The variable proj_abc_ptr is used in function do_func_stuff' */
Most of the time, the pieces seperated by underscores are complete words, but other times they are abbreviations that I would prefer not to add to a word list. Is there any global way to tell vim to include _'s as part of the word when spell checking?
Here are some more general spell-checking exception rules to put in .vim/after/syntax/{LANG}.vim files:
" Disable spell-checking of bizarre words:
" - Mixed alpha / numeric
" - Mixed case (starting upper) / All upper
" - Mixed case (starting lower)
" - Contains strange character
syn match spellingException "\<\w*\d[\d\w]*\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\<\(\u\l*\)\{2,}\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\<\(\l\+\u\+\)\+\l*\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\S*[/\\_`]\S*" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
Change pythonComment,python.*String for your language.
transparent means that the match inherits its highlighting properties from the containing block (i.e. these rules do not change the way text is displayed).
contained prevents these matches from extending past the containing block (the last rule ends with \S* which would likely match past the end of a block)
containedin holds a list of existing syntax groups to add these new rules to.
contains=#NoSpell overrides any and all inherited groups, thus telling the spellchecker to skip the matched text.
You'll need to move it into its own group. Something like this:
hi link cCommentUnderscore cComment
syn match cCommentUnderscore display '\k\+_\w\+'
syn cluster cCommentGroup add=cCommentUnderscore
In some highlighters you may need contains=#NoSpell on the end of the match line, but in C, the default is #NoSpell, so it should be fine like that.
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".