vim在计算匹配时保持光标位置

时间:2014-10-30 20:10:08

标签: function vim

我有一个计算函数并返回一些文本的匹配数:

function! count_matches()
    redir => matches_cnt
    silent! %s/\[\d*\]//gn
    redir END
    return split(matches_cnt)[0]
endfunction

我创建了一个map,用于在当前位置插入count_matches()的返回值:

noremap <C-A> Go[foo<C-R>=count_matches()<CR>]

但是,在执行无声%s / [\ d *] // gn命令后,光标会跳转到行的开头。因此,当我按下控制+一个vim插入“[foo”,然后该函数正在执行时,搜索命令重置光标位置,返回值插入行的开头,导致“1] [foo”而不是“[foo1]”。

我可以以某种方式阻止计数改变光标位置,或在计算匹配后重置光标位置吗?

如果找不到模式,脚本也会导致错误。如何在没有错误的情况下使函数返回1以进行零匹配?

4 个答案:

答案 0 :(得分:1)

更好的是只保存光标位置,就是保存完整的视口。 (但这只有在你不改变窗口布局的情况下才有效)

请参阅:help winsaveview()

let wsv = winsaveview()
MoveTheCursorAround
call winrestview(wsv)

在您的特定情况下,我会采取另一种方法:

inoremap <expr> <f3>  len(split(join(getline(1,'$'),"\n"), '\[\d\+\]',1))

获取整个文本,并将其拆分为模式\[\d\+\],然后计算有多少元素。或者,如果您想添加一些文字:

inoremap <expr> <f3>  '['.len(split(join(getline(1,'$'),"\n"), '\[\d\+\]',1)).']'

这会在前面添加[,在数字后添加]。根据您的个人喜好调整映射键和文本。 (注意,您不需要winsaveview()函数,因为光标不会移动。)

在多MB文本大小上使用该功能可能不是一个好主意。 ;)

答案 1 :(得分:1)

这是相同的功能,当没有匹配时返回1进行重新设计:

function! count_matches()
    redir => matches_cnt
    try
        silent! %s/\[\d*\]//gn
    catch
        echo 1
    endtry
    redir END
    return split(matches_cnt)[0]
endfunction

答案 2 :(得分:0)

请参阅:help getpos()

let save_cursor = getpos(".")
MoveTheCursorAround
call setpos('.', save_cursor)

答案 3 :(得分:0)

我的解决方案:

function! CountWithCursorKeep(...)
    let currentCursor = getcurpos()
    let pattern = expand('<cword>')
    if a:0 > 0 | let pattern = a:1 | endif
    execute(':%s#' . pattern . '##gn')
    call setpos('.', currentCursor)
endfunction

nmap ,ns :call CountWithCursorKeep(<C-R>/)<cr>
nmap ,nw :call CountWithCursorKeep(expand('<cword>'))<cr>
nmap ,nW :call CountWithCursorKeep(expand('<cWORD>'))<cr>

command! -nargs=? -bar -complete=tag CountMatch call CountWithCursorKeep(<f-args>)

您可以使用:CountMatch pattern来获取当前文件中出现的模式次数。