Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim search in C/C++ code lines

Tags:

Is there any way to search a string in a C/C++ source file while skipping commented lines?

like image 685
Nicola Bonelli Avatar asked Apr 21 '10 13:04

Nicola Bonelli


People also ask

How do I comment out code in vim C?

Use ctrl-V to do a block selection and then hit I followed by //[ESC] . Then you just shift-V , select the range, and type // (or whatever you bind it to).

How do we search forwards for a pattern in Vim?

One can search forward in vim/vi by pressing / and then typing your search pattern/word. To search backward in vi/vim by pressing ? and then typing your search pattern/word. Once word found in vim, you can press the n key to go directly to the next occurrence of the word in backwards.

How to search next occurrence in Vi editor?

To find a character string, type / followed by the string you want to search for, and then press Return. vi positions the cursor at the next occurrence of the string. For example, to find the string “meta,” type /meta followed by Return. Type n to go to the next occurrence of the string.


2 Answers

This is an intriguing question.

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.

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 

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 

That searches for hello, but only within text that Vim considers a string.

And (finally!) this searches for double everywhere except comments:

:SearchOutside Comment double 

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.)

like image 194
Bill Odom Avatar answered Sep 19 '22 14:09

Bill Odom


This pattern searches for a string that is not preceded by the two C++ commenting conventions. I've also excluded '*' as the first non-whitespace character, as that's a common convention for multi-line comments.

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

Only the first and fourth foo are matched.

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

Putting \v at the beginning of the pattern eliminates a bunch of backslashes:

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

You can bind a hotkey to this pattern by putting this in your .vimrc

"ctrl+s to search uncommented code noremap <c-s> <c-o>/\v((\/\*\|\/\/\|^\s*\*[^/]).*)@<! 
like image 20
bukzor Avatar answered Sep 19 '22 14:09

bukzor