2010-04-21 54 views

回答

28

這是一個有趣的問題。

我認爲@sixtyfootersdude有個正確的主意 - 讓Vim的語法突出顯示告訴你什麼是評論,什麼不是,然後搜索非評論內的匹配。

讓我們先從模仿Vim的內置search()常規的功能,而且還提供了「跳過」參數讓它忽略了一些比賽:

function! SearchWithSkip(pattern, flags, stopline, timeout, skip) 
" 
" Returns true if a match is found for {pattern}, but ignores matches 
" where {skip} evaluates to false. This allows you to do nifty things 
" like, say, only matching outside comments, only on odd-numbered lines, 
" or whatever else you like. 
" 
" Mimics the built-in search() function, but adds a {skip} expression 
" like that available in searchpair() and searchpairpos(). 
" (See the Vim help on search() for details of the other parameters.) 
" 
    " Note the current position, so that if there are no unskipped 
    " matches, the cursor can be restored to this location. 
    " 
    let l:matchpos = getpos('.') 

    " Loop as long as {pattern} continues to be found. 
    " 
    while search(a:pattern, a:flags, a:stopline, a:timeout) > 0 

     " If {skip} is true, ignore this match and continue searching. 
     " 
     if eval(a:skip) 
      continue 
     endif 

     " If we get here, {pattern} was found and {skip} is false, 
     " so this is a match we don't want to ignore. Update the 
     " match position and stop searching. 
     " 
     let l:matchpos = getpos('.') 
     break 

    endwhile 

    " Jump to the position of the unskipped match, or to the original 
    " position if there wasn't one. 
    " 
    call setpos('.', l:matchpos) 

endfunction 

這裏有幾個功能,它建立在SearchWithSkip()實現語法敏感的搜索:

function! SearchOutside(synName, pattern) 
" 
" Searches for the specified pattern, but skips matches that 
" exist within the specified syntax region. 
" 
    call SearchWithSkip(a:pattern, '', '', '', 
     \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "' . a:synName . '"') 

endfunction 


function! SearchInside(synName, pattern) 
" 
" Searches for the specified pattern, but skips matches that don't 
" exist within the specified syntax region. 
" 
    call SearchWithSkip(a:pattern, '', '', '', 
     \ 'synIDattr(synID(line("."), col("."), 0), "name") !~? "' . a:synName . '"') 

endfunction 

這裏有命令,使語法敏感的搜索功能,更易於使用:

command! -nargs=+ -complete=command SearchOutside call SearchOutside(<f-args>) 
command! -nargs=+ -complete=command SearchInside call SearchInside(<f-args>) 

這是一個很長的路要走,但現在我們可以做的東西是這樣的:

:SearchInside String hello 

,搜索hello,但僅限於文本Vim假設一個字符串。

和(!終於)這個搜索double無處不在,除了評論:

:SearchOutside Comment double 

要重複搜索,使用@:宏重複執行相同的命令,就像按下n來重複搜索。

(謝謝你問這個問題,順便說一句。現在,我已經建立了這些程序,我希望使用他們很多。)

+0

非常感謝您的回覆。我希望能夠很好地使用它們:-) – 2010-04-24 10:27:05

+7

這太棒了!但有一個小問題。如果您的搜索字符串在文件中找到,但僅在跳過的地方出現,則會出現無限循環。你可以通過放置警衛來解決這個問題。在循環之上:'let l:guard = []'。然後在循環中:'if l:guard == [] |讓l:guard = getpos('。')| elseif l:guard == getpos('。')|打破| endif'。 – 2011-12-16 18:58:55

+2

這真的很棒。請注意,您可以使用'SearchOutside Comment \\\\ | String double'排除多個SynName,是的,您需要四個反斜槓才能退出管道。 – Drasill 2015-01-28 22:40:01

0

這是我將如何着手:使用常規搜索命令/

    1. 刪除所有的C/C++註釋(使用更換命令%s
    2. 前往搜索一個標記在使用m a(設置標記「a」)的位置
    3. 撤消的意見使用u
    4. 跳轉到標記「一」使用``了`
    5. 最終刪除使用delm a標記(它會在的情況下被覆蓋你不刪除它,所以沒有刪除大不了)

    當然,你可以在一個大的操作/功能中做到這一點。雖然我沒有掌握Vim的腳本,但還是能夠舉例說明。

    我承認我的解決方案有點「懶」(你也可以做的方式更好),但這就是我所要做的。

    希望它有幫助。

  • +0

    我希望有一個更合適的方式,不過還好,沒有什麼.. .--) – 2010-04-21 14:41:44

    +0

    如果你問我,這很危險。 – 2010-04-23 04:16:41

    +1

    @ Ken Bloom:沒有危險的生活一定很無聊嗎?! ;) – ereOn 2010-04-23 06:26:59

    6

    此模式搜索一個沒有使用兩種C++註釋約定的字符串。我還排除了'*'作爲第一個非空白字符,因爲這是多行註釋的常見慣例。

    /\(\(\/\*\|\/\/\|^\s*\*[^/]\).*\)\@<!foo 
    

    只有第一個和第四個foo匹配。

    foo 
    /* foo 
    * baz foo 
    */ foo 
    // bar baz foo 
    

    把符\ v在模式的開始消除了一堆反斜線:

    /\v((\/\*|\/\/|^\s*\*[^/]).*)@<!foo 
    

    您可以通過將你的.vimrc文件熱鍵綁定到這個模式

    "ctrl+s to search uncommented code 
    noremap <c-s> <c-o>/\v((\/\*\|\/\/\|^\s*\*[^/]).*)@<! 
    
    +0

    聰明,好看又簡單。 – ereOn 2010-04-22 09:10:30

    +0

    它甚至可以與'hlsearch' – 2010-04-23 04:15:23

    +0

    一起使用,不會在一行開始時使用一些評論/ * * /評論。 – 2015-04-21 08:33:12

    1

    不確定這是否有幫助,但是是否您輸入:syn它具有在您的文件類型中使用的所有格式。也許你可以參考一下。你可以這樣說:

    map n betterN 
    
    function betterN{ 
        n keystroke 
        while currentLine matches comment class 
        do another n keystroke 
    }