Vim Syntax Match In A Region - vim

I've a syntax after file for Java. It works, cause I already defined some syntax keywords, matches and regions, which are successfully highlighted.
Not I want to highlight some matches, which are within a highlight region I defined before. My intention was that the region get highlighted first and the matches afterwards draw over this region parts.
The exact use case are the function/class/... descriptions with thei documentation keywords like #author, #version, ... Therfore I wrote the following into my syntax file:
syntax region _Comment start="\/\*" end="\*\/"
syntax match _CommentKey "^\s*\*\s*\zs#\w*\ze\s"
highlight link _Comment Comment
highlight link _CommentKey Special
No I have two problems. I test both independently and the comment region works fine. The comment key match only works without the \zs part, so it highlight also the leading *. As soon as I add the \zs nothing is highlighted anymore. How can I solve this? For other matches this works fine.
The second problem: I don't them combined. If I enable both rules, only the whole section will be highlighted as Comment. I doesn't matter where I place the second rule, it will not be highlighted. Also I tried to use the skip for the region, until I realiszed it is meant for something different.
Any ideas? Thanks!
Example code to test:
/**
* Function description here.
*
* #param id
* #author Max Mustermann
*/
private static int function foo(final int id) {
return id;
}

Syntax regions, which have nested matches must allow them:
syntax region _Comment start="\/\*" end="\*\/" contains=_CommentKey
Have a look at :h syn-contains
For your first Problem, you should read :h syn-pattern there you'll find the following sentence:
Syntax patterns are always interpreted like the 'magic' option is set,
no matter what the actual value of 'magic' is.
See :h magic for that. Your regex must escape # in magic mode.
"^\s*\*\s*\zs\#\w*\ze\s"
should work fine

Related

Vim: Substitute only in syntax-selected text areas

The exact problem: I have a source in C++ and I need to replace a symbol name to some other name. However, I need that this replace the symbol only, not accidentally the same looking word in comments or text in "".
The source information what particular language section it is, is enough defined in the syntax highlighting rules. I know they can fail sometimes, but let's state this isn't a problem. I need some way to walk through all found occurrences of the phrase, then check in which section it is found, and if it's text or comment, this phrase should be skipped. Otherwise the replacement should be done either immediately, or by asking first, depending on well known c flag.
What I imagine would be at least theoretically possible is:
Having a kinda "callback" when doing substitution (called for each phrase found, and requesting the answer whether to substitute or not), or extract the list of positions where the phrase has been found, then iterate through all of them
Extract the name of the current "hi-linked" syntax highlighting rule, which is used to color the text at given position
Is it at all possible within the current features of vim?
Yes, with a :help sub-replace-expression, you can evaluate arbitrary expressions in the replacement part of :substitute. Vim's synID() and synstack() functions allow you to get the current syntax element.
Luc Hermitte has an implementation that omits replacement inside strings, here. You can easily adapt this to your use case.
With the help of my ingo-library plugin, you can define a short predicate function, e.g. matching comments and constants (strings, numbers, etc.):
function! CommentOrConstant()
return ingo#syntaxitem#IsOnSyntax(getpos('.'), '^\%(Comment\|Constant\)$')
endfunction
My PatternsOnText plugin now provides a :SubstituteIf command that works like :substitute, but also takes a predicate expression. With that, it's very easy to do a replacement anywhere except in comments or constants:
:%SubstituteIf/pattern/replacement/g !CommentOrConstant()

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".

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'

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".

Vim: need help with a tiny script code to highlight

I need a script code to highlight "[Capítulo" and "]" and everything between them. Thank you.
I want it to work everytime I open , for example, a .txt file. Just like code highlighting.
Here's an easy way to do it:
in vim, make sure syntax highlighting is on with :syn on
run the command :highlight to get a listing of all the highlight group names, and samples of what they look like. The Error group looks like it stands out well in my colorscheme, so I'll use that in my example (but you can use any of the other names, like Todo or Search)
:syntax match Error /\[Capítulo[^\]]*\]/
This pattern will keep you from greedily matching the largest chunk. Even though other people are suggesting you use the regular expression /\[Capítulo.*\]/ - it's probably not what you want, because it will match everything in between if there are two or more such patterns on a line.
For example /\[Capítulo.*\]/ will match this entire line:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
The same example but with /\[Capítulo[^\]]*\]/ will only match stuff inside []:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
With regular expressions, it's a common trick to make a group that matches everything but the character that you want to end your match, instead of using the .* which will match as many characters as it can. In this case, we make the group [^\]]* - which says "match everything except ]."
If this works the way you want it to, add the syntax match line without the ":" to your .vimrc
A regular expression is what you're looking for:
Type / to enter in "search mode" and type:
\[Capítulo.*\]/

Resources