몇 개의 레이어가있는 약간 큰 코드베이스에는 vim 또는 명령 줄에서 기본 클래스에서 파생 된 모든 클래스를 찾는 방법이 있습니다 수업? grep은 옵션이지만 grep이 색인을 생성하지 않기 때문에 속도가 느릴 수 있습니다.C++, cscope, ctags 및 vim :이 클래스에서 상속받은 클래스 찾기
답변
어느 cscope의도 ctags를 우리가 직접 상속을 처리 할 수 있지만 파생 클래스는 또한 색인하고 있기 때문에 그 문제를 해결하려면 상대적으로 쉽게 입니다 - 명령을 두드리는하여 수행됩니다. "C 기호"Foobar
을 찾고 cscope의에서
cscope의
은 일반적으로 원래의 클래스 그것을 상속 및 클래스를 나열합니다. 검색은 데이터베이스에 대해 수행되므로 번개가 빠릅니다.
또는, Foobar
에서 상속 만 클래스를 나열하는 :.*Foobar
같은 패턴으로 cscope의의 egrep을 검색하는 기능을 사용할 수 있습니다.
그래서 "이 클래스에서 상속 한 클래스 찾기"명령을 사용하지 않아도 많은 노력을 기울이지 않아도 작업을 완료 할 수 있습니다.
ctags를
ctags를 사용하면 --fields=+i
와 상속 정보를 포함 할 수 있지만이 정보는 빔에서 직접 사용할 수 없습니다. inherits
필드는 Vim에서 구문 분석되므로 taglist()
을 사용하여 빠르고 더러운 솔루션을 작성할 수 있습니다.
ACK, AG
그 두 프로그램이 더 많거나 적은 그렙처럼 작동하지만,이 소스 코드에서 검색으로 대상으로는 그래서 그들은 그렙에 비해 정말 빠릅니다. 관련 라인은 여기
:grep :.*<C-r><C-w><CR>
: 내 빔 설정에서
는:grep
은 같을 것이다 커서 아래에있는 클래스에서 파생 된 클래스 검색, 그래서 기본 grep
대신 ag
프로그램을 실행하도록 설정되어 내 ~/.vimrc
에서 : if executable("ag")
set grepprg=ag\ --nogroup\ --nocolor\ --ignore-case\ --column
set grepformat=%f:%l:%c:%m,%f:%l:%m
endif
': Ggrep' 명령으로 fugitive와 vim을 사용하여 속도를 높이고 있습니다. 이 개선은 코드가 내 게시물에서 언급되지 않은 git repo가되어야하지만 또 다른 대안입니다. –
lh-cpp에서 나는 :Children
명령을 정의합니다. 그것은 ctags 데이터베이스에 의존하고 결과적으로 매우 제한적입니다.
두 가지 옵션 매개 변수가 필요합니다. 찾을 수있는 네임 스페이스 (피할 수있는 방법을 찾지 못했습니다)와 상위 클래스의 이름 ->:Children [!] {namespace} {parent-class}
입니다.
이 명령은 최대한 많은 정보를 캐시하려고합니다. 따라서 ctags 데이터베이스에서 관련 정보가 변경되면 캐시를 업데이트해야합니다. >:Children!
나는 정력이 모든 자식 클래스를 나열 할 수있는 올바른 도구입니다 생각하지 않습니다. 대신 doxygen을 사용하여 소스 코드에 대한 문서를 생성하는 것이 좋습니다.doxygen이 약간의 시간을 필요로하지만 모든 클래스에 대해 문서/다이어그램을 사용할 수 있으며 이는 분명하고 빠릅니다.
이것은 그래픽 인터페이스를 사용하여 개발 중이라고 가정합니다. 때로는 devbox가 doxygen 파일을 호스트 할 웹 서버를 가지고 있어야한다는 것을 의미하는 ssh를 통해 minty (cygwins 터미널)를 사용해야합니다. –
네, 그렇습니다. 그리고 이미 SSH를 제공하고있는 Linux/Unix 서버는 웹 서버를 쉽게 배포 할 수 있으며 doxygen 페이지 내에 간단한 검색 엔진을 제공하는 웹 서버에서 PHP를 활성화하는 것이 좋습니다. – Chandler
Eclipse와 SlickEdit에는 클래스에 대한 상속 트리와 재정의 된 메소드의 트리 목록을 나열하는 방법이 있습니다. Eclipse에서 Type Hierarchy라고하며 OO 언어로 코딩 할 때 IDE에서 가장 유용한 기능 중 하나입니다. Doxygen은 정말 유용하지만, "Type Hierarchy"를 간략하게 살펴볼 필요가있을 때 과잉입니다. –
상속 정보 (see the --fields option)를 사용하여 Exuberant CTags로 태그 파일을 빌드하면 다음 스크립트가 작동합니다. 클래스 이름 (예 : :Inherits Foo
) 또는 정규 표현식을 사용하는 :Inherits
명령을 추가합니다.
:tag
명령과 마찬가지로, 정규식을 사용하여 검색하려면 '\'문자를 앞에 붙여야합니다. :Inherits \Foo.*
.
:ll
, :lne
, :lp
등으로 검색 한 결과가 창 위치 목록에 저장됩니다. VIM은 스크립트가 내가 선호하는 태그 목록을 수정하는 것을 허용하지 않습니다.
내가 taglist()
을 사용하지 않는 이유가 궁금하다면 큰 태그 파일의 경우 taglist()
이 매우 느리기 때문입니다. 원래 게시물의 버전이 taglist()
이었습니다. 궁금한 점이 있으면 편집 기록을 탐색 할 수 있습니다.
" Parse an Exuberant Ctags record using the same format as taglist()
"
" Throws CtagsParseErr if there is a general problem parsing the record
function! ParseCtagsRec(record, tag_dir)
let tag = {}
" Parse the standard fields
let sep_pos = stridx(a:record, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['name'] = a:record[:sep_pos - 1]
let tail = a:record[sep_pos + 1:]
let sep_pos = stridx(tail, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
" '/' will work as a path separator on most OS's, but there
" should really be an OS independent way to build paths.
let tag['filename'] = a:tag_dir.'/'.tail[:sep_pos - 1]
let tail = tail[sep_pos + 1:]
let sep_pos = stridx(tail, ";\"\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['cmd'] = tail[:sep_pos - 1]
" Parse the Exuberant Ctags extension fields
let extensions = tail[sep_pos + 3:]
for extension in split(extensions, '\t')
let sep_pos = stridx(extension, ':')
if sep_pos < 1
if has_key(tag, 'kind')
throw 'CtagsParseErr'
endif
let tag['kind'] = extension
else
let tag[extension[:sep_pos - 1]] = extension[sep_pos + 1:]
endif
endfor
return tag
endfunction
" Find all classes derived from a given class, or a regex (preceded by a '/')
" The results are placed in the current windows location list.
function! Inherits(cls_or_regex)
if a:cls_or_regex[0] == '/'
let regex = a:cls_or_regex[1:]
else
let regex = '\<'.a:cls_or_regex.'\>$'
endif
let loc_list = []
let tfiles = tagfiles()
let tag_count = 0
let found_count = 0
for file in tfiles
let tag_dir = fnamemodify(file, ':p:h')
try
for line in readfile(file)
let tag_count += 1
if tag_count % 10000 == 0
echo tag_count 'tags scanned,' found_count 'matching classes found. Still searching...'
redraw
endif
if line[0] == '!'
continue
endif
let tag = ParseCtagsRec(line, tag_dir)
if has_key(tag, 'inherits')
let baselist = split(tag['inherits'], ',\s*')
for base in baselist
if match(base, regex) != -1
let location = {}
let location['filename'] = tag['filename']
let cmd = tag['cmd']
if cmd[0] == '/' || cmd[0] == '?'
let location['pattern'] = cmd[1:-2]
else
let location['lnum'] = str2nr(cmd)
endif
call add(loc_list, location)
let found_count += 1
endif
endfor
endif
endfor
catch /^OptionErr$/
echo 'Parsing error: Failed to parse an option.'
return
catch /^CtagsParseErr$/
echo 'Parsing error: Tags files does not appear to be an Exuberant Ctags file.'
return
catch
echo 'Could not read tag file:' file
return
endtry
endfor
call setloclist(0, loc_list)
echo tag_count 'tags scanned,' found_count 'matching classes found.'
endfunction
command! -nargs=1 -complete=tag Inherits call Inherits('<args>')
내가 그렇게, cscope를하고 ctags를이 정규식을 기반으로 생각하지만, IDE –
같은 구문하지 않는 당신이 생각 해 봤나 [긍정] (http://beyondgrep.com/), [의 Ag 실버 서퍼] (https://github.com/ggreer/the_silver_searcher) 또는 [git grep] (http://git-scm.com/docs/git-grep)? 이들은 일반적으로 grep보다 훨씬 빠릅니다. –
나는 이것에도 관심이있다. 현재 Eclipse와 SlickEdit을 사용하고 있습니다. Eclipse에서이 기능을 유형 계층 구조라고합니다. 이클립스 기능을 Vim에 통합 한 eclim이라는 프로젝트가있다. Vim에서 가장 친숙한 프로그램이다. 불행하게도 eclim은 많은 RAM을 필요로하며, Windows에서 끊임없이 충돌한다. –