5

In text editors like sublime text, atom and notepad++, when you select a word, all matches are highlighted automatically as shown in the following screenshot of my atom editor:

Automatically highlight the word permutation when selected

I use v and select text in vim but how can I obtain all highlight functionality?

1

4 Answers 4

9

TL;DR: Combine * and # with hlsearch

You could highlight by using match and <cword> via an autocommand on an event like CursorHold. But I’m going to show an alternative method.

  • * searches forward for the word under the cursor
  • # searches backward for the word under the cursor

Both have variants (g*, g#) that don’t restrict the searches to word-boundaries.

Use n and N to navigate.

By setting hlsearch, these searches will also highlight matches.

Why do this?

  1. It uses a vim search instead of arbitrary highlights, so you can actually navigate between matches
  2. It uses existing vim machinery and needs little-to-no setup
  3. The commands are good to learn anyway (and then you start to like gd, among others)

Disadvantage

This is does not work for “partial words”: if you visually-select part of a word and hit *, you won’t get the result you want.

One workaround is one of the many visual star plugins.

Another is to simply yank y and then search /<C-r>"<CR> (vim notation: type slash / to search, then Control-R quote to paste the selected text, then hit enter).

3
  • 2
    Why vim does has to be so hard? I hope all these learning commands and losing some features from other editors will be worth it.
    – as2d3
    May 23, 2019 at 21:12
  • 1
    @AbhishekAgrawal I dont see it as losing a feature—fwiw, i dont feel like im missing anything. As far as worth it, any adjustment to workflow comes with cost. Switching to vim years ago paid off for me.
    – D. Ben Knoble
    May 23, 2019 at 21:23
  • @as2d3 Totally worth it. Plus once you figure out the key combo to do exactly what you want like the answer describe, you can make a binding for it. For example in my case, I select text (any text, doesn't matter what characters) and when I hit <enter> it highlights all matches (with hlsearch) and n and p go to them.
    – trusktr
    Dec 30, 2020 at 22:58
5

D. Ben Knoble's answer provides the correct features to look into. Here's a solution that takes that knowledge and gives you some easy key mappings.

First, here's how regular * works with hlsearch enabled (see Ben Knoble's answer for that):

enter image description here

Now the new feature that we will create will do the following. In the next recording, we select some text with VISUAL mode, then hit the enter key and it will highlight all matches, like so:

enter image description here

It is also useful for selecting whole lines and finding matching lines! In the next recording I pressed capital V (shift+v) to enter VISUAL LINE mode and select the current line, then I hit the enter key, and it highlighted all three identical lines:

enter image description here

Nifty!

Note, because this hooks into vim's built-in search feature, you can use n and p to navigate to the next/previous matches just like with * or # search.

To have this functionality, add this mapping to your .vimrc (or init.vim in neovim):

" highlight the visual selection after pressing enter.
xnoremap <silent> <cr> "*y:silent! let searchTerm = '\V'.substitute(escape(@*, '\/'), "\n", '\\n', "g") <bar> let @/ = searchTerm <bar> echo '/'.@/ <bar> call histadd("search", searchTerm) <bar> set hls<cr>

When you have text selected, this mapping will programmatically add the selected text as the last thing you search for (same as if you had used the / key and inputted in manually).

If you have hlsearch enabled, the new search text will be highlighted.

Bonus #1!

I like to toggle the search highlight, so I made ctrl+c toggle it in NORMAL mode (otherwise ctrl+c does not do anything in NORMAL mode, so now ctrl+c will be useful).

When I press ctrl+c repeatedly, it toggles hlsearch:

enter image description here

The mapping for that is:

" Give ctrl+c a job when it is otherwise being wasted!
" Now it toggles `hlsearch` while in NORMAL mode:
nnoremap <silent> <c-c> :if (&hlsearch == 1) \| set nohlsearch \| else \| set hlsearch \| endif<cr>

Bonus #2!

The * and # will move your cursor, which you may not like. A lot of the time I would like to see matches, but without the cursor moving. So I mapped the <enter> key in NORMAL mode to search for the current word (very much like *) but without the cursor jumping.

This is what it looks like when I move to a word, and hit the enter key:

enter image description here

Notice the cursor stayed where it was! In my example, the on instances are close to each other, but if they were far apart, it could be annoying if the whole screen jumped to a new location when I didn't want it to.

And here's the mapping!

" Put <enter> to work too! Otherwise <enter> moves to the next line, which we can
" already do by pressing the <j> key, which is a waste of keys!
" Be useful <enter> key!:
nnoremap <silent> <cr> :let searchTerm = '\v<'.expand("<cword>").'>' <bar> let @/ = searchTerm <bar> echo '/'.@/ <bar> call histadd("search", searchTerm) <bar> set hls<cr>

Bonus #3!

You can run Neovim inside VS Code with the Neo Vim extension. This runs neovim in the background, and you can use the above features right inside VS Code, and also take advantage of all of VS Code's other GUI features.

For example, in the next recording, I selected a line with capital V, and highlighted the matching identical lines with enter, and finally navigated to them with n:

enter image description here

Notice the VS Code GUI including the minimap! With VS Code you'll also have the nice intellisense tooltips with markdown rendering, git GUI, and everything else (many extensions).

Ironically, also notice VS Code's own highlighting (in blue) of the word that is under the cursor! That feature is the whole reason this StackOverflow exists! But now you can do even more with it than just visual matches (navigate to them, and more than just words).

Takeaway

Vim and Neovim are really powerful once you learn them, and especially learn how to script them. They can do so much more with scripting. (And even more with VS Code features in the mix!).

Hope that helps!

6
  • Nice answer. Two nits: why use the clipboard register when the unnamed or even the search register will do ? And your control c mapping is just set hlsearch!
    – D. Ben Knoble
    Dec 31, 2020 at 13:49
  • Actually 3: your enter mapping is *N
    – D. Ben Knoble
    Dec 31, 2020 at 13:50
  • @D.BenKnoble Thanks for the tips on the registers! I was a newb at the time several years back, and probably still am. :) The *N trick won't work, because it may move the scroll position, that was the first thing I tried, whereas mine will never move the scroll position (that's what I want).
    – trusktr
    Jan 1, 2021 at 4:09
  • I suppose you could use winsaveview/winrestview then
    – D. Ben Knoble
    Jan 1, 2021 at 16:41
  • This looks great — but does the illustrated behavior depend on some other stuff in your vimrc (or require nvim)? If I add this mapping plus bonus 1 and 2 to an empty .vimrc in vim 8.1, use v/shift-v to select something, then press enter, it doesn't search, just remains in visual mode (cursor remains where it is, which is good). If I then disable the bonus 2 mapping, trying the same will go to next line, but still won't search -- just expands my visual selection onto the next line, remaining in visual mode. Un-silencing gives me no errors either; I can't tell if I'm just doing something wrong. Dec 29, 2022 at 18:25
1

My SearchHighlighting plugin is one of those "visual star" plugins that @D.BenKnoble mentions in his answer; it also has a command that does exactly what you're asking for:

:SearchAutoHighlighting selection
0

I wrote a little plugin many years ago, and still use it.

highlight_word_under_cursor.vim

Previous versions used :syntax but the last iteration uses :match so it might bug you if you wanted to use :match yourself.

When you land on a word it will highlight other occurrences of that word. But if you move the cursor and are still on the same word, it will stop the highlighting. That is supposed to be convenient.

Oh no I am embarrassed by the code now! Certainly some room for cleanup. Still it has been working pretty well in my experience.

1
  • No need to be embarrassed! You could switch :match for matchadd() though
    – D. Ben Knoble
    Nov 12, 2019 at 13:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.