我正在为多行快速,有效的普通模式命令构建plugin。我当前正在执行的代表性功能如下:
function! s:lines(...) abort
return [line("'["), line("']")]
endfunction
function! s:gObject(...) abort
if !a:0
let &operatorfunc = matchstr(expand('<sfile>'), '[^. ]*$')
return 'g@'
else
let [lnum1, lnum2] = <SID>lines(a:0, a:1)
let search = input("Run (Leave empty for last search): g/\\v")
let prompt = lnum1 . "," . lnum2 . "g/\\v" . search . "/". "norm "
let cmd = input("Run: " . a:prompt)
exec a:prompt . cmd
endif
endfunction
我现在想增加可重复性。我希望能够按下.
键并重播整个序列。这意味着它应该执行与上一次运行相同的动作来选择文本对象,执行相同的搜索并运行相同的命令。
我可以通过在运行函数之前记录一个宏来完成此操作,然后重播该宏将完全产生所需的行为。我想要确切的结果,但没有用户声明宏的开销。
.
。这会重新运行文本选择,但不会重新运行输入命令(因此会重新出现问题)。预先感谢您的帮助。
答案 0 :(得分:0)
使用repeat.vim是正确的方法;它允许您调整重新执行的内容,还为内置.
命令未涵盖的情况提供重复功能。 (我的visualrepeat plugin将此扩展到了可视模式重复。)
如果我理解正确,那么您想跳过用户查询,只重复使用上一个答案即可。为此,您需要向<Plug>
注册与触发插件不同的repeat#set()
映射。通常,我会这样:
function! s:Impl()
let l:search = input(...)
" action here, using l:search
call repeat#set("\<Plug>PeculiarMapping")
endfunction
nnoremap <silent> <Plug>PeculiarMapping :<C-u>call <SID>Impl()<CR>
if ! hasmapto('<Plug>PeculiarMapping', 'n')
nmap <Leader>p <Plug>PeculiarMapping
endif
要重复使用重复查询的l:search
,请用标志将s:Impl()
参数化,然后将输入保存在脚本局部变量中,或重新调用它。添加<Plug>
映射重复变量以设置isRepeat
标志:
let s:search = ''
function! s:Impl( isRepeat )
if ! a:isRepeat
let s:search = input(...)
endif
" action here, using s:search
call repeat#set("\<Plug>PeculiarRepeat") " Different repeat mapping
endfunction
nnoremap <silent> <Plug>PeculiarRepeat :<C-u>call <SID>Impl(1)<CR>
nnoremap <silent> <Plug>PeculiarMapping :<C-u>call <SID>Impl(0)<CR>
if ! hasmapto('<Plug>PeculiarMapping', 'n')
nmap <Leader>p <Plug>PeculiarMapping
endif
我尝试避免使用input()
,因为它使命令与生俱来就具有交互性,因此它不能重用于脚本编写,甚至不能轻易地被另一个映射调用。如果您只需要在执行工作之前首先从用户那里获取一些参数,我更喜欢一个接受参数的自定义:command
。对于单个参数,这很简单,并且不涉及解析。对于多个参数,我尝试遵守现有Ex命令的约定(最复杂的:substitute
取{pattern}
,{replacement}
,[flags]
甚至是{{1} }); [count]
所采用的各种标志提供了许多变体,您可以通过自定义完成功能进一步帮助用户。
使用自定义命令,可以通过:command
或命令历史记录重复此操作,并且用户可以决定是否重用参数(全部/部分)。如果您认为命令输入的时间太长,则辅助映射可以进入命令行模式,将命令放在其中,甚至可以添加样板间(例如@:
的{{1}}分隔符)和位置光标,因此用户只需填写参数并按///
。