Custom syntax highlighting on current buffer in vim - vim

From time to time I would like to apply some custom extra syntax highlighting on the current buffer.
How can this be done using the build in vim syntax/highlight system (I do not want to use the Highlight plugin)
As example, I would like to highlight all assert statements in current buffer.

If the highlighting is for certain filetypes (e.g. Java) only, and you want it all the time, I'd extend the original syntax with :syn match ... definitions placed in ~/.vim/after/syntax/java.vim.
For spontaneous highlighting, use :match (or :2match), as dwalter has shown.
If you're gonna write a more elaborate mapping, maybe with toggling on/off logic, use matchadd() / matchdelete().
Finally, if you need highlighting for arbitrary words / strings, like marking up a document with a text marker, I'd suggest the comfort of a plugin like Mark (which I have taken over maintaining).

You can use match and highlight if you want.
example:
:hi MyAsserts term=bold ctermbg=Cyan
:match MyAsserts /assert(.*)/
to highlight your assert() statements with Cyan background.
:match without any arguments will reset it.
for more information on either highlight or match look at the documentation via
:help hi or :help match
To reuse your highlighting you can save those commands in a file and use :source file.vim to load it anytime you want. Another way would be to define a command inside your .vimrc.
hi MyAsserts ctermbg=Cyan
command -bar -nargs=0 HiAsserts match MyAsserts /assert(.*)/
"highlight any given regex
command -bar -nargs=1 HiIt match MyAsserts /<args>/
and call it with :HiAsserts to highlight your assert() statements or :HiIt foo to highlight every foo in your buffer.

Related

Dynamic pattern for vim highlight

In the vim help, there is a suggestion to use highlight groups for highlighting text greater than the textwidth:
Another example, which highlights all characters in virtual column
72 and more:
:highlight rightMargin term=bold ctermfg=blue guifg=blue
:match rightMargin /.\%>72v/
I would like this to always reflect the value of texwidth setup. Something like:
match rightMargin /%\=&textwidthv.*/
But this doesn't give me what is expected. Can you help me to parameterize OverLength with the actual value of textwitdh.
NB: I plan to put this in a filetype autocommand block , inside which, there would be a set to textwidth option and redefinition of the rightMargin highlight group.
I realize that this parameterization will not save me any lines of code, but I just want to know if this is possible at all in vim.
One way to do it:
call matchadd('rightMargin', '\%'. &tw .'v')
You should probably put this in a ftplugin (see :help ftplugin) rather than an autocmd.

Run a command each time a file opens, or general syntax

I have a syntax rule that highlights trailing whitespace:
highlight Badspace ctermfg=red ctermbg=red
match Badspace /\s\+$/
This is in my .vimrc. It works fine, but the problem is I use splits a lot, and it seems that the match is only run on the first file you open, as well it should because the .vimrc should only run once.
Anyway, how can I get the above syntax to match any file that is opened? Is there a "general" syntax file? Is there any other way to run match each time a file opens rather than just once? I'd like to know both because I could end up using either one in the future.
The :match command applies the highlighting to a window, so you can use the WinEnter event to define an :autocmd.
:autocmd WinEnter * match Badspace /\s\+$/
Note that there are already a number of plugins for this purpose, most based on this VimTip: http://vim.wikia.com/wiki/Highlight_unwanted_spaces
They handle all that for you, and turn off the highlighting in insert mode; some can also automatically delete the whitespace. In fact, I have written a set of plugins for that, too: ShowTrailingWhitespace plugin.
You could accomplish this by using an autocmd:
highlight Badspace ctermfg=red ctermbg=red
autocmd BufEnter * match Badspace /\s\+$/
However, there's another way to accomplish your specific goal of marking trailing whitespace. Vim has a built-in feature for highlighting "special" whitespace, which includes tabs (to differentiate from spaces), trailing whitespace, and non-breaking spaces (character 160, which looks like a normal space but isn't).
See :help list and :help listchars. Here's what I use:
set list listchars=tab:>·,trail:·,nbsp:·,extends:>
listchars has the benefit of working with any file type, and marking up multiple whitespace types that are of interest. It is also a lot faster (match will be noticeably slow on giant files) and built-in already.
(Note that those are funky non-ASCII dot characters, which should work fine for you if you cut-and-paste into a UTF8-capable Vim. If they don't work for you, you can use any characters you like there, such as periods or underscores).
Here's what it looks like for me:
The correct approach to this problem is actually to use :syntax to define a custom syn-match.
Try putting this in your vimrc:
augroup BadWhitespace
au!
au Syntax * syn match customBadWhitespace /\s\+$/ containedin=ALL | hi link customBadWhitespace Error
augroup END
Edit: It should also be noted that there is built-in support for highlighting trailing whitespace with the 'list' option; see :help 'listchars' and :h hl-SpecialKey (SpecialKey is the highlight group used to highlight trailing whitespace characters when 'list' is on).
This is accomplished using autocmd. The events you're looking for are BufWinEnter and VimEnter. From the Vim manual:
BufWinEnter
After a buffer is displayed in a window. This
can be when the buffer is loaded (after
processing the modelines) or when a hidden
buffer is displayed in a window (and is no
longer hidden).
Does not happen for |:split| without
arguments, since you keep editing the same
buffer, or ":split" with a file that's already
open in a window, because it re-uses an
existing buffer. But it does happen for a
":split" with the name of the current buffer,
since it reloads that buffer.
VimEnter
After doing all the startup stuff, including
loading .vimrc files, executing the "-c cmd"
arguments, creating all windows and loading
the buffers in them.
Try putting this in your vimrc:
augroup BadWhitespace
au!
au VimEnter,BufWinEnter * match Badspace /\s\+$/
augroup END
Do :help autocmd for more info.
This is completely wrong because :match is window-local, not buffer-local. Ingo Karkat has the right idea. Unfortunately, there is no good way to avoid triggering the autocmd every time you enter the window.
More to the point, though, this is a job for a custom syntax, not match.

How to add color to parenthesis and brackets in vim using molokai

I am using molokai in vim to code in python/html/css/javascript. When I edit python files (or javascript) parenthesis are not colored. This is not true for simple scripts (like molokai.vim itself) where parenthesis are colored gray.
I edited molokai.vim and added
hi parens guifg=#999999
and then I edited .vimrc and added:
syn match parens /[(){}]/
but parenthesis and brackets remain white.
What am I doing wrong?
Never use :syn to highlight all filetypes, there is matchadd() for this. Using :syn can easily break highlighting, matchadd() is an overlay.
Syntax highlighting is being overridden when Syntax event fires. More, it has effect only on the current buffer. So just syn in vimrc will never work, you have to use autocommands
autocmd! Syntax python :syntax match Parens /[(){}]/
(for python it is safe as parenthesis and figure brackets are not matched by any other syntax element).
In javascript parenthesis (()) are already matched by javaScriptParens highlighting group. Thus you have to use
hi def link javaScriptParens Parens
(in colorscheme). Braces are matched by javaScriptBraces and require similar command.
To determine what highlighting is used for specific symbol I place cursor on this symbol and launch
echo 'Normal '.join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'))
, the last displayed word is normally what you need. If only Normal is displayed then symbol is not highlighted and you have to go 2., otherwise you have to go 3.
For universal solution disregarding currently used highlighting you may use matchadd() as I already said. But it is local to window so if you are working with multiple windows/tabs you can’t go without autocmd:
autocmd! WinEnter * :if !exists('w:parens_match_id') | let w:parens_match_id=matchadd('Parens', '[(){}]') | endif
All autocommands are to be surrounded with
augroup HighlightParens
autocmd! …
augroup END

Highlight entire line when there are matches

Does anyone know how to highlight the entire line if there is or if there are matches after doing a search.
p.e. I do a search for /user
Now I want to highlight the entire line if there are matches.
EDIT
I want to use the highlighting as in the search highlighting.
I don't want to use the highlighting groups.
An alternative to highlighting the the lines might be using the quickfix list. For example doing following will put all lines matching the pattern /user/ into the quickfix list for the current file (%).
:vimgrep /user/ %
You can display in a separate window the contents of the quickfix list by doing :copen. You can move between matching lines by :cnext, :cprev, and friends. I personally recommend Tim Pope's excellent unimpaired.vim plugin to provide some rather nice and natural feeling mappings like [q and ]q to move through the quickfix list. You can also add a g flag to find multiple matches per line and add them to the quickfix list as well.
You may want to mapping to this vimgrep command to make it a bit faster. I personally use the following in my ~/.vimrc
nnoremap <leader>/ :vimgrep/<c-r>//g %<cr>:copen<cr>
A disadvantage to using :vimgrep command is that it needs a saved file, so unsaved buffers must be saved first. You can overcome this with using a combination of :global and :cgetexpr as shown below.
:cexpr []
:g//caddexpr expand("%").":".line(".").":".getline(".")
However maybe you really do just want to highlight the lines with a match instead of using the quickfix list. The I would suggest using :match like so
:match Search /.*user.*/
You can use whatever highlight group you want. I choose Search as it seemed appropriate. To turn off the highlighting just execute :match with out any arguments.
I personally prefer using :vimgrep and the quickfix list, but your needs may vary from mine.
For more help see:
:h quickfix
:h :vimgrep
:h :cnext
:h :cexpr
:h :caddexpr
:h :match
If you use
:let #/ = '.*\%(' . #/ . '\m\).*'
that should work for most regexp patterns (e.g. the bracketing takes care of \| branches). You could refine that to recognize ^ and $, and magic modifiers like \V.
I don't know if this is acceptable for you:
first you need to define a highlight group: e.g. userline
:highlight userline ctermbg=darkred guibg=darkred
then you could:
:match userline /.*user.*/
all lines containing "user" would be highlighted.

vim: Highlight quickfix selected line with color different than 'Search'

What is the highlight group for the currently selected line in the quickfix window?
The selected line in the quickfix window uses Search for highlighting. I'd like to continue using yellow for Search highlighting, but use blue for quickfix selected line.
Ingo Karkat's answer is right. It's indeed hard-coded in vim code.
I have created a patch - QuickFixCurrentLine.patch for vim8.
Patch is long enough to be posted here. Plus, it has mix of tabs and spaces. So, providing a link-only-answer.
EDIT:
The patch has got upstreamed in the latest vim code.
The name of the highlight has been changed to quickfixline instead of quickfixcurrentline.
The currently selected quickfix item is hard-coded to Search. You'd have to change the Vim source code and recompile to change this.
I see only limited ways to work around this with Vimscript. You could try to override the highlighting for the current line via :match / matchadd() (it has higher priority), but it would only cover the length of the text, not the entire line the original highlighting. Also, I think the currently selected item cannot be easily queried from Vim, so you'd have to hook into the quickfix-local <CR> mapping to update it, and stop using :cnext etc. to move to different errors.
:highlight BlueLine guibg=Blue
:autocmd BufReadPost quickfix match BlueLine /\%1l/
:autocmd BufReadPost quickfix nnoremap <buffer> <CR> :execute 'match BlueLine /\%' . line('.') . 'l/'<CR><CR>

Resources