问题描述
有没有办法在跳过注释行的同时搜索 C/C++ 源文件中的字符串?
Is there any way to search a string in a C/C++ source file while skipping commented lines?
推荐答案
这是一个有趣的问题.
我认为@sixtyfootersdude 的想法是正确的 -- 让 Vim 的语法突出显示告诉您什么是注释,什么不是,然后在非注释中搜索匹配项.
I think @sixtyfootersdude has the right idea -- let Vim's syntax highlighting tell you what's a comment and what's not, and then search for matches within the non-comments.
让我们从一个模仿 Vim 内置 search()
例程的函数开始,但也提供了一个跳过"参数让它忽略一些匹配:
Let's start with a function that mimics Vim's built-in search()
routine, but also provides a "skip" parameter to let it ignore some matches:
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()
之上的函数,用于实现对语法敏感的搜索:
Here are a couple of functions that build on SearchWithSkip()
to implement syntax-sensitive searches:
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
以下是使语法敏感搜索功能更易于使用的命令:
Here are commands that make the syntax-sensitive search functions easier to use:
command! -nargs=+ -complete=command SearchOutside call SearchOutside(<f-args>)
command! -nargs=+ -complete=command SearchInside call SearchInside(<f-args>)
那还有很长的路要走,但现在我们可以做这样的事情:
That was a long way to go, but now we can do stuff like this:
:SearchInside String hello
搜索 hello
,但只在 Vim 认为是字符串的文本中搜索.
That searches for hello
, but only within text that Vim considers a string.
并且(终于!)除了注释之外的所有地方都搜索 double
:
And (finally!) this searches for double
everywhere except comments:
:SearchOutside Comment double
要重复搜索,请使用 @:
宏重复执行相同的命令,例如按 n
重复搜索.
To repeat a search, use the @:
macro to execute the same command repeatedly, like pressing n
to repeat a search.
(顺便说一句,感谢您提出这个问题.现在我已经构建了这些例程,我希望能经常使用它们.)
(Thanks for asking this question, by the way. Now that I've built these routines, I expect to use them a lot.)
这篇关于Vim 在 C/C++ 代码行中搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!