Syntax highlight start and end of transparent regions in Vim - vim

I am writing a syntax highlight file for a language (that didn't already have one) in Vim.
An analogous problem to the one I'm stuck on would be highlighting lists in Python: I want the elements of the list to highlight normally, assuming they are types the language allow to be in such a list, while the list's structure (i.e. [ , ] should highlight in its own colour.
Currently I use
syn region myList start='\[' end=']' transparent contains=myList,myDelimiter,myNumber,myString
syn match myDelimiter ',' contained
myList contains itself to allow nested lists (hence legal extra ] end markers) without breaking the region. However, since it is transparent (to allow highlighting of other legal groups (myNumber and myString in this example)), the [ start and ] end brackets remain without highlighting.
The myDelimiter group can be considered a workaround to at least highlight the commas (though it's rather pointless without the rest of the structure, i.e. the start [ and end ]). Adding the [ and ] to the myDelimiter pattern like this:
syn match myDelimiter ',\|\[\|]' contained
breaks the myList region and makes it activate on unrelated parts of the file (outside of any list, thus breaking other syntax highlights for elements not allowed in a list. I think the problem is that the end isn't considered an end anymore, but a delimiter within a big array spanning to the last array in the file).
I tried adding matchgroup=myList to syn region myList ... (and ensured it had a corresponding hi myList ctermfg=red entry in my colorscheme), but it changed nothing.
Is there a way to fix this?

You need to add matchgroup=myListContainer to your region definition and after that you can highlight this new group:
:hi myListContainer guifg=red
You can use for your matchgroup any other group name, but I think that it shouldn't be the same as the primary group you're linking to.
Please take a look at the example here.

Related

vim custom syntax, highlight class occurrences with different colors

I'm new to vim syntax highlight customizations. Trying to create a text based call path description file:
// Entry point
Class1#mainMethod
Class1#privateMethod2
Class2#method3
Class3#method4
Class4#method5
In plantUML the equivalent would be:
ExternalActor -> Class1 : mainMethod
Class1 -> Class1 : privateMethod2()
Class1 -> Class2 : method3()
Class2 -> Class3 : method4()
Class1 -> Class4 : method5()
I already have some decent syntax file in place that makes it look like:
current syntax file looks like:
syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celComment "//.*$" oneline contains=celTodo
hi celComment ctermfg=yellow
hi celTodo ctermfg=green
syn match methodCall /\(#\)\#<=\w*/ contained oneline
hi methodCall ctermfg=blue
syn match className /\w*\(#\)\#=/ contained oneline
hi className ctermfg=red
syn region line start='\(\.\)\#<=\w' end='.\($\)\#=' oneline fold transparent contains=celComment,className,methodCall
Problem
I think a different background color for each occurrence of the same class would help understand the sequence better.
Is there any way to achieve this? So that Class1 will have a different background color than Class2, 3, and 4. But each class always the same, consistent color.
Syntax highlighting associates a keyword, pattern match, or region with a syntax group. A corresponding highlight group then (directly or indirectly through linked groups) determines the color and formatting of the text.
In order to have different (background or otherwise) colors for each class name, you'd have to define different syntax groups, and assign different highlight groups, too. Your syntax file would not only have a fixed set of :syntax match commands, but also a loop that extracts matches from the current buffer and builds the corresponding :syntax match and :highlight command as the syntax loads (using :execute).
Then you have the problem of updating, if the user adds or changes class names. Normally, a syntax is static, so once it loads, it's done. In your case, you'd have to define :autocmds that periodically re-scan the buffer, and add new class names (and maybe even recycle unused highlight group names, so you don't run out of colors). The CursorHold event would be a good candidate for it, but there will be a delay until the colors show up. The available colors is another problem if you want to make this syntax available to other users. The number of colors can vary wildly, and coming up with background colors that work well with various colorschemes is difficult.
Summary
It is possible, but it would be unusual for a syntax, and have side effects like delays in updating or poor performance. (I've seen this used for highlighting function names from the tags file, though.) Some users definitely would want to turn this off.
Alternative
For small files with few (or very distinct) class names, this additional highlighting probably isn't necessary. For large files with many classes, having everything light up would make it appear like a Christmas tree, and all the colors could be more distracting than helpful. I'd rather leave it to the user to do such highlighting of some classes of interest, on demand. My Mark plugin provides the generic functionality for this, in a way that does not interfere with syntax highlighting, and it ships with color palettes that look like text marker highlightings. I use this often to have better orientation in log files or legacy code bases. (The plugin page has links to alternative plugins; there are a few.)
Your syntax
Group names typically have a common prefix that's identical to the name of your syntax. If that is cel, use celMethodCall instead of methodCall, and so on.
I would put the :hi commands all at the bottom; most syntax plugins do it like this.
Especially if you intend to later share the syntax, favor :hi linking to existing syntax groups (:help highlight-groups) over defining your own colors. Even for your personal use, defining your colors in your ~/.vimrc has the benefit of having a single place to adapt and reuse it, instead of hunting around various syntax scripts.
By using :hi def, users can customize the syntax, e.g. in their ~/.vimrc. :help 44.12 has more information on writing syntax plugins.

How to have a Vim multiline syntax highlight clause?

I'm trying to write the syntax highlight module for a tiny text format that includes three different kinds of list elements (starting with -, o and x respectively), and I'd like to highlight entries based on their kind. For single lines it's easy, I just use a syn match myGroup /^\s\+- .\+/ and I'm done.
Problem is, I've been trying to do it so that the next lines without a list marker keep the same colour as the starting list item line, to no success. I've been trying to do it with syntax regions, but I can't seem to understand how they work.
To be more precise, this is the output I'm trying to reach:
If any change is needed in the file format so that it is easier/possible, I have liberty to change it.
Any clue of how can I get it?
You can try something along these lines
syntax region Minus_Region start=/^\s\+-/ end=/;/
hi Minus_Region guifg='Yellow'
syntax region O_Region start=/^\s\+o/ end=/;/
hi O_Region guifg='Green'
syntax region X_Region start=/^\s\+x/ end=/;/
hi X_Region guifg='Gray'
You define region by its start and its end (in this case ;), no matter how many lines are involved.
For more information, see help
:h syn-region
If you want to finish the regions without having a end marking character (in this case ;), you could do it using the match-end (me) option on the end argument of the regions, and having the regions end on the next region-start marker. Example:
syntax region Minus_Region start=/^\s\+- / end=/^\s\+[-ox] /me=s-1
syntax region O_Region start=/^\s\+o / end=/^\s\+[-ox] /me=s-1
syntax region X_Region start=/^\s\+x / end=/^\s\+[-ox] /me=s-1
The me=s-1 part means "The real match ends at one character to the left of the start position of the pattern match".

Syntax Highlighting with Fine Granularity

Is there a way to assign an individual character, as identified by a height and depth index, to a highlight group? Every match feature I have come across uses a regex pattern as input.
The reason I ask is because I am making a syntax coloring plugin that will make text an increasingly lighter shade of gray with increasing parenthesis depth. If vim has no such feature and another algorithm makes character-by-character highlighting unnecessary, please point me to it!
Vim has a whole set of special regular expression atoms that can specify buffer positions.
For lines, \%23l matches only in line 23. You can also use \%>23l for all lines starting from 23, and concatenate two of those with < and > to specify ranges.
For columns, there are the corresponding \%23c and \%23v. The former uses byte indices (what Vim somewhat confusingly calls "columns"), as returned by functions like col() and getpos(), the latter screen widths (from virtcol()).
By combining those atoms, you can select arbitrary blocks of text, and highlight them, e.g. with :call matchadd(...). See :help /\%l for details on the atoms.
For your plugin implementation, you may be able to get some ideas from the vim js context coloring plugin, which highlights JavaScript code according to its scope.

How to change word recognition in vim spell?

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.

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