Поиск Vim в строках кода C/C++

Там какой-либо путь состоит в том, чтобы искать строку в исходном файле C/C++ при пропуске прокомментированных строк?

23
задан Nicola Bonelli 21 April 2010 в 13:58
поделиться

4 ответа

Это интригующий вопрос.

Я думаю, что у @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 , чтобы повторить поиск.

(Кстати, спасибо за этот вопрос. Теперь, когда я построил эти подпрограммы, я надеюсь, что буду их часто использовать.)

29
ответ дан 29 November 2019 в 02:18
поделиться

Этот шаблон выполняет поиск строки, которой не предшествуют два соглашения о комментировании 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*\*[^/]).*)@<!
6
ответ дан 29 November 2019 в 02:18
поделиться

Вот как я поступлю:

  1. Удалите все комментарии C / C ++ (с помощью команды replace % s )
  2. Перейдите к поиску с помощью обычного поиска команды /
  3. Установите метку в позиции, используя ma (чтобы установите метку «a»)
  4. Отмените удаление комментариев с помощью u
  5. Перейти к метке «a» с помощью `` a`
  6. Окончательное удаление метки с помощью delm a (он будет перезаписан, если вы не удалите его, так что ничего страшного)

Конечно, вы можете сделать это за одну большую операцию / функцию. Я недостаточно хорошо разбираюсь в сценариях Vim, чтобы привести пример этого.

Я признаю, что мое решение немного «лениво» (и вы, вероятно, сможете сделать это способом лучше), но это все, к чему я пришел.

Надеюсь, это поможет.

0
ответ дан 29 November 2019 в 02:18
поделиться

Не уверен, что это полезно, но когда вы набираете : syn , он имеет все форматирование, которое используется в вашем типе файла. Может быть, вы можете как-нибудь на это сослаться. Вы могли бы сказать что-то вроде:

map n betterN

function betterN{
  n keystroke
  while currentLine matches comment class
    do another n keystroke
}
1
ответ дан 29 November 2019 в 02:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: