Zero Xan
Zero Xan

Reputation: 123

Highlight all occurence of the selection

i'm creating a little function in order to highlight same term as you are currently selected in Visual mode.

that's my current work :

function CheckSameTerm()

    let currentmode = mode()

    " Check for (any) visual mode
    if currentmode =~? '.*v'

        exec printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))

        "this method is for selection only and not full word(but don't really work) 
        "let select = getline("'<")[getpos("'<")[2]-1:getpos("'>")[2]-1]
        "exec printf('match IncSearch /\V\<%s\>/', select)

    endif

endfunction

au CursorMoved * exec "call CheckSameTerm()"

For now i'm quite stuck with 2 issues :

So have you some ideas for that ? And most important question : Do I go on the good way ? Maybe I miss something easier.

oh and by the way, this is to learn vim script, it is not life saver ;)

Edit

This plugin evolved, go check https://github.com/Losams/-VIM-Plugins/blob/master/checkSameTerm.vim

Upvotes: 1

Views: 144

Answers (1)

Ingo Karkat
Ingo Karkat

Reputation: 172600

You're on the right way. This is far beyond trivial Vim customization, though, and to turn this into a robust plugin, a lot more work is required.

To address your questions:

  • The '<,'> marks unfortunately only contain the current selection once you've left visual mode (explicitly or after operating on it). Your code for extracting the text is fine, but the marks aren't set yet. Instead, you can yank the current selection and then restore it with gv. This clobbers the default register; additional code to save / restore its contents would be needed. (See ingo#selection#Get() from my ingo-library plugin for a robust implementation.)
  • As the visual selection is not necessarily delimited by keyword boundaries, you need to drop the \< ... \> from the pattern.
  • To handle selections across lines, embedded newline characters need to be converted into the \n atom. I do this with substitute() after escaping the special characters in the selection.
  • mode() returns v, V, or ^V for visual mode. No need for the .* and pattern matching; ^V also is a single character (and we cannot handle blockwise selections in a good way, anyway, so it's best to ignore it).
  • To turn off highlighting, just add an else block to the conditional. It needs an additional cursor move to apply, though.
  • You don't need :execute in the :autocmd; there are no variables here that need to be interpolated.

Here's what I have:

function! CheckSameTerm()
    let currentmode = mode()
    " Check for (any) visual mode
    if currentmode ==? 'v'
        normal! ygv
        exec printf('match IncSearch /\V%s/', substitute(escape(@", '/\'), '\n', '\\n', 'g'))
    else
        match none
    endif
endfunction
au! CursorMoved * call CheckSameTerm()

I hope this helps you with a further exploration of Vim scripting. Have fun!

Upvotes: 2

Related Questions