Bil*_*dom 29
这是一个有趣的问题.
我认为@sixtyfootersdude有正确的想法 - 让Vim的语法突出显示告诉你什么是评论,什么不是,然后在非评论中搜索匹配.
让我们从一个模仿Vim内置search()例程的函数开始,但也提供一个"skip"参数让它忽略一些匹配:
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
Run Code Online (Sandbox Code Playgroud)
以下是一些基于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
Run Code Online (Sandbox Code Playgroud)
以下命令使语法敏感的搜索功能更易于使用:
command! -nargs=+ -complete=command SearchOutside call SearchOutside(<f-args>)
command! -nargs=+ -complete=command SearchInside call SearchInside(<f-args>)
Run Code Online (Sandbox Code Playgroud)
这还有很长的路要走,但现在我们可以做到这样的事情:
:SearchInside String hello
Run Code Online (Sandbox Code Playgroud)
这会搜索hello,但只在Vim认为是字符串的文本中搜索.
而且(最后!)这会搜索double除评论之外的所有地方:
:SearchOutside Comment double
Run Code Online (Sandbox Code Playgroud)
要重复搜索,请使用@:宏重复执行相同的命令,例如按n重复搜索.
(顺便说一下,谢谢你提出这个问题.既然我已经建立了这些例程,我希望能够使用它们.)
此模式搜索不在两个C++注释约定之前的字符串.我还排除了'*'作为第一个非空白字符,因为这是多行注释的常见约定.
/\(\(\/\*\|\/\/\|^\s*\*[^/]\).*\)\@<!foo
Run Code Online (Sandbox Code Playgroud)
只匹配第一个和第四个foo.
foo
/* foo
* baz foo
*/ foo
// bar baz foo
Run Code Online (Sandbox Code Playgroud)
将\ v放在模式的开头可以消除一堆反斜杠:
/\v((\/\*|\/\/|^\s*\*[^/]).*)@<!foo
Run Code Online (Sandbox Code Playgroud)
您可以将热键绑定到此模式,方法是将其放在.vimrc中
"ctrl+s to search uncommented code
noremap <c-s> <c-o>/\v((\/\*\|\/\/\|^\s*\*[^/]).*)@<!
Run Code Online (Sandbox Code Playgroud)