Highlight entire line when there are matches - vim

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.

Related

How to prevent search highlight during when executing a mapping

When writing mappings in nvim, I'm sometimes using a search/replace, for instance in this mapping to creating headings that are the same length as the current line (for markdown etc):
nnoremap <leader>= 0Vyp0v$:s/./=/g<cr>:nohls<cr>
While this clears the search highlighting with :nohls, it still creates the "flash" of the search/replace.
General solution
I would make use of :help function-search-undo and extract the commands into a :function. This won't clobber the current search pattern, and therefore also doesn't affect search highlighting. To be fully neutral, you just have to remove the used substitution pattern from the search history (via histdel()):
function! MakeHeading()
normal! Vyp
s/./=/g
call histdel('search', -1)
endfunction
nnoremap <leader>= :call MakeHeading()<CR>
Note that I've also simplified the visual selection handling: As V always selects the entire line, you don't need to go to the first column (^), neither is the reselection necessary; we can just let :substitute work on the current (pasted) line.
Alternative implementation
That reminds me that the canonical implementation of this functionality uses the :help v_r command, and this indeed requires a re-selection:
nnoremap <leader>= Vyp0v$r=
As there's no pattern involved here, search highlighting is totally unaffected by it :-)
Based on your own answer, I would propose the following:
nnoremap <leader>= :set nohlsearch<cr>0Vyp0v$:s/./=/g<cr>:let #/=''<cr>:set hlsearch<cr>
This just sets the search register to an empty string. So no highlighting. You could even reset it to the previous search string:
nnoremap <leader>= :let olds=#/<cr>0Vyp0v$:s/./=/g<cr>:let #/=olds<cr>
And BTW: Wouldn't yyp:s/./=/g be easier.
I personally have hlsearch off by default and only switch it on, when I need it. To toggle it I have the following mapping in my vimrc:
" Switch on/off higlighting of search string
noremap <F8> :set invhlsearch hlsearch?<CR>
While researching :h :s and :h s_flags`, and doing more looking around here, part of #Ein's answer stuck out to me:
whenever you run the command :set hlsearch there are two effects: It sets the option AND it makes vim forget if you've ever typed :nohlsearch. In other words, changing 'hlsearch' (either on or off) will force the current "highlight visibility" to logically match.
With a combination of using :set nohls and the e flag (:h s_e), I ended up with:
nnoremap <leader>= :set nohlsearch<cr>0Vyp0v$:s/./=/g<cr>:s/thanks#Ein//e<cr>:set hlsearch<cr>
" Broken out
" Turn off highlighting
:set nohlsearch
" Yank the whole line, duplicate it, and replace `.` with `=`
0Vyp0v$:s/./=/g
" Do a replace with something I'll never find in a document (probably), with `/e` to suppress errors.
:s/thanks#Ein//e
" Finally, reenable highlighting
:set hlsearch
Any more elegant solutions are welcome. I think I'll be refactoring some of this into a function soon at least, to allow for using other characters like - for subheadings.

When does expand need to be used when mapping a <cword> command in vim?

I can create a mapping that will search for the word under the cursor like so:
noremap <leader>/ :grep <cword> **<cr>
Why is it that unite mappings like unite (I doubt this is a unite specific issue) requires <C-r>=expand('<cword>')<CR> or <c-r><c-w> instead of <cword>?
nnoremap g/ :Unite -input=<C-r>=expand('<cword>')<CR> tag<CR>
The special characters like % and <cword> are explained under :help cmdline-special.
In Ex commands, at places where a file name can be used, the following
characters have a special meaning. These can also be used in the expression
function expand().
That explains why :edit <cword> works, but :echo "<cword>" does not: the latter does not take a file name. :grep just fuzzily refers to [arguments], but naturally some of them have to be files. The :Unite command is universal (and custom), so you need to use expand() there. When in doubt, just try it out :-)

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.

Custom syntax highlighting on current buffer in 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.

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