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.