我有一个计算函数并返回一些文本的匹配数:
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以进行零匹配?
答案 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
来获取当前文件中出现的模式次数。