有什麼方法可以在跳過註釋行的同時在C/C++源文件中搜索字符串?Vim在C/C++代碼行中搜索
回答
這是一個有趣的問題。
我認爲@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
來重複搜索。
(謝謝你問這個問題,順便說一句。現在,我已經建立了這些程序,我希望使用他們很多。)
這是我將如何着手:使用常規搜索命令/
- 刪除所有的C/C++註釋(使用更換命令
%s
) - 前往搜索一個標記在使用
m a
(設置標記「a」)的位置 - 撤消的意見使用
u
- 跳轉到標記「一」使用``了`
- 最終刪除使用
delm a
標記(它會在的情況下被覆蓋你不刪除它,所以沒有刪除大不了)
當然,你可以在一個大的操作/功能中做到這一點。雖然我沒有掌握Vim的腳本,但還是能夠舉例說明。
我承認我的解決方案有點「懶」(你也可以做的方式更好),但這就是我所要做的。
希望它有幫助。
我希望有一個更合適的方式,不過還好,沒有什麼.. .--) – 2010-04-21 14:41:44
如果你問我,這很危險。 – 2010-04-23 04:16:41
@ Ken Bloom:沒有危險的生活一定很無聊嗎?! ;) – ereOn 2010-04-23 06:26:59
此模式搜索一個沒有使用兩種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*\*[^/]).*)@<!
聰明,好看又簡單。 – ereOn 2010-04-22 09:10:30
它甚至可以與'hlsearch' – 2010-04-23 04:15:23
一起使用,不會在一行開始時使用一些評論/ * * /評論。 – 2015-04-21 08:33:12
不確定這是否有幫助,但是是否您輸入:syn
它具有在您的文件類型中使用的所有格式。也許你可以參考一下。你可以這樣說:
map n betterN
function betterN{
n keystroke
while currentLine matches comment class
do another n keystroke
}
- 1. Vim的搜索替換代碼塊
- 2. 在vim中搜索〜(代字號)
- 3. 在Eclipse中搜索代碼行
- 4. 在Vim的搜索中運行AWK
- 5. 在源代碼中搜索
- 6. 在HTML代碼中搜索?
- 7. 在Vim中高級搜索
- 8. Vim:在Open Buffers中搜索
- 9. 在vim中包含搜索
- 10. 在vim中搜索選擇
- 11. 在Vim中搜索/替換
- 12. VIM - 僅在搜索
- 13. Vim多行搜索模式
- 14. 限制Vim中代碼的搜索範圍
- 15. Vim的搜索
- 16. vim搜索\\不\
- 17. 在Vim上面搜索一行
- 18. 直接在Vim中運行python代碼
- 19. 正在搜索asp.net代碼
- 20. 在AJAX搜索代碼
- 21. 搜索和在HTML代碼
- 22. 搜索代碼datasheed
- 23. PHP代碼「搜索」
- 24. 搜索VB6代碼
- 25. 搜索高亮(hlsearch)在vim
- 26. 取消搜索在vim
- 27. Vim的cnoremap在搜索
- 28. 在搜索VIM修改
- 29. 在VBA代碼中搜索文本(在哪一行中)
- 30. 使用vim來搜索十六進制代碼
非常感謝您的回覆。我希望能夠很好地使用它們:-) – 2010-04-24 10:27:05
這太棒了!但有一個小問題。如果您的搜索字符串在文件中找到,但僅在跳過的地方出現,則會出現無限循環。你可以通過放置警衛來解決這個問題。在循環之上:'let l:guard = []'。然後在循環中:'if l:guard == [] |讓l:guard = getpos('。')| elseif l:guard == getpos('。')|打破| endif'。 – 2011-12-16 18:58:55
這真的很棒。請注意,您可以使用'SearchOutside Comment \\\\ | String double'排除多個SynName,是的,您需要四個反斜槓才能退出管道。 – Drasill 2015-01-28 22:40:01