vim tips - 3. Playing with grep
Computing/vim tips 2009. 1. 4. 01:06Notice : 본 일련의 vim tips 시리즈를 보려면 category 에서 vim-tips 를 눌러 보면 된다.
1. TAGS 사용하기
http://orchistro.tistory.com/entry/vim-tips
2. Playing with make
http://orchistro.tistory.com/entry/vim-tips-2-make
3. Playing with grep
3-1. cscope 와 grep
앞선 section 들에서는 ctags 를 이용해서 소스 파일을 분석하고 따라 가는 방법과, make 를 이용해서 작업 능률을 한층 높이는 방법에 대해서 기록하였다.
그런데, 아직 뭔가 아쉬운 것이 있다. ctags 를 vim 과 함께 쓰면, 함수나 변수의 정의되어 있는 곳으로는 쉽사리 뛰어 갈 수 있는데, 그 역이 되는 일, 즉, 특정 함수를 호출하거나 특정 변수 (전역변수) 를 사용하는 곳을 찾는 방법은 없어 보인다.
여태껏 해 왔던 대로, shell 로 나가서 grep 을 한 다음 그 결과를 눈섭을 찡그리면서 읽고, 다시 vim 에서 해당 파일을 열어서 확인하는 과정을 거쳐야만 할까?
물론, 함수를 호출하는 부분들을 쉽사리 찾아가는 방법이 존재한다. 바로 cscope 를 이용하는 것인데, 내가 사용해 본 바로는, cscope 는 소스의 양이 많아지면 db 생성하는 데만도 수십초씩 걸렸다. 게다가, 인터페이스도 그다지 마음에 들지 않았다. 만약 수십명이 공동으로 작업해서 빠르게 변하는 소스 트리에서 작업한다면, 매번 소스 repository 에서 업데이트를 받을 때 마다 cscope DB 를 새로 빌드해 주어야 하는 귀찮음(!)을 감수해야만 할 것이다. 게다가 한번 DB 를 갱신하는데에 걸리는 시간이란!
그래서 나는 그냥 이전에 하는 대로 grep 을 이용하는 것을 선호하는 편이다.
여담인데, grep 이 왜 grep 인지 혹시 알고 있는가?
'g/re/p'
라는 ed 명령어가 그 이름의 기원이다. 믿거나 말거나... (vim 의 help 페이지에서 본 내용이다.)
혹시라도 이거, 정말 그런지 직접 해 보실 분은, 해 보시도록... grep 의 출력과 매우 흡사한 출력이 나온다.
$ ed foo.c
3456
g/foo/p
.
.
.
q
$
3-2. vimgrep vs. gnu-grep
방금 grep 을 언급했으니 당연히 앞 절의 make 처럼 grep 도 vim 에서 편리하게 쓰는 방법이 존재할 것이라는 눈치를 다들 챘을 것이다.
vim 에서 쓸 수 있는 grep 의 종류는 크게 두 가지이다.
먼저, vim 7 부터 추가된 vim 의 내장 grep 과, 외부의 grep 프로그램이 그것인데, 먼저, 내장 grep 은 좀 느리고, 무엇보다 내가 써 보지 않았기 때문에 별로 권하고 싶지 않다. 그러면, external grep 을 쓰라는 이야기인데, 좋은 grep 프로그램으로 GNU grep 쓰기를 권한다 (아니, gnu grep 을 써야 앞으로 설명할 기능들을 사용할 수 있다.) 내가 알기로 현재 최신 버젼은 2.5.3 인데, -i 옵션에 버그가 (가끔 무한루프 -_-) 있는 것 처럼 보이긴 하지만, 가장 강력한 기능을 지원 (특히 --exclude-dir option) 하므로 그 버젼을 쓰기 바란다 (2.5.1 을 써도 기능 사용에 문제는 없다). 자신의 시스템에 grep 이 없다면, 간단하다. ftp://ftp.gnu.org 에서 소스를 받아서 컴파일해서 설치하면 된다. 컴파일이 귀찮은 분들은 아래 자료를 참조하시라 :
Solaris : http://www.sunfreeware.com
HP-UX : http://hpux.connect.org.uk
AIX : 알아서 설치하세요. -_-;;;
ubuntu : 8.04 부터였던가... 아마 기본으로 깔린 grep 이 GNU grep 2.5.3 이었던 것 같다.
OSX (Leopard) : 2.5.1 이 깔려 있긴 한데, 그냥 위의 ftp 에서 받은 다음에 ./configure;make;make install 하면 문제 없이 잘 깔린다.
windows : cygwin 을 설치하면 grep 도 깔리더라....;;; 써 본 지가 하도 오래 되어서.. ( '-')
3-2. 설치
이제, grep 프로그램이 준비되었으므로 vim 과 grep 의 연결 작업을 해 줄 차례이다. 그러자면, vim 의 grep plugin 을 설치해야 한다. 뭐가 이렇게 복잡하냐고? grep 처럼 강력한 프로그램을 vim 에 통합(?) 시키는데, 이정도의 수고는 해 주어야 하지 않겠는가...;
사실, 별도의 vim plugin 설치 과정은 필요가 없기도 하다. 그렇지만, plugin 설치하는 방법도 알아 보고, 또, 무엇보다, grep plugin 을 쓰는 게 vim 의 grepprg 변수를 세팅해서 쓰는 것보다 편하니 plugin 을 설치하는 방법을 설명하겠다. 물론, 별도의 plugin 없이 사용하는 방법도 이 글 말미에 적어 놓도록 하겠다.
우선, 아래의 파일을 다운로드 해서 여러분의 홈 디렉토리의 .vim/plugin/grep.vim 이라는 이름의 파일로 저장하도록 하자. 디렉토리가 존재하지 않는다면 만들자 : (심심하면 그리 어렵지 않으니 스크립트를 한번쯤 읽어 보는 것도 좋겠다. 내가 수정한 부분은 s:RunGrepRecursive() 함수이다.)
이 플러그인은, 소스에도 나와 있지만, Yegappan Lakshmanan 씨의 스크립트를 약간 수정한 것이다. http://www.vim.org/scripts/script.php?script_id=311 에서 다운로드 받을 수 있다. Yegappan 씨의 스크립트는 gnu 버젼의 find 까지 요구하기 때문에 gnu-find-util 까지 설치해야 하는 부담이 따른다. 물론 여러분이 사용하는 운영체제가 리눅스라면 당연히 gnu-find 가 설치되어 있겠지만, 그 외의 운영체제에서는 find-util 을 또 깔아 주어야 하는 불편함이 있다.
그래서 위에 리스팅 된 스크립트는 내가 find 에 의존하지 않도록 스크립트를 약간 손본 것이다.
만약 여러분이 리눅스에서만 작업을 하신다면, 혹은 GNU find-util 이 설치되어 있는 환경에서만 작업을 하신다면 Yegappan 씨의 스크립트를 그대로 사용해도 좋겠다. Yegappan 씨의 스크립트를 사용하면서 유용한 옵션 중의 하나만 소개하도록 하겠다. 자세한 내용은 스크립트를 읽어 보거나 해당 홈페이지를 방문해서 알아 보도록 하자. :
let g:Grep_Skip_Dirs='.svn'
그리고 아래의 내용을 ${HOME}/.vimrc 에 넣어 두자.
"내가 설치한 gnu grep 이 있는 경로. 일반적으로 /usr/local/bin/ 에 설치되므로 이와 같이 해 두었다.
let Grep_Path = '/usr/local/bin/grep'
let Grep_OpenQuickfixWindow = 1
let Grep_Default_Options = '-rn'
이왕지사 .vimrc 를 손대는 것, 아예, 키보드 매핑까지 해 두자. 아래의 라인도 ${HOME}/.vimrc 에 추가하자 :
nnoremap <silent> <F9> :Rgrep<CR>
플러그인을 어떻게 설치하는지 설명하는 것을 깜빡 잊어버렸으나, 앞에서 이미 넌지시 설명해 버렸다. 간단하다. pluginname.vim 파일을 ${HOME}/.vim/plugin/ 디렉토리에 복사해 넣어 주면 된다. 그럼 다음번 vim 을 시작할 때, vim 은 플러그인을 읽어들이게 될 것이다.
3-3. 활용
이제 활용을 위한 모든 준비는 끝났다. vim 을 열고 위에서 키맵을 해 둔 것처럼 <F9> 키를 눌러 보자.
아래와 같이 어떤 패턴을 찾을 것이냐는 질문이 화면 아래쪽에 나올 것이다 :
쉽다. 여기에 원하는 패턴을 입력해 주고 엔터키를 치면 된다. 어디 한번 해 보자. (( 너무 친절하게 설명해 주는 것 같다 -_-;;;;
그리고, 아래 그림에서 보듯이, 원하는 단어 위에서 <F9> 키를 누르면 일일이 찾고자 하는 패턴을 입력할 필요 없이 커서가 위치해 있던 단어가 "Search for pattern: " 에 입력되어 나온다 :
화면에서 볼 수 있듯이 커서가 있던 자리의 단어가 <F9> 를 눌렀을 때 자동으로 표시된다.
찾고자 하는 패턴을 입력하고 엔터키를 치면 검색을 시작할 디렉토리를 묻는데, current working directory 가 기본으로 세팅되어서 나온다. tab 키로 자동완성이 된다.
디렉토리를 입력한 후에는
Search in files matching pattern: *
이라고 나오는데, 이것은, 검색을 실시할 파일명의 패턴을 입력하라는 것이다. 만약 여러분이 *.c 파일에서만 검색을 하고자 한다면 .c 를 입력해서 아래처럼 보이게 만들어 주면 된다 :
Search in files matching pattern: *.c
그리고 엔터키를 입력하면, grep option 을 입력하라는 메뉴가 뜬다.
Grep options: -rn
만약 위쪽에서 내가 추천한 것 처럼 자신의 .vimrc 파일에 아래의 라인을 입력해 둔 분이라면 -rn 이 기본으로 나타나게 될 것이고, 그렇지 않으면 그냥 공란으로 나올 것이다. 이 곳에 grep 에 줄 option 을 적어 주면 된다.
let Grep_Default_Options = '-rn'
주의할 것은, -n 옵션이 빠져서는 안된다는 것이다.
왜냐하면, vim 이 grep 의 -n 옵션으로 출력되는, 파일에서 패턴이 발견된 라인의 정보를 보고서 해당 파일을 자동으로 열어 주고, 그 라인으로 점프해 가기 때문에 -n 옵션을 주어야만 grep+vim 을 편리하게 사용할 수 있기 때문이다.
여기서 잠깐, 유용한 grep option 두가지를 알아보고 넘어가자:
-i : 대/소문자 구분을 하지 않는다.
-w : 정규표현식 < > 로 패턴을 둘러싼 것과 같은 효과가 난다. 즉, 예를 들어서 main 을 -w 옵션을 주고서 grep 했다면 main 만 grep 에 걸리고, main2, main_function 등은 걸리지 않는다.
필요에 따라 "Grep options: " 라고 묻는 라인의 뒤에 옵션 추가만 해 주면 된다 :
필요에 따라서 옵션을 추가했으면 엔터키를 누르자.
뭔가를 한참 뒤진(?) 후에 아래처럼 quick fix 윈도우가 화면에 나타나게 된다 :
화면을 자세히 보면, 패턴 정보가 나오고, 그 아랫줄에 검색에 사용된 명령어가 나온다.
검색되어 나온 결과 사이를 왔다갔다 하는 방법은 앞전의 Playing with make 게시물에 잘 나와 있으니 그 게시물을 참조하기 바란다.
3-4. GNU grep 사용 팁 약간
언제나 그렇듯, 가장 좋은 사용 설명서는 man page 이다. 수시로 man command 를 해서 심심할 때 마다, 잠이 오지 않을 때 마다 읽어 보도록 하자.
일단, quick start 로 몇가지 것들만 정리해 주겠다.
3-4-1. 환경변수 GREP_OPTIONS
그렇다. gnu grep 은 환경변수 GREP_OPTIONS 에 세팅되어 있는 값을 grep 을 실행할 때마다 옵션에 자동으로 붙여 주는 일을 해 준다.
나는 주로 아래와 같은 값으로 세팅해 두고 생활하고 있다 :
shawn.castepo:~/Sources/httpd-2.2.4/srclib/apr/strings$ echo ${GREP_OPTIONS}
--exclude-dir=.svn -I --color
음.. grep tip 을 이야기하겠다고 section 까지 만들었건만, 더 이상 할 이야기가 없다. -ㅅ-;;
r, n, w, i 는 이미 앞에서 설명해 버렸고...
아무튼, grep plugin 과 gnu grep 을 이용해서 보다 편안한 개발자의 일상을 누리시길 바란다.
good luck!
4. quickfix window
5. navigating through source file(s)