vim tips - 1. ctags 를 이용한 source navigation

Computing/vim tips 2008. 7. 1. 00:07
처음 vim 을 접했을 때가 version 4 였을 것이다. 그 후로 많은 시간이 흘러서 7.1 까지 오게 되었는데,
처음 내가 남성현님의 홈페이지에서 vim 을 개발용 에디터로 쓰는 팁을 배웠을 때가 생각난다.

유닉스 환경에서 개발을 하면서 vim 을 어떻게 효과적으로 (emacs 부럽지 않게 [각주:1] ) 쓸 수 있는가에 대해서 몇가지 팁을 이 페이지에서 정리하도록 하겠다.

우선, 내가 설명하는 거의 모든 것은 vimrc 설정을 올린 포스팅에 있는 설정들에 다 담겨 있는 내용이다.


1. TAGS 사용하기
1-1. tag 프로그램들
tag 파일은 어떤 함수/변수/상수가 어느 파일에 정의되어 있나를 미리 분석해서 인덱스로 만들어 둔 파일을 일컫는다. 여러가지 태깅 툴이 있는데, 잘 알려진 것으로, ctags, etags, GNU global, exuberant-ctags 가 있다.

ctags 는 tagging 을 하는 매우 오래된 유닉스 툴인데, 오래된 시스템들에는 아마 이것이 깔려 있을 것이다.
기능은 많이 별로다.

etags 는 emacs distribution 의 일부로써 배포되는 tagging tool 이다.

GNU global 은 GNU 프로젝트라는 점이 매력적이지만, 아쉽게도 vim 과는 궁합이 잘 맞지 않는다. 쓸 수 없는 것은 아닌데, tag-stack 이 지원되지 않아서 마치 웹 브라우징을 하듯 소스를 왔다갔다 할 수가 없다. 그러기 위해서는 몇가지 트릭이 필요하긴 한데, 이 글의 주제가 아니므로 넘어가자.

exuberant-ctags. 이것이 내가 vim 사용자들에게 추천하고 싶은 tagging 프로그램이다. 지원하는 언어도 상당히 많다. 자세한 것은 홈페이지를 방문해서 알아 보도록 하자.
http://ctags.sourceforge.net

1-2. Exuberant ctags 설치
가장 간편한 방법은 자신의 리눅스 배포판이 제공하는 패키지를 이용하는 것이다. 우분투를 사용한다면, 간단하게

   sudo apt-get install exuberant-ctags

혹은 위의 url 을 따라 가서 소스를 받은 후 압축을 풀고,

  ./configure
  make
  sudo make install

하면 /usr/local/ 에 설치가 된다. 경로만 설정해주면 OK.

OSX 를 사용하고 있어도 마찬가지로 하면 된다.

1-3. tags 파일 만들기
exuberant-ctags 가 준비 되었고, 분석할 소스가 준비되었다면 이제, tags 파일을 만들 차례이다.
가장 간단한 방법으로, 소스 트리의 루트에서 아래와 같이 입력하면 된다.

  ctags -R .

그러면 디렉토리 . 에서부터 하위 디렉토리를 모두 훑으면서 c/c++ 의 소스, 헤더파일들을 훑으면서 함수/변수/상수들이 어디에 정의되어 있는지를 정리한 tags 파일을 . 디렉토리에 만들어 준다.

여러분의 소스가 약간 복잡해서 태깅 프로그램이 거의 컴파일러 수준의 파싱이나 preprocessing 이 있어야 분석이 가능한 수준의 복잡한 소스라면 모든 definition 들을 다 잡지 못할 지도 모른다.
그러나 몇가지 힌트를 주면 다 분석해 내긴 하는데 그렇게까지 해야 할 일은 잘 없을 것이다.

참고삼아 내가 tag 를 만들 때 쓰는 Makefile 을 올린다. 아, 이것은 GNU find 최신버젼 (내가 쓰는 것은 4.2.32) 이 지원하는 옵션을 쓰므로 오래된 find 에서는 실행되지 않을 것이다. GNU find 도 가져다 컴파일해서 깔도록 하자. 어렵지 않다. ./configure, make, make install 이면 대부분 끝이다.



1-4. vim 에게 tags 파일의 위치 알려 주기
이제, tags 파일도 만들었으므로, vim 이 이 파일을 읽어 올 수 있도록 위치를 알려 주어야 한다.

  :set tags=./tags,~/tags,~/work/tags 블라블라블라

위와 같은 식으로 tags 파일이 있는 위치를 알려 주면 된다. 여러개를 콤마로 구분해서 사용할 수 있다.
vim 은 우선, 가장 처음에 나오는 tags 파일에서 사용자가 지정한 키워드를 찾고, 없으면 그 다음 파일에서, 없으면 그 다음 파일에서... 이런 식으로 검색해 나갈 것이다.

위의 명령은 .vimrc 같은 파일에 넣어 두면 편리하겠다.

1-5. 소스 분석
실제로 ctags 를 쓰는 법을 살펴 보자.
사용되는 키는 두 개이다. ^] (<CTRL> ]) 과 ^T (<CTRL> T) 이다.
소스에서 커서를 definition 을 보고자 하는 identifier 위로 올려 둔 후 ^] 을 누르면 그 identifier 가 정의되어 있는 위치로 점프해 간다. 마치 웹 브라우저에서 링크를 눌렀을 때 처럼. 다시 이전 위치로 가고 싶다면 ^T 를 누르면 된다. 마치 웹 브라우저의 back 버튼을 눌렀을때 처럼 말이다.

시험삼아 아래의 간단한 소스파일을 만들어서 테스트 해 보자.



먼저, tags 파일을 만들고 (ctags -R .) vim 으로 파일을 열고 (vim a.c) tags 파일의 위치를 알려 준 다음 (:set tags=./tags) 커서를 14라인의 mul 위로 옮겨서 ^] 을 누르자 (물론, normal 모드에서). 그럼 커서는 mul() 함수가 정의되어 있는 곳으로 점프해 갈 것이다. 다시 여기서 mul 함수의 argument 의 타입인 mytype 위로 커서를 옮긴 후 ^] 를 누르면 typedef 로 뛰어 간다. ^T 를 눌러 보자. 바로 이전의 위치인 mytype 위로 돌아가고 한번 더 ^T 를 누르면 14번 라인으로 돌아간다.

1-6. 같은 이름의 identifier 가 두개 이상 있을 때
이 때는 먼저 발견되는 identifier 가 정의된 곳으로 뛰어간다. 그리고, vim 화면 아랫쪽에 tag 1 of 2 or more 등과 같이 태그가 더 있다고 알려 준다.

아래의 b.c 를 다시 입력하고, ctags a.c b.c 로 태그를 만든 후 테스트 해 보자.



처음과 마찬가지로 a.c 의 14번 줄에 있는 mul 위에서 ^] 를 누르면, 커서는 a.c 에 정의되어 있는 mul() 로 점프하고, 아래의 스크린샷에서 볼 수 있듯이 vim 화면 아래에 tag 1 of 2 or more 라고 나온다.


이 때, a.c 에 정의된 mul() 외에 다른 mul() 함수를 보고 싶다면, 아래의 명령을 이용해서 매치되는 태그 목록들 사이를 왔다갔다 할 수 있다 :

  :tp   ---> 이전 매치(match)로
  :tn   ---> 다음 매치(match)로

나는 이것을 아래와 같이 매핑해서 쓰고 있다 :

  $ grep :t[pn] .vimrc
  nnoremap <silent> <S-F1> :tp<cr>            " Go to the previous tag
  nnoremap <silent> <S-F2> :tn<cr>            " Go to the next tag

즉, Shift-F1 을 누르면 이전 매치로, Shift-F2 를 누르면 다음 매치로 가는 것이다. 방금 시연해 본 a.c b.c 의 경우에는 Shift-F2 를 누르면 b.c 에 정의된 mul() 함수로 이동하게 되겠다.

가끔 매우 큰 소스 (100만 라인 이상) 를 다룰 때에는 이같은 매치가 몇십개씩 발견되기도 한다. 그럴 때, 일일이 하나씩 옮겨다니면서 매치를 찾아 보기는 어려운 법.

  :ts

를 입력하면 매치되는 정의의 목록이 나온다. 원하는 번호를 입력하면 그리로 곧장 점프하게 된다.

만약 gvim 을 사용한다면 마우스로도 가능하다. 컨트롤-마우스 왼쪽 버튼은 ^] 와 같은 일을 하며, 컨트롤-마우스 오른쪽 버튼은 ^T 와 같은 일을 한다.

이쯤 하니까, 피곤하다. 나머지는 다음 기회에 생각나면 쓰도록 하겠다.


2. Playing with make

http://orchistro.tistory.com/entry/vim-tips-2-make


3. Playing with grep

http://orchistro.tistory.com/entry/vim-tips-3-Playing-with-grep


4. quickfix window

5. navigating through source file(s)


6. help


  1. 사무실의 존경하는 프로그래머 한 분이 이맥스를 매우 잘 사용하신다. 실제로 그 소스에 기여도 하신 분인데, 리챠드 스톨만과 이메일을 주고 받기도 하신 분이다. 그 분이 수 차에 걸쳐서 나로 하여금 이맥스를 사용하도록 설득하려 하셨는데, 자신이 emacs 로 하는 걸 vim 으로 다 하면서 잘 사용하고 있는 걸 보더니 더 이상 권유하지 않으신다. 사실, 딴건 부럽지 않지만 - 오히려 vi 가 더 적은 키 스트로크로 동일한 일을 해 내기도 하지만 - emacs 의 gdb 연결과 shell 모드 (? 용어가 정확한지 모르겠다) 는 좀 많이 부럽다. [본문으로]
: