Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a function that moves the cursor without leaving visual mode?

Tags:

vim

I have a function that moves the cursor with the built-in cursor() function and it works fine on normal mode.
For concreteness suppose that this is the function:

function! F()
    call cursor( line('.')+1, 1)
endfunction

used with a mappings as:

 nnoremap <buffer> a :call F()<cr>

Now I want to reuse this function to move the cursor on any visual mode (visual, line visual, and block visual) and without losing the previous selection.

For example, with an initial buffer in visual mode (c means the cursor is at a line, v means the line is part of the current visual selection):

vc 1
   2
   3

hitting a would give:

v  1
vc 2
   3

and hitting a again would give:

v  1
v  2
vc 3

so the old selection was kept.

I would like to reuse F() as much as possible, since in my application F() is quite large.
What is the best way to do that?

Up to now, the best I could do was use a wrapper function:

function! VisMove(f)
    normal! gv
    call function(a:f)()
endfunction

and map as:

 vnoremap <buffer> a :call VisMove('F')<cr>

however I am not satisfied because this:

  1. It requires putting the annoying wrapper on every new fgplugin I write.
  2. Calling a function that moves the cursor (or has other arbitrary side effects) without ever leaving visual (current) mode seems like such a natural thing to be able to do. There is even already <expr> which almost does it, but it resets cursor position.

1 Answers

I solve this by passing a mode argument (or alternatively a boolean isVisual flag) into the function:

fu! F(mode) range
    if a:mode ==# 'v'
        normal! gv
    endif
    ...
endf
nn <buffer> a :cal F('n')<cr>
vn <buffer> a :cal F('v')<cr>
like image 161
Ingo Karkat Avatar answered Oct 03 '22 03:10

Ingo Karkat