vim custom syntax highlighting - vim

I'm wanting to create custom syntax highlighting in vim for a task-list.
Task items begin with a hyphen. Two types of task items are relevant: (a) items without an '#done' tag. (b) items with an #done tag. (a) and (b) need to be highlighted differently.
I'm using taskpaper, which works fine, but the issue is, I'm trying to make this to work for task items that span multiple lines. For example:
- Regular item (works)
- Completed item #done (works)
- Multi-line item. This item continues on to
the line below. (doesn't work)
- Multi-line completed item. This item continues
on to the line below. (doesn't work). #done
The highlighting file at taskpaper works for the first two, but not for the second two. As a workaround hack, I tried this for the last case above:
syn region multLineDoneItem start="{" end="}" fold
HiLink multLineDoneItem NonText
But now, I'm forced to mark multi-line done items with braces like so:
- {Multi-line completed item. This item continues
on to the line below. (workaround works).}
I've already searched stackexchange and elsewhere. I would appreciate any help! :)

You could try using the \ze regex atom in the end part of your syntax region. This would allow you to match everything up to but not including the next task. I haven't looked at how you do matching but something like this might work.
syn region muiltLineItem start="^-" end="\(\s*\n)\+\ze^-" fold
syn region multiLineDoneItem start="^-" end="#done\s*\n\(\s*\n\)*\ze^-" fold
HiLink multiLineItem Normal
HiLink multiLineDoneItem NonText
I haven't tested this at all but I think it, or something like it, should work. If you wish to take indentation into account the \z regex atom will allow you to keep matching lines with the same indent.
UPDATE:
Try this:
syn match multilineItem "^-\_.\{-}\ze\(\n-\|\%$\)" fold
syn match multilineDoneItem "^-\(\%(\_^-\)\#!\_.\)\{-}#done\s*\n\ze" fold
command -nargs=+ HiLink highlight default link <args>
HiLink multilineItem Normal
HiLink multilineDoneItem NonText
delcommand HiLink
Oh, also this should work for all four cases and not just the multi-line items.

Related

Limit vim syntax highlighting to diff

I am making changes to an existing C code. If I just want to check my changes, I can easily use vimdiff for that, with old & modified files.
What I want is to limit some syntax highlighting to just the diff part.
Particularly I need to highlight TABS, but only those TABS contained within DiffAdd & DiffChange sections/regions.
What I tried:
syntax region TESTRGN start="TESTRGN_START" end="TESTRGN_END"
highlight TESTRGN ctermbg=lightgreen guibg=lightgreen
syntax match LeadingTabsInRegion display contained containedin=TESTRGN /^\( *\t\+\)\+/
highlight LeadingTabsInRegion ctermbg=darkred guibg=darkred
Above snippet highlights the leading TABS within TESTRGN & tabs in remaining file remain un-highlighted.
However, if I change TESTRGN to DiffAdd in the syntax match line, it does not work as I expected.
My understanding is that DiffAdd is not a region defined using syntax region ... & hence containedin=DiffAdd does not work.
So is there any method/work-around for doing what I am trying to do?
First, what's so bad about having the highlighting everywhere? The diff highlighting stands out well and therefore provides visible scope; couldn't you just ignore the highlighting elsewhere?
In Vim, syntax groups are defined and then linked to colors and attributes defined in highlight groups. The diff stuff uses the second part of that mechanism, but not the syntax part. Therefore, you unfortunately cannot refer to the diff regions within :syntax commands.
There's only a very ugly workaround for this: You have to determine the line numbers that have diff highlighting (via repeatedly stepping through the changes with the ]c motion, and/or using synID() to check for diff highlighting). With those line numbers, you can then define :syntax match commands with the special \%l atom that only matches certain lines. Of course, any addition / deletion of lines would invalidate your definitions, which would need to be frequently re-synchronized (triggered by :autocmd). That's a lot of effort vs. just ignoring the highlighting elsewhere.
Though you need to reset whenever the line was changed, this is just a tip for one of line number based ideas, you can get a list of all diff highlighted lines with:
let dl = filter(range(1, line('$')),
\'index([hlID("DiffChange"), hlID("DiffText"), hlID("DiffAdd")],
\diff_hlID(v:val, 1)) != -1')
And using this, it might be possible to set your TESTRGN with:
exec "syntax match TESTRGN /\\(" . join(map(dl, '"\\%" . v:val . "l"'), "\\|") . "\\).*/"

Set item to higher highlight priority on vim

I want to non ascii characters to show as discussed here, but the syntax highlight disappears when the non ascii character are inside a comment. Investigating a little the problem, I've discovered at the vim-manual that an item that starts earlier has higher priority (3rd item). From help :syn-priority:
When several syntax items may match, these rules are used:
When multiple Match or Region items start in the same position, the item defined last has priority.
A Keyword has priority over Match and Region items.
An item that starts in an earlier position has priority over items that start in later positions.
I am currently using this:
syntax match nonascii "[^\x00-\x7F]"
highlight nonascii cterm=underline ctermfg=red ctermbg=none term=underline
I tried to give higher priority to nonascii match item using the options nextgroup:
syntax match nonascii "[^\x00-\x7F]" nextgroup=Comment
and contains options:
syntax match nonascii "[^\x00-\x7F]" contains=ALL
but it didn't work. I also tried to disable comments temporarily (highlight clear Comment) without the desired effect (my comments got without highlight, but the nonascii continued unhighlighted). What I am missing?
Yes, your custom syntax group isn't matched because there's already a match for comments (or other syntax elements from the existing syntax script).
The solution is to tell Vim that your nonascii group is containedin those groups, so that Vim will attempt to match there (and not just at the uncolored top level), too. What's complicating this is that the syntax group for comments depends on the syntax script and therefore on the filetype (those the naming is quite regular). In the following example, I've used the names for C and Vimscript files:
:syntax match nonascii "[^\x00-\x7F]" containedin=cComment,vimLineComment
Someone already have answered the question. However, for others that are still having problems, here is another solution to highlight non-ascii characters in comments (or any group in the matter). It's not the best, but it's a temporary fix.
One may try:
:syntax match nonascii "[^\u0000-\u007F]" containedin=ALL contained |
\ highlight nonascii ctermfg=yellow guifg=yellow
It's very close to the original implementation and other solution. You may even remove contained, but, from documentation, there may be potential problem of recursing itself (as I understand). To view other defined patterns, syn-contains section would contain it.
:help syn-containedin
:help syn-contains

Is it possible to have vim underline the scope of parentheses my cursor is currently in?

I know there is the rainbow plugin for vim that colorizes opening and closing parentheses and I know that vim can highlight the matching parentheses. I'd like vim to underline everything in the scope of parentheses I am currently in.
For example: Let | be the current cursor position, then:
(a|bc (de fg))
Would underline everything.
(abc (de |fg))
Would underline only (de fg).
Is that even possible?
This match seems to work pretty well:
syn match Foo /([^(]*\%#.*)/
hi link Foo Underlined
You can put it in your ~/.vimrc or a syntax file for a particular language.
Step by step:
syn match Foo - match a syntax group based on a regex and name it Foo
/([^(]* - match a ( followed by an unlimited amount or 0 of any character except (
\%# - match the current cursor position
.* - match an unlimited amount or 0 of any character
) - match a )
hi link Foo Underlined - link the Foo group to Underlined
It should be noted that this is an imperfect solution since regex is not ideal for nested substructures. Rainbow Parenthesis accomplishes this by adding up to 13 levels of recursion, but it does not provide infinite recursion. You could modify its 13 level recursion using the regex example I've provided to accomplish an arbitrary amount of recursion. I am not certain of the impacts on speed that might have.
You can do something visually similar with the following in your .vimrc:
nmap <f12> m[%v%:sleep 350m<CR>`[
imap <f12> <Esc>m[%v%:sleep 350m<CR>`[a
more information at the source

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'

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