(미완성)평범한 개발자의 C 프로그래밍 이야기

emacs 패키지

svn-status(update, diff, revert 등등), gtags, gdb, tramp, 컴파일 및 에러 이동, eshell,


C프로그래밍에 필요한 emacs 기능들을 몇가지 소개하겠습니다. emacs는 사실 편집기라고 생각하기 어색할 정도로 기능이 많습니다. 하드웨어 부팅만 안할뿐이지 운영체제가 하는 일을 거의 다 할 수 있습니다. 웹 브라우징도 되고 스케줄 관리, 통합 개발 툴, 터미널, e-메일, ftp, telnet, ssh 등등 뭐가 지원 안되는지를 알기 힘듭니다. GUI기반 통합개발툴처럼 개발 환경을 꾸밀수도 있습니다. 제가 익숙하지 않아서 못쓸 뿐이지 개발에 필요한 기능은 모두 있다고 생각하면 됩니다. GUI 개발툴처럼 버전이 달라질때마다 동작이 달라지거나, 추가 비용이 들어가는 일도 없습니다. 한번 익숙해지면 운영체제에 상관없이 어디에서나 똑같은 개발 환경을 무료로 꾸밀 수 있습니다.

그래서 제가 사용하는 기능들만 소개합니다만 emacs의 기능 중에 아주 기본적인 기능 중에 일부분이라고 생각하시면 됩니다. 여기서 소개하는 몇가지 기능들이 익숙해지시면 조금씩 다른 기능들을 시험해보시기 바랍니다. 시간이 흐를 수록 더 생산성이 높아지는 것을 경험하실 겁니다. 

또한 비슷한 기능을 가지면서 더 편리한 것들이 있을 수 있습니다. emacs에 이런 기능이 있다라는 것을 확인하시고, 자신에게 더 잘 맞는 라이브러리를 찾아보시기 바랍니다.


1.3.1 psvn 라이브러리

emacs에서 subversion을 사용하기 위한 라이브러리중에 psvn.el 이라는 것이 있습니다. 여러개의 파일을 한꺼번에 처리할 수 있고, subversion 개발자가 직접 참여해서 개발된 라이브러리이므로 안정적이고 편리하게 subversion을 사용할 수 있습니다. 

emacs를 실행한 후 M-x svn-status를 입력합니다. 실행할 디렉토리를 묻는 메시지가 나오면 원하는 디렉토리를 입력합니다. 이 디렉토리는 이미 svn으로 관리되고 있는 디렉토리어야 합니다. 파일의 리스트가 나타날 것입니다.

파일 리스트가 출력되면 svn의 기능을 동일하게 사용할 수 있습니다. 다음은 제가 주로 사용하는 명령어입니다.

‘g’
- svn-status를 다시 실행해서 정보를 갱신합니다.

‘U’
- svn update 명령을 실행합니다.

‘C-u U REVISION RET’
- 특정 리비전으로 업데이트합니다.
Update the files to ‘REVISION’.
‘M-- U’
- 선택된 파일들만 업데이트합니다.

‘m’
- 커서가 위치한 파일을 선택합니다.

‘u’
- 커서가 위치한 파일의 선택을 해지합니다.

‘c’
- 선택된 파일들이나 커서가 위치한 파일을 커밋합니다. 명령을 실행하면 새로운 버퍼가 열리고 로그 메시지를 입력할 수 있습니다. 메시지 입력을 종료하려면 C-c C-c를 입력합니다.

`=’
- 선택된 파일이나 커서가 위치한 파일에 svn diff를 실행합니다. 새로운 버퍼가 열리고 diff 결과가 출력됩니다.

`C-u = REVISION RET’
- 특정 리비전과 diff를 실행합니다.

'i'
- svn info를 실행합니다.

'r'
svn revert를 실행합니다.

'a'
- svn add --non-recursive를 실행합니다.
A
- svn add'를 실행합니다.
+
- svn mkdir를 실행합니다.
R
- svn mv를 실행합니다.

C
- svn cp를 실행합니다.

D
- svn rm를 실행합니다.
b
- svn blame를 실행합니다.

‘l’
- log를 출력합니다.


로그를 출력하면 각 리비전별로 어떤 파일들이 수정되었는지가 나타납니다. 파일 이름이 있는 줄에 커서를 대고 실행할 수 있는 명령어가 있습니다.

'엔터키'
- 파일을 엽니다.

'='
- 해당 리비전과 그 이전 리비전의 diff 출력

psvn에도 subversion 서버에서 체크아웃할 수 있는 기능이 있습니다. M-x load-library를 실행한 후 라이브러리 이름을 묻는 메시지가 나오면 psvn을 입력압니다. 그리고 M-x svn-checkout을 실행하면 됩니다. 그 외에 M-x svn-까지 입력하고 탭키를 누르면 다양한 명령들이 있다는 것을 알 수 있습니다.

더 자세한 설명과 그외 기능들의 목록은 psvn.el 파일을 열어서 확인할 수 있습니다.

1.3.2 GNU global 프로그램과 gtags 라이브러리

소스 태깅을 위한 다양한 라이브러리가 있습니다. cscope용으로 xcscope라는 라이브러리가 있지만 저는 global이라는 태깅 프로그램을 주로 사용하므로 gtags라는 라이브러리를 사용합니다. global 5.9.3 버전을 기준으로 설명하겠습니다.

gtags를 사용하기 위해서는 먼저 다음 코드를 .emacs에 추가해줍니다. /usr/share/emacs/site-lisp/global은 global의 패키지에 포함된 gtags.el의 위치입니다. 다른 위치에 gtags.el를 저장하셨다면 수정해서 사용하시기 바랍니다.

;; GNU GLOBAL for source tag
(setq load-path (cons "/usr/share/emacs/site-lisp/global/" load-path))
(autoload 'gtags-mode "gtags"
  "Minor mode for browsing source code using GLOBAL" t)
(add-hook 'c-mode-common-hook
          (lambda () (gtags-mode 1)))

그리고 소스가 있는 디렉토리에서 태그 파일을 생성해야합니다. global 프로그램을 설치하셨다면 gtags라는 실행파일이 설치됩니다. 터미널에서 gtags파일을 실행하면 실행된 디렉토리에 GTAGS, GPATH, GRTAGS 등의 파일이 생성됩니다. 편집할 소스는 반드시 이 파일들이 있는 디렉토리의 하위 디렉토리에 있어야 합니다. 여기까지가 gtags 라이브러리를 사용하기 위한 준비과정입니다.

emacs를 실행하고 gtags-mode로 진입하면 그때부터 gtags를 사용할 수 있습니다. M-x gtags-mode를 실행하면 gtags-mode로 진입합니다. .emacs에서 c-mode로 진입할때마다 자동으로 gtags-mode로 진입하도록 설정했으므로 .c 파일을 열면 자동으로 gtags-mode가 되어있을 것입니다. 

gtags-mode에서는 다음 명령어들을 사용할 수 있습니다. M-x를 입력한 후 원하는 명령어를 입력하면 됩니다.

gtags-find-tag (단축키 C-.)
- 태그를 찾습니다. 태그를 찾게되면 새로운 버퍼가 나타나면서 검색된 태그의 위치가 나타납니다. 여러개일때는 원하는 위치로 커서를 옮기고 엔터키를 누르면 해당 위치로 이동합니다.

gtags-find-rtag
- 검색하고자하는 태그를 참조하는 소스를 검색합니다. printf를 입력하면 printf를 호출한 함수들의 목록이 나타납니다.

gtags-pop-stack (단축키 C-*)
- 이전 화면으로 넘어갑니다. 태그를 검색하고 여러개의 위치 중에 특정 위치로 넘어갔을 때 이 명령을 실행하면 다시 선택 버퍼로 넘어갑니다. 그리고 다른 위치를 선택할 수 있습니다.

그 외에도 다양한 명령이 있습니다. M-x gtags-를 입력하고 탭키를 누르면 모든 명령이 출력됩니다. 텍스트를 검색하는 gtags-find-with-grep, 파일을 찾는 gtags-find-file 등 다양한 명령이 있습니다.


1.3.3 Grand Unified Debugger (GUD)

gdb의 가장 큰 문제점이 손으로 해야 할 일이 너무 많다는 것 같습니다. 저도 그래서 ddd같은 gdb의 프론트엔드 제품을 자주 사용합니다. emacs 사용자들도 비슷한 생각을 한것 같습니다. GUD는 gdb를 ddd와 유사하게 사용할 수 있는 모드를 제공합니다.

emacs안에서 gdb를 실행시키는 방법은 M-x gdb입니다. 터미널에서 gdb를 실행시키는 것과 같은 화면이 출력됩니다. 사용법도 터미널에서 gdb를 사용하는 것과 동일합니다.

이번에는 다른 방식으로 gdb를 실행시켜 보겠습니다. 우선 .emacs 파일에 다음 코드를 추가합니다.

(setq gdb-many-windows t)

그리고 M-x gdb를 실행해보시면, 자동으로 지역변수, 스택 프레임, 브레이크 포인트, 소스를 보여주는 창이 생깁니다.

"실행 이미지 넣을 것"

주로 저는 여기에 변수 출력 창 하나를 더 실행해서 사용합니다. 프로그램 소스가 있는 창으로 이동한 다음 보이길 원하는 변수에 커서를 가져갑니다. 그리고 C-x C-a C-w를 입력하면 speedbar라는 새로운 창에 Watch Expressions이라는 버퍼가 생성되면서 변수와 변수 값이 보입니다. 변수의 값이 바뀌면 빨간색으로 출력되는 것도 쓸모가 있습니다.

Watch Expression 버퍼에서 변수의 값을 바꾸려면 해당 변수가 있는 줄로 이동한 다음 엔터키를 누르면 됩니다. 새로운 값을 입력하라는 메시지가 나오고 새로운 값을 입력합니다. 곧바로 바뀐 값이 보이지는 않습니다. speedbar가 아닌 다른 창을 선택하면 새로운 값이 보이는데, 이것은 아마도 리눅스의 윈도우 매니저의 문제로 보입니다. 어쨌든 값을 바꾸고 Alt+Tab을 눌러서 gdb가 실행된 창으로 옮겨오면 새로운 값이 보입니다.

또 Watch Expression 버퍼에서 구조체를 볼 때, 구조체의 내부 변수들을 보고 싶을 때는 라인 왼쪽 끝에 있는 +표시로 커서를 옮기고 스페이스바를 누릅니다. 그러면 곧바로 구조체가 펼쳐지지 않고, Alt+Tab을 눌러서 다른 창으로 옮겼을 때 펼쳐진 모습이 보입니다. 내부 변수의 값을 바꾸는 것은 다른 변수들의 값을 바꾸는 것과 동일합니다.

gdb의 실행이 끝났으면 gdb의 실행 창에서 q를 입력합니다. 터미널에서 gdb를 종료시키는 것과 동일합니다. 그러면 다른 창들이 자동으로 닫히고 소스 편집 창만 남게됩니다. 

emacs의 메뉴바에서 GUD를 클릭하시면 그 외에도 많은 기능을 볼 수 있습니다. GUD는 GUI적인 환경을 제공하므로 더 많은 기능을 사용하기 위해서는 마우스를 같이 이용하시기 바랍니다. gdb가 제공하는 거의 모든 기능을 간편하게 사용할 수 있습니다.


1.3.4 tramp

원격 서버에 저장된 파일을 편집하기 위한 라이브러리입니다. 터미널에서 ssh나 telnet으로 서버에 접속하지 않고 emacs안에서 로컬 머신의 파일을 여는 것과 같은 방식으로 원격 파일을 열 수 있습니다. 그래서 라이브러리 이름이 tramp(Transparent Remote Access, Multiple Protocols)입니다. 

최신 버전의 emacs는 tramp를 기본적으로 내장하고 있습니다. 다음 명령으로 서버에 있는 파일을 열 수 있습니다.

M-x M-f /ssh:myid@myserver:

M-x M-f 는 파일을 여는 명령입니다. tramp는 로컬 머신의 파일을 여는 것이나 동일한 인터페이스를 제공한다는 것을 알 수 있습니다. ssh는 접속에 사용할 프로토콜입니다. telnet도 사용가능합니다. myid는 서버에 접속할 아이디이고, myserver는 서버의 호스트 네임이나 IP주소입니다. 마지막에 :를 입력하는 것을 잊지 말아야 합니다.

여기까지 입력하고 실행하면 패스워드를 물어봅니다. 패스워드를 입력하면 서버에서 홈 디렉토리가 열립니다. 이때부터는 로컬 머신에서 emacs를 사요하는 것과 동일합니다.

접속 프로토콜을 ssh로 사용할 일이 많다면 다음 코드를 .emacs에 추가해서 기본 프로토콜을 ssh로 설정할 수 있습니다.

(setq tramp-default-method "ssh")

이렇게 기본 프로토콜이 설정되면 다음과 같이 프로토콜을 생략했을 때 자동으로 ssh를 사용하게 됩니다.

M-x M-f /myid@myserver:
그리고 현재 사용하는 아이디와 접속 아이디가 같다면 접속 아이디까지도 생략할 수 있습니다.

M-x M-f /myserver:
다음과 같이 특정 파일을 곧바로 편집할 수도 있습니다.
M-x M-f /myserver:.emacs
M-x M-f /myserver:env/bashrc
tramp를 사용하기 위해서 가장 중요한 사항이 있습니다. 서버의 기본 쉘을 bash로 설정하는 것입니다. tramp는 서버에서 전송되는 메시지를 가공해서 emacs에 출력하는 방식으로 동작합니다. 만약 bash외의 다른 쉘이 사용된다면 tramp는 메시지를 인식하지 못하고, 잘못 동작하게 됩니다. 동작이 정지한다거나 아무 출력도 나오지 않는 등의 문제가 생길 수 있습니다. 그럴때는 C-g를 입력해서 접속 시도를 취소하고 쉘 프롬프트를 확인하시기 바랍니다. 이전 장에서 설정한 호스트네임과 아이디를 출력하는 정도의 프롬프트라면 문제없이 사용할 수 있을 것입니다.
그리고 구형 유닉스 머신에도 접속이 안될 경우가 있습니다. 그럴때는 ssh대신에 telnet을 사용해보거나 접속시 아이디를 물어보는 login: 메시지가 출력되는지 확인해야 합니다. login: 외에 다른 메시지가 출력되거나 ssh가 불안정해서 tramp를 사용하지 못하는 경우가 있습니다.

1.3.5 compile
emacs에서 컴파일을 실행하고, 결과도 emacs에서 확인할 수 있습니다. 
컴파일은 M-x compile 명령으로 실행할 수 있습니다. M-x compile 명령을 실행하면 Compile command: make -k 라는 메시지가 출력됩니다. 기본적으로 make -k 를 실행하겠다는 의미입니다. Makefile을 작성해놓았으면 그대로 엔터키를 눌러서 make -k가 실행되도록 합니다. -k 외에 -s 등 다른 옵션을 지정할 수도 있습니다. make 명령을 실행하지 않고 메시지를 지운 후 gcc a.c 등으로 컴파일러를 호출할 수도 있습니다.
다음과 같이 .emacs를 설정하면 F9키를 compile을 위한 단축키로 설정할 수 있습니다.
(global-set-key [f9] 'compile)
compile 명령을 실행하고 빌드가 완료되면 *compilation*이라는 버퍼가 나타납니다. 빌드에 아무런 문제가 없으면 마지막에 'Compilation finished at 날짜'라는 메시지가 출력됩니다. 에러나 경고가 발생했다면 컴파일러가 출력한 에러 메시지가 출력되고 마지막으로 'Compilation exited abnormally with code 에러번호 at 날짜'라는 메시지가 출력됩니다.
각 에러 메시지는 에러가 발생한 소스 파일과 줄 번호로 시작합니다. 여기에 마우스를 클릭하거나 엔터키를 누르면 해당 위치로 자동으로 이동합니다. 그리고 previous-error, next-error 명령도 사용할 수 있습니다. previous-error 명령은 현재 보다 이전에 발생한 에러나 경고의 위치로 이동합니다. next-error 명령은 다음 위치로 이동합니다.
다음 코드를 .emacs에 추가해서 단축키 F7, F8로 에러 위치들을 살펴볼 수 있도록 설정하면 더 편리하게 소스를 확인할 수 있습니다.
(global-set-key [f7] 'previous-error)
(global-set-key [f8] 'next-error)   

1.3.6 eshell
emacs에서 터미널을 사용할 수 있는 라이브러리는 shell, term, eshell 등이 있습니다. 저는 주로 eshell을 사용합니다. eshell은 실제 터미널 환경을 Emacs LISP으로 다시 구현한 것입니다. 따라서 어떤 운영체제에서든지 동일하게 동작하므로 윈도우나 구현 유닉스와 같이 터미널이 불편한 환경에서도 편리하게 사용할 수 있습니다. 유니코드나 하이라이팅이 지원되므로 실제 터미널과 별 차이없이 편리하게 사용할 수 있습니다.
실행방법은 M-x eshell 입니다.

git 사용자를 위한 magit도 있습니다.

magit에 대한 내용은 추후 추가하겠습니다.

댓글

댓글 본문
작성자
비밀번호
graphittie 자세히 보기