Paxsali
Paxsali

Reputation: 203

Vim: search word under cursor (not * or #)

I want to replicate Sublime Text's "CTRL-D" behavior which highlights the current word under the cursor.

* and # don't work here, because they automatically move the cursor (like n and N), which I explicitly don't want.

In order to hightlight the current word under the cursor, I have found the following to be effective:

yiw
:let @/=@@
:set hls

If you type this manually it works just fine, as intended.

My problem is that I just don't get it what I do wrong to put this on a keymap so I can bind it.

What I've tried so far is:

  1. create a function, then map it to a key:

    function SearchWordUnderCursor()
        silent! yiw
        silent! :let @/ = @@
        silent! :set hls
    endfunction
    
  2. use the inline keybinding, like so:

    nmap <C-D> yiw | :let @/ = @@ | :set hls
    

Both methods don't work as intended and I don't know what I'm doing wrong.

The search pattern/register is set just fine, but the immediate highlighting is not working, you'd have to manually n or N once to display the highlighting, but that moves the cursor, as opposed to the "manual" method.

Why is it so hard to get it done as if it was typed manually?

I'm using NVIM v0.2.2.

Upvotes: 1

Views: 2064

Answers (4)

SergioAraujo
SergioAraujo

Reputation: 11800

My attempt to solve this issue:

" [I shows lines with word under the cursor
nnoremap <silent> <2-LeftMouse> :let @/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>
nnoremap <Leader>* :let @/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>:CountWord<cr>

if !exists('*CountWordFunction')
    fun! CountWordFunction()
        try
            let l:win_view = winsaveview()
            exec "%s/" . expand("<cword>") . "//gn"
        finally
            call winrestview(l:win_view)
        endtry
    endfun
endif

You can use these options

1 - double mouse clik
2 - <leader>*

Upvotes: 0

D. Ben Knoble
D. Ben Knoble

Reputation: 4673

A simple, non-cursor moving solution is

nnoremap <C-D> *N

Upvotes: 6

Matt
Matt

Reputation: 15091

The first one does not work, because you must use normal! yiw in VimScript (as VimScript statements are :commands, and not normal-mode keys).

The second one does not work, because these are keys, not Ex-commands, and so you must put in : and <CR> where it's appropriate (and also to escape all "bars" with backslashes, as the first "bar" will end the "map"-command otherwise).

So you should read more about normal mode vs. command-line mode.

Also, using hlsearch does not look nice, as you are not searching anything. It's better IMO to use :h :match instead. For example,

nnoremap <C-D> :execute 'match Search /\V' . escape(expand('<cword>'), '\/') . '/'<CR>

Use :match NONE to switch it off.

Upvotes: 2

phd
phd

Reputation: 94453

  1. If you remove silent! from the code vim helpfully cries yiw: not an editor command.

In a function every line is : (ex-)command. Your yiw is equivalent to :yiw and this is not an editor command. (This also means that you can safely omit : before commands). To run a Normal-mode command say :normal explicitly:

function SearchWordUnderCursor()
    silent! normal yiw
    silent! let @/ = @@
    silent! set hls
endfunction
  1. In a mapping you need to separate commands with <BAR> instead of | and pass all the keys you press including Enter:

nmap <C-D> yiw <BAR> :let @/ = @@<CR> <BAR> :set hls<CR>

Upvotes: 0

Related Questions