在vim中使用execute for visual命令

时间:2012-09-19 21:43:24

标签: vim

我知道这一定很简单。

为什么vnoremap <leader>rl di[<esc>pa]将所选文本括在括号中,但是:

vnoremap <leader>rl :call VisAddRefLink()<CR>

function! VisAddRefLink()
    execute "normal! di[\<esc>pa]"
endfunction

不?!

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

您需要让您的函数处理范围。实现这一目标的一种方法是:

vnoremap <leader>rl :call VisAddRefLink()<CR>

function! VisAddRefLink() range
   exe a:firstline . "normal! ^i["
   exe a:lastline . "normal! $a]"
endfunction

你的例子不起作用的原因是因为exe不按照所谓的视觉选择进行操作。例如,尝试直观地选择一些内容,然后执行:norm d。你会注意到它没有删除。如果您为函数添加范围,例如:help function-range-example,则可以通过以类似方式(逐行)操作来帮助进行视觉选择。但是,它仍然不是真正的视觉选择。范围添加确实允许您使用a:firstlinea:lastline变量,这可用于实现此目的。您也可以通过以下方式完成此操作:

vnoremap <leader>rl <esc>:norm! '<^x2Phr['>$x2pr]<cr>

首先使用<esc>结束视觉选择。然后它执行一个只运行一次的普通命令。如果保留了视觉选择,那么它将在视觉选择中为每一行运行一次。一旦它运行了

'<^跳转到视觉选择的第一行和该行的第一个非空白区域。

x2Phr[删除该字符,在前面粘贴两次,向左移动以便我们覆盖新角色,并将其替换为开头[

'>$移动到视觉选择最后一行的最后一个字符

x2pr]和以前一样,但方向相反

像往常一样,皮肤猫的方法不止一种,尤其是vimscript。随着您的了解越来越多,您会看到很多可能性来完成任务。

答案 1 :(得分:2)

试试这个:

vnoremap <leader>rl :<C-u>call VisAddRefLink()<CR>

function! VisAddRefLink()
    execute "normal! gvdi[\<esc>pa]"
endfunction

<C-u>前面的call可以避免地图在其前面插入'<,'>视觉范围;我们希望函数只调用一次,而不是一次调用范围内的每一行。

在功能内部,我们需要在操作前先重新建立视觉选择; gv做到了。