2013-04-25 2 views
5

У меня есть функция, которая перемещает курсор со встроенной функцией cursor() и отлично работает в обычном режиме.
Для конкретности предположит, что это функция:Как вызвать функцию, которая перемещает курсор, не покидая визуальный режим?

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

используется с отображениями, как:

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

Теперь я хочу, чтобы повторно использовать эту функцию, чтобы переместить курсор на любом визуальном режиме (визуальные, линии визуальный и блок визуальный) и без потери предыдущего выбора.

Например, с начальным буфером в визуальном режиме (c означает, что курсор находится на линии, v означает, что линия является частью текущего визуального выделения):

vc 1 
    2 
    3 

удара a дал бы:

v 1 
vc 2 
    3 

и удар a снова даст:

v 1 
v 2 
vc 3 

поэтому старый выбор сохранен.

Я хотел бы использовать F() по возможности, так как в моем приложении F() довольно большой.
Каков наилучший способ сделать это?

До сих пор, лучшее, что я мог сделать, это использовать функцию обертку:

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

и карта как:

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

Однако я не удовлетворен, потому что это:

  1. Это требует размещения раздражающей обертки на каждом новом fgplugin, который я пишу.
  2. Вызов функции, которая перемещает курсор (или имеет другие произвольные побочные эффекты), не покидая визуальный (текущий) режим, кажется таким естественным, что можно это сделать. Уже есть <expr>, который почти делает это, но сбрасывает положение курсора.
+0

Я не могу думать о другой обходной путь с верхней части моей головы; Я думаю, что любая визуальная карта потеряет визуальный отбор. – dsummersl

+0

Я должен сопротивляться желанию сделать все команды в вашем вопросе более читабельными. – romainl

+0

В визуальном режиме курсор находится либо в начале, либо в конце выбора, пытаетесь ли вы развернуть/оттянуть выделение до произвольной точки? – romainl

ответ

2

Я решить эту проблему, передавая mode аргумент (или в качестве альтернативы, логический isVisual флаг) в функцию:

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> 
+0

благодарит Инго, но я думаю, что предпочитаю мой текущий решение добавления единой оболочки для всех функций вместо добавления одного дополнительного аргумента arg и 'if' для каждой функции движения. –