2014-10-30 30 views
2

我有一個函數來計算並返回一些文本的匹配數量時:VIM保持光標位置算起比賽

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

我創建了一個地圖插入count_matches的返回值()在當前位置:

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

然而光標執行無聲%S/[\ d *] // GN命令後跳轉到行的開頭。所以當我按下control + vim插入「[foo」,然後函數正在執行時,搜索命令重置光標位置,返回值被插入到行的開頭,導致「1」[foo]而不是「[foo1]」。

我可以以某種方式防止計數改變光標位置,或計數匹配後重置光標位置?

如果未找到該模式,該腳本也會導致錯誤。如何讓函數返回1而不會出現零匹配錯誤?

回答

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文本大小上使用該函數可能不是一個好主意。 ;)

+0

謝謝!另外:你碰巧知道如何防止函數輸出一個錯誤消息爲零匹配,並返回1呢? – 2014-10-30 20:38:23

+0

我會在一分鐘內更新答案。 – 2014-10-30 20:38:59

+0

它工作,如果我切換「」和「」並關閉最後一個括號,但是如何在不同的鍵映射中使用返回值? – 2014-10-30 21:00:38

0

:help getpos()

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

另請參閱':h winsaveview()' – 2014-10-30 20:19:54

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 
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獲得格局出現的次數當前文件。