C ++ 함수로 제한되는 빠른 검색


13

나는 다소 큰 C ++ 프로젝트에서 일하고 있습니다. 조직의 가장 실망스러운 측면 중 하나는 엄청나게 큰 파일 안에 배치 된 매우 큰 기능입니다.

종종 현재 함수로 제한된 특정 전역 변수 또는 함수 호출의 인스턴스를 검색하려고합니다. 이것을 달성하기 위해 합리적으로 간단한 공식이 있습니까?

(나는 ctags를 설치하고 Tagbar를 사용합니다 ... 이것이 도움이 될 수 있습니다)

답변:


9

내가하는 방법은 다음과 같습니다. 이것을 당신의.vimrc

vnoremap if [[O][

설명 : vnoremap 수단은 왼쪽지도 if오른쪽에 [[mO][당신은 비주얼 모드에있는 동안. 원하는 경우 이름을 바꿀 수 있지만 In Function을if 의미 합니다. 기능의 시작으로 이동합니다. 시각적으로 선택된 텍스트의 다른 쪽 끝으로 이동 한 다음 기능의 끝으로 이동합니다.[[O][

따라서 함수에서 검색하려면을 사용하여 시각 모드로 v들어가서을 사용하여 전체 기능을 선택하십시오 if. 이제로 시각 모드를 종료 <esc>하고로 검색하십시오 /\%V. \%V검색을 이전에 선택한 텍스트로 제한합니다. 공격하지 않으려면 다음을 <esc>/\%V추가하십시오 .vimrc.

vnoremap / <esc>/\%V

그러면 키 입력 순서는 다음과 같습니다.

vif/foo<enter>

그리고 이것은 현재 함수에서 모든 foo 발생을 찾습니다.


이 방법의 유일한 단점은 여는 중괄호와 닫는 중괄호가 모두 들여 쓰기가 0이 될 것으로 예상한다는 것입니다. 이것을 가지고 있지 않은 코드를 정기적으로 사용한다면

int foo() {
    bar()
}

이 약간 더 복잡한 버전이 작동합니다.

vnoremap if ][ma%O'a

이것은 닫는 중괄호가 들여 쓰기가 0이 될 것으로 예상합니다. 오프닝 브레이스에 들여 쓰기가 있으면 마크를 차지하지만 여전히 작동합니다. 정기적으로 마크 'a'를 사용하면 다음과 같이 이동할 수 있습니다.

vnoremap if ][mb%O'b
vnoremap if ][mc%O'c
...

아아, 이것은 C ++ 함수와 잘 작동하지 않습니다. C 함수와 달리, 들여 쓰기 될 가능성이 높습니다 (클래스 정의에 정의 된 인라인 멤버 함수 및 네임 스페이스 내에서 함수의 기본 들여 쓰기). 그러나 ctags로 얻을 수있는 함수 정의 범위 덕분에 아이디어를 구축 할 수 있습니다. 나는 lh#dev#find_function_boundarieslh-dev 의 기능 에서 그것을한다
Luc Hermitte

3
좋은 접근법. 함수의 맨 위 줄을 안정적으로 찾을 수 있으면로 이동하여 {를 사용 %하여 맨 아래 줄에 도달 할 수 있습니다 . 어떻게 C ++에서 함수가 시작되는지 알 수 없지만 Javascript에서는 제대로 작동합니다.vnoremap if <Esc>?^\s*function<CR>v/{<CR>%o
joeytwiddle

1
마지막 편집에 관하여. CTRL-]커서 아래의 태그로 이동합니다. 현재 기능의 시작이 아닙니다. 도움이되지 않습니다.
Luc Hermitte

새로운 편집에 대하여. 그렇게 간단하지 않습니다. 어려움은 vim이 현재 기능을 아는 것입니다. 정보가 있으면 ctags 도움말이 필요하지 않습니다. ctags에서 정보를 얻는 유일한 방법은 ctags에서 생성 된 jump-to-declaration 명령 을 분석하는 것 입니다. 이 명령이 :linenumber이면 vim은 플러그인에서 수행하는 작업을 수행 할 수 있습니다. 그러나 보장 할 수 없으며, 이러한 명령을 대신 검색 /pattern할 수 있습니다. Vim은 현재 패턴과 일치하는 패턴을 알기 위해 모든 패턴을 테스트 할 수 없습니다. 기능
Luc Hermitte

6

DJ McMayhem의 솔루션 은 함수 경계에 대한 적절한 분석을 수행하기 위해 ctags와 matchit에 의존하는 내 자신을 작성하도록 영감을주었습니다.

어려운 부분은 이미 몇 년 동안 lh-dev 와 lh-tags에 의해 수행되었습니다 .

  • 현재 파일은 올바른 옵션으로 ctags를 통해 구문 분석됩니다
  • 현재 파일에 대해 얻은 태그로 제한된 태그 데이터베이스에서 모든 함수 정의를 찾습니다.
  • DB를 덕분에, 우리는 (물론 모든 기능의 시작 줄 번호를 template하고 inline일부는 ctags를 놓친 할 수있다)
  • 간단한 반복 검색 (이진 검색을 수행 할 수는 있지만 파일이 "짧음"으로되어 있음)을 사용하면 현재 함수의 시작 부분이 발견됩니다.
  • 그리고 matchit 플러그인 덕분에 최종 라인도 발견됩니다. 범용 ctags는 endC, C ++, Python 및 Vim과 함께 사용하여 함수의 끝을 찾는 데 사용할 수 있는 필드를 제공한다는 것을 알았습니다 .

이 알고리즘의 모든 부분은 파일 유형별로 재정의 될 수 있습니다. 즉, 파이썬 함수의 경계 감지는 def들여 쓰기를 검색 하고 분석 할 수 있습니다. 우리는 function자바 스크립트 등을 검색 할 수 있습니다. 즉, 현재 버전은 Java, Vim 및 다른 언어와도 작동합니다 (아직도 일부 작업이 있습니다) 파이썬을 위해해야 ​​할 일)

이제 비주얼 모드 매핑과 운영자 대기 모드 매핑이라는 두 가지 새로운 매핑을 정의합니다.

onoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr>
xnoremap <silent> if :<c-u>call lh#dev#_select_current_function()<cr><esc>gv

에 의존하는 것 :

function! lh#dev#_select_current_function() abort
  let fn = lh#dev#find_function_boundaries(line('.'))
  exe fn.lines[0]
  normal! v
  exe fn.lines[1]
endfunction

나는 당신에게 수백 줄의 코드를 아끼지 않습니다. lh#dev#find_function_boundaries()

DJ McMayhem의 매핑 덕분에

" Note that my vim settings requires two backslashes here instead of one
vnoremap / <esc>/\\%V

우리는 vif/pattern검색 할 수 있습니다pattern현재 함수에서 .

으로 함수를 삭제 dif하거나으로 yank 할 수도 있습니다 yif.

현실적인 C ++ 함수 에 적용했을 때의 모습은 다음과 같습니다 (예 : 0 들여 쓰기).스크린 캐스트 : C ++ 기능 선택


4

함수의 시작과 끝을 찾는 것은 어려울 수 있습니다. 특히 function 키워드가 와 충돌하는 들여 쓰기 스타일이 많은 .

함수가 자체 줄에 닫는 중괄호만으로 끝나는 경우 ( 여기에 나열된 13 가지 스타일 중 10 개와 같이) 다음과 같이 시각적으로 선택할 수 있습니다.

xnoremap if /^\s*}<CR><Esc>V%

거기에서 foo함수 내 에서 검색 하는 것은 다음과 같습니다.

:'<,'>g/foo/#

이를 종합하면 다소 멋진 매핑을 얻을 수 있습니다.

xnoremap if /^\s*}<CR><Esc>V%
nmap <key> vif:g//#<Left><Left>

기능 검색

즉, 시각적 모드 매핑은 아마도 a while또는 a에 의해 쉽게 바보가 될 수 if있으므로 약간의 연마로 이익을 얻을 수 있습니다. 또한 시각적 선택을 유지하는 것은 좋은 생각이 아닙니다.


다음에 찾을 수있는 다음 블록 만 선택합니다. 추가하면 그것은 전혀 작동하지 않는 if, for, while, 등
제임스

3

불완전한 해결책은 주름을 사용하는 것 입니다. 모든 것을 접으십시오 :

set foldmethod=syntax
set foldlevel=0
set foldminlines=0

Vim에게 검색 결과를 위해 접힌 영역을 열지 말라고 지시하십시오.

set foldopen-=search

그런 다음 해당 기능의 접기를 엽니 다 ( zO).

이제, 접힌 영역에서 검색된 텍스트에 대한 모든 적중은 Vim이 접힘 선으로 한 번 점프 한 후 다음 적중으로 진행합니다.

예를 들어, 아래의 경우 :

여기에 이미지 설명을 입력하십시오

접힌 기능은 많은 용도를 가지고 size있지만, n주위의 모든 사용 저를 선도하지 않습니다 size그 기능에 있습니다.


3

또 다른 방법:

  • ctags 등을 사용하여 대상 기능을 찾으십시오.
  • 함수 본문 내에서 커서를 앞으로 이동
  • 현재 블록 내에서만 검색 하려면 Osyo Manga의 검색 연산자 ( vim-operator-user 에 따라 다름 )를 사용하십시오. 예 :

    " configure the plugin (once, vimrc):
     map g/ <Plug>(operator-search)
    
    " 1. use ctags etc. to jump to the beginning of the target function;
    " 2. move cursor inside the function definition, then:
    g/i{
    

... 이제 주어진 프롬프트에서 검색어를 삽입 할 수 있습니다. 히트 n검색 결과가 현재 제공 모션 / 텍스트 객체로 제한하는 방법을 참조하십시오. 이것은 Vim (즉, 합성 가능) 연산자이므로, 훌륭한 함수 텍스트 객체를 가지고 있다면, 검색하기 전에 정의 본문 내부로 이동할 필요가 없지만 g/if, 또는 이와 유사한 smthing을 직접 사용하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.