如何重复包含内置输入函数的vimscript函数?

时间:2019-11-02 10:37:30

标签: vim

当前行为

我正在为多行快速,有效的普通模式命令构建plugin。我当前正在执行的代表性功能如下:

用户界面

  1. 它询问用户要在其中执行普通模式命令的文本对象
  2. 它要求一个正则表达式来描述要在其上执行命令的行
  3. 它要求命令运行
  4. 它运行命令

代码

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

所需结果

我现在想增加可重复性。我希望能够按下.键并重播整个序列。这意味着它应该执行与上一次运行相同的动作来选择文本对象,执行相同的搜索并运行相同的命令。

我可以通过在运行函数之前记录一个宏来完成此操作,然后重播该宏将完全产生所需的行为。我想要确切的结果,但没有用户声明宏的开销。

我尝试过的

  1. 已安装vim-repeat,然后按.。这会重新运行文本选择,但不会重新运行输入命令(因此会重新出现问题)。
  2. 记录序列的宏并重播。这会导致用户体验不佳。

预先感谢您的帮助。

1 个答案:

答案 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}}分隔符)和位置光标,因此用户只需填写参数并按///