· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Emacs Auto Completion Quick Note

이맥스(Emacs) 자동완성 초간단 사용법

용어의 일관성을 위해
"인텔리센스(intellisense)"는 리스트를 보여주는 자동완성을 의미하고
"심볼완성(symbol completion)"은 리스트를 안 보여주는 자동완성을 의미하는 것으로 하겠습니다.

그리고 Emacs에는 자동완성이라고 일컬어지는 auto completion, smart completion, intellisense 등등
종류가 너무 많기 때문에 cedet 패키지에 있는 semantic을 중심으로 설명합니다.

Emacs에서 자동완성은 설정도 약간 까다롭고 맨 처음 자동완성이 될 때는 캐쉬 파일을 생성해야 되서
약간 느리기도 하지만 다양한 종류의 자동완성 기능이 있고 사용자 취향에 맞게 설정 할 수 있어서 정말 강력합니다.
일례로 VS에서 MFC로 프로그래밍을 어느 정도 하다 보면 멤버함수 같은 것을 거의 기억 할 수 있기 때문에
그 분이 오셔서 정말 신내린 코딩(?)을 할 때는 오히려 인텔리센스 기능이 거치적거려서 꺼놓고 코딩하는 경우도 있으실 것입니다.
이럴 경우에도 Emacs는 아주 유연한 대처가 가능합니다.

1. 준비

1) cedet 패키지 설치
http://cedet.sourceforge.net/
1.0pre4 버전에서는 C++ namespace를 쓸 경우 자식클래스에서 부모클래스 멤버가 자동완성에 안나타나므로 cvs 버전 사용하세요.
cvs -d:pserver:anonymous@cedet.cvs.sourceforge.net:/cvsroot/cedet login
암호 물어보면 엔터
cvs -z3 -d:pserver:anonymous@cedet.cvs.sourceforge.net:/cvsroot/cedet co -P cedet
설치경로/INSTALL 파일을 참고해서 컴파일 및 .emacs에 추가하라고 한 것 추가해 줍니다.

참고:
데비안 lenny에서는 emacs-snapshot과 기존 저장소의 cedet 패키지가 충돌하므로 저장소 cedet패키지는 제거하고 cvs 버전 수동 설치하세요.
(lenny가 stable이 된 이후로는 미확인 상태)

2) .emacs에 다음 추가
;; 현재(2009년 4월 12일) cvs 버전에서는 아래가 없어도 자동완성이 되었음
;; (require 'semantic-ia) 
;; (global-semanticdb-minor-mode 1)

;; 캐쉬 파일 만들어 두는 곳
;; 시스템 라이브러리는 같은 경우 거의 변경될 일이 없기 때문에
;; 한 번 캐쉬되면 다음 번 자동완성에서는 빠르게 사용 가능합니다.
;; 폴더 "~/.emacs.d/#semanticdb.cache#" 는 적당히 원하는 것으로 꼭 만들어 주어야 합니다.
(setq semanticdb-default-save-directory "~/.emacs.d/#semanticdb.cache#")

;; 자동완성에 쓸 헤더 파일 경로 적는 예
;; 이것이 있어야 #include 한 헤더파일의 내용도 자동완성에 나타납니다.
(semantic-add-system-include "/usr/include/gtkmm-2.4/" 'c++-mode)

2. 인텔리센스 (Intellisense)

2.1. 종류

emacs 인텔리센스에는 여러 가지가 있습니다.
(cedet 버전에 따라 아래 각 함수가 자동완성을 하는 모양이 다를 수 있습니다.)

1) semantic-ia-complete-symbol-menu
semantic-ia-complete-symbol-menu.png
[PNG image (71.53 KB)]

2) semantic-ia-complete-symbol
semantic-ia-complete-symbol.png
[PNG image (81.94 KB)]

3) semantic-ia-complete-tip
semantic-ia-complete-tip.png
[PNG image (64.96 KB)]

4) senator-completion-menu-popup
senator-completion-menu-popup.png
[PNG image (70.08 KB)]

5) semantic-complete-self-insert ("." 입력하고 "sho"까지 입력후 tab 누른 상태)
semantic-complete-self-insert.png
[PNG image (76.03 KB)]

6) semantic-complete-analyze-inline
semantic-complete-analyze-inline.png
[PNG image (77.94 KB)]

7) semantic-analyze-possible-completions
semantic-analyze-possible-completions.png
[PNG image (80.02 KB)]

8) global-semantic-idle-completions-mode ("sh" 입력하고 약1초 기다린 후 tab 2번 누른 상태)
global-semantic-idle-completions-mode.png
[PNG image (56.77 KB)]

2.2. 키바인딩 예제

;; cedet semantic 인텔리센스 키바인딩 예제
(global-set-key [(control return)] 'semantic-ia-complete-symbol-menu)
(global-set-key [(control shift return)] 'semantic-ia-complete-tip)

(global-set-key [(control c)(control return)] 'semantic-complete-analyze-inline)

(global-set-key [(shift return)] 'semantic-analyze-possible-completions)
예를 들어 semantic-ia-complete-symbol-menu 같은 경우 인텔리센스를 사용할 곳에서
C-RET 하고 C-n (아래), C-p (위), C-f (오른쪽), C-b (왼쪽) 로 움직이고 RET로 선택하고
C-g 로 취소하면 됩니다. 더 간단하게 Ctrl "계속" 누른 상태에서 RET 하고 n,p,f,b 로 음직이고 g로 취소하는 방법도 가능합니다.

참고사항으로 MS윈도우에서는 semantic-ia-complete-symbol-menu 창이 C-g 로 사라지지 않는데
ESC 키나 이상하게도 왼쪽 Alt 키를 누르면 사라집니다.

2.3. VS와 비슷하게 인텔리센스를 "." "->" "::" 로 사용하기

VS처럼 "." "->" "::" 입력되면 인텔리센스가 되도록 사용하려면 명시적으로 키바인딩을 해서 사용해야 합니다.

cedet 홈페이지에 나온 내용으로 하면 "." 는 되는데 "->" "::" 는 원하는 대로 작동이 안되서 코드를 약간 추가해서 .emacs 파일에 넣어야 합니다.
참고: http://cedet.sourceforge.net/intellisense.shtml
;; 처음 부터 . -> :: 기능을 사용하시려면 아래 "nil" 을 "t" 바꾸세요. 
(defvar semantic-complete-self-insert-p nil)
(defun semantic-complete-self-insert-toggle-switch ()
  (interactive)
  (if semantic-complete-self-insert-p
      (progn (setq semantic-complete-self-insert-p nil)
	     (message "semantic-complete-self-insert off") )
    (progn (setq semantic-complete-self-insert-p t)
	   (message "semantic-complete-self-insert on") )  )   )


(defun semantic-complete-self-insert-for-dot-operator (arg)
  (interactive "p")
  (if semantic-complete-self-insert-p
      (call-interactively 'semantic-complete-self-insert)
    (self-insert-command arg) )  )

(defun semantic-complete-self-insert-for-arrow-operator (arg)
  (interactive "p")
  (if (and semantic-complete-self-insert-p
	   (string= "-" (char-to-string (char-before (point)) )  )   )
      (call-interactively 'semantic-complete-self-insert)
    (self-insert-command arg) )  )

(defun semantic-complete-self-insert-for-scope-operator (arg)
  (interactive "p")
  (if (and semantic-complete-self-insert-p
	   (string= ":" (char-to-string (char-before (point)) )  )   )
      (call-interactively 'semantic-complete-self-insert)
    (self-insert-command arg) )  )


(defun c++-mode-additional-semantic-keys ()
  "Key bindings to add to `c++-mode'."
  (define-key c++-mode-map [(control c)(control .)] 'semantic-complete-self-insert-toggle-switch)
  (define-key c++-mode-map "." 'semantic-complete-self-insert-for-dot-operator)
  (define-key c++-mode-map ">" 'semantic-complete-self-insert-for-arrow-operator)
  (define-key c++-mode-map ":" 'semantic-complete-self-insert-for-scope-operator)
  )

(add-hook 'c++-mode-hook 'c++-mode-additional-semantic-keys)

3. 심볼완성(symbol completion)

3.1. 종류

심볼완성에도 인텔리센스처럼 여러가지가 있습니다.

1) dabbrev-expand
emacs에 내장된 기능입니다. 현재 열려 있는 버퍼의 심볼을 가지고 자동완성을 합니다.
죽, C-x C-b (list-buffers) 해서 나오는 리스트 중 자신이 만든 버퍼가 해당됩니다.
(지역변수를 심볼완성 할 때 정말 편합니다. 현재 버퍼 검색을 제일 먼저하기 때문에...)

2) hippie-expand
dabbrev-expand 처럼 emacs에 내장된 기능입니다.
dabbrev-expand와 hippie-expand 중 선호하는 것을 사용하세요.
(senator-minor-mode 를 off 하고 사용하세요.)

3) senator-complete-symbol
cedet 패키지를 사용하면 그냥 사용 할 수 있습니다.
인텔리센스처럼 #include 를 포함해서 자동완성을 합니다.

4) complete-symbol
etags 로 TAGS 파일을 만들어 주어주고 visit-tags-table 을 해야 사용 가능합니다.

5) ebrowse-tags-complete-symbol
ebrowse 로 BROWSE 파을을 만들어 주고 BROWSE 파일을 다른 버퍼에 열어 두어야 사용 가능합니다.
ebrowse의 기능이 etags와 비슷하지만 ebrowse가 C++에 더 잘 최적화되어 있습니다.([http]참고문서)

3.2. 키바인딩 예제

;;;; 심볼완성 키바인딩 예제

;; M-/ (dabbrev-expand) - emacs에 기본 설정 되어 있음

;;senator-complete-symbol 기본 키바인딩은 C-c , TAB 이고 아래는 추가 지정한 것임
(global-set-key [(meta return)] 'senator-complete-symbol)

(global-set-key [(meta shift return)] 'complete-symbol)

;; ebrowse-tags-complete-symbol 기본 키바인딩은 C-c RET TAB 이고 아래는 추가 지정한 것임
(global-set-key [(control meta return)] 'ebrowse-tags-complete-symbol)
예를 들어 senator-complete-symbol 를 사용할 곳에서 M-RET 를 누르면
사용 가능한 심볼이 완성이 되고 다시 M-RET누르면 다른 심볼이 완성되고
이런 식으로 사용 가능한 심볼이 돌아가며 완성되게 됩니다.

Meta(Alt)를 "계속" 누른 상태에서 RET만 누르는 방법도 가능합니다.

4. 인텔리센스와 심볼완성 테스트

인텔리센스는 원하는 모든 것을 자동완성시킬 수 있지만 느리기 때문에 심볼완성을 적절히 사용하면 좋은데
심볼완성의 종류에 따라 자동완성이 원하는 대로 안 되는 경우도 있습니다.
귀찮으신 분은 속편히 인텔리센스만 사용하셔도 됩니다.

아래와 같은 코드가 있고 etags와 ebrowse로 TAGS와 BROWSE 파일을 만들었고 BROWSE 파일은 다른 버퍼에 열어 놓았다 가정합니다.
#include <iostream>

class Test
{
public:
    Test();
    virtual ~Test();

public:
    void TestClassPrint () = 0;
    void TestClassPrint2 () = 0;
};

void TestFunctionPrint()
{
    printf("hello emacs");
}

int main(int argc, char *argv[])
{
    int localvalue = 4;
    Test test;

    printf("print localvalue : %d", localvalue);

    _ <-- 여기 커서

    return 0;
}
테스트 1)
위 상태에서
"lo"까지 타이핑 후 "localvalue"을 완성 시키고자 하면 인텔리센스는 semantic-complete-self-insert를 제외하고 전부 사용할 수 있고
심볼완성은 dabbrev-expand(hippie-expand)와 senator-complete-symbol만 완성 시킬 수 있습니다.
그 이유는 TAGS와 EBROWSE파일을 열어 보면 localvalue라는 것이 없고 클래스명, 함수, 멤버함수만 태그로 만들어져서 있어서
complete-symbol, ebrowse-tags-complete-symbol는 "localvalue"를 자동완성 시킬 수 없습니다.

테스트 2)
위 상태에서 "test.Te"까지 타이핑 후 "test.TestClassPrint"를 완성 시키고자 하면 인텔리센스는 전부 사용할 수 있고
심볼완성은 senator-complete-symbol와 ebrowse-tags-complete-symbol 만 완성 시킬 수 있습니다.
C++ 의 멤버함수이기 때문에 complete-symbol는 완성 시킬 수 없습니다. TAGS파일을 열어 보면 알 수 있습니다.

참고:
find-file (C-x C-f)로 BROWSE 파일을 열면 Ebrowse-Tree Mode 로 들어가기 때문에
내용을 보고 싶으시면 M-x find-file-literally 를 사용하세요.

5. 가상 시나라오

emacs에는 자동완성 종류가 너무 많기 때문에 가상 시나라오를 하나 적어 봅니다.

우선 지역변수 자동완성은 M-/ (dabbrev-expand)를 사용합니다.
이것은 현재 버퍼의 심볼을 먼저 검색하고 emacs에 내장되어 있어 가장 빠르기 때문에 최상의 선택이라 생각됩니다.

처음 접하는 라이브러리가 있다 가정하면 멤버함수 같은 것이 익숙지 않기 때문에
semantic-complete-self-insert와 semantic-ia-complete-symbol-menu를 적당히 섞어 사용하다가
좀 익숙해 지면 멤버함수명을 생각나는데 까지 타이핑 후 semantic-complete-analyze-inline 를 사용하고
생각이 안 나는 매개변수가 있으면 semantic-analyze-possible-completions 를 사용합니다.

그리고 라이브러리가 완전히 능숙해져서 왠만한 멤버함수가 다 기억나면
이제 신내린 코딩(?)을 하며 간간히 심볼완성(senator-complete-symbol)을 사용하면 됩니다.

자신이 만든 클래스 같은 경우도 멤버함수를 거의 기억하고 있기 때문에 심볼완성(senator-complete-symbol)을 사용하면 됩니다.

complete-symbol, ebrowse-tags-complete-symbol 는 TAGS, BROWSE 파일을 따로 명령어를 사용해서
만들어야 하는 부담이 있기 때문에 소스코드 분석 겸 수정 할 때 사용하면 좋습니다. (tag로 지정된 곳을 왔다 갔다 할 수 있으므로...)

6. Yet Another Snippet (yasnippet)

인텔리센스와 심볼완성이면 완벽하지만
yasnippet 까지 사용하면 정말 더할 나위 없게 됩니다.

yet another snippet extension for Emacs.
http://code.google.com/p/yasnippet/

"class" 타이핑 후 tab 누르고 "Te"까지 입력한 화면
yasnippet.png
[PNG image (41.3 KB)]

주의사항:
yasnippet로 완성된 코드는 indent가 space로 삽입되고 indent level이 4입니다.
그래서 설정이 다르신 분은 정렬을 다시 해주어야 하는데
가장 간단한 해결 방법은 .emacs에 아래를 추가하는 것입니다.
(add-hook 'yas/after-exit-snippet-hook
          '(lambda ()
             (indent-region yas/snippet-beg
                            yas/snippet-end)))
(출처: http://code.google.com/p/yasnippet/wiki/Tips)

참고:
c언어 같은 경우 [http]msf-abbrev가 가 더 편할 수 있습니다.

by 사이져:
msf-abbrev가 yasnippet보다 더 빨리 나온 약어(abbrevation or snippet) 모드이고, 요즘 유행하고 있는 것은 msf-abbrev가 아니라 yasnippet입니다.

7. 실시간 분석 (real-time analysis)

자동완성에 연관된 emacs의 강력한 기능을 하나 소개하겠습니다.

1) semantic-speedbar-analysis
semantic-speedbar-analysis.png
[PNG image (89.58 KB)]

2) ECB Analyse Buffer (ECB 설치 필요)
ecb-analyse-buffer.png
[PNG image (92.31 KB)]

참고:
analyse-buffer 반응이 느리다면
C-h v (M-x describe-variable)
ecb-analyse-buffer-sync-delay 참고하셔서 적당히 바꾸세요.
저같은 경우 한 0.7 정도하니 적절했습니다.

- 현재(2009년 7월 4일) [http]Latest CVS-shapshot 버전에서는 아래 문제 해결되었습니다.

아래 메세지가 나오고 ECB Analyse Buffer 가 작동 안된다면
eieio-default-superclass: Invalid slot name: "#<semantic-analyze-context context>", localvariables
Invalid slot name: "#<semantic-analyze-context context>", localvariables
ecb-analyse.el 파일에 아래를 적용해 보세요.
***************
*** 270,276 ****
  
  (defmethod ecb-analyse-more-nodes ((context semantic-analyze-context))
    "Show a set of ecb-nodes specific to CONTEXT."
!   (let ((localvars (oref context localvariables)))
      (when localvars
        (ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
                               ecb-analyse-nodetype-localvars)))
--- 270,278 ----
  
  (defmethod ecb-analyse-more-nodes ((context semantic-analyze-context))
    "Show a set of ecb-nodes specific to CONTEXT."
!   (let* ((scope (oref context scope))
! 	 (localvars (when scope
! 		      (oref scope localvar))))
      (when localvars
        (ecb-analyse-add-nodes "Local Variables" "Local Variables" localvars
                               ecb-analyse-nodetype-localvars)))

8. 문제해결 및 이슈

8.1. 인텔리센스가 잘 안될 때

아래 에러가 나오고 인텔리센스가 잘 안된다면
semantic-analyze-possible-completions-default:
Cannot find types for `"..."'
.emacs 파일에서 semantic-add-system-include 함수로 헤더파일 경로를 잘 설정했는지 확인하고
C-x C-s (save-buffer)
M-x revert-buffer
이렇게 하세요.

좀 더 편하게 사용하려면 아래 사이트를 참고해서
http://www.stokebloke.com/wordpress/2008/04/17/emacs-refresh-f5-key/

아래를 .emacs 파일에 추가하세요.
(defun refresh-file-after-save-buffer ()
  "refresh file after save buffer"
  (interactive)
  (save-buffer)
  (revert-buffer t t t) )

(global-set-key [(control c)(control R)] 'refresh-file-after-save-buffer)

8.2. semantic은 "add-hook" 에 민감하다?

예1)
(add-hook 'c-mode-common-hook 'folding-mode)
folding-mode가 로드가 안 되어 있어서 "folding-mode" 가 void-function 일 경우 아래 에러가 생길 수 있습니다.
Wrong type argument: syntax-table-p,nil

예2) choose-header-file-mode (http://han9kin.doesntexist.com/28) 함수같은 경우 아래처럼 수정해야 정상 작동합니다.
(defun choose-header-file-mode ()
  (if (and buffer-file-name (string= (file-name-extension buffer-file-name) "h"))
      (let ((filebase (file-name-sans-extension buffer-file-name)))
        (cond
         ((and (file-exists-p (concat filebase ".c")) 
	       (not (string= major-mode "c-mode")))
          (c-mode) )
         ((and (file-exists-p (concat filebase ".cpp"))
	       (not (string= major-mode "c++-mode")))
          (c++-mode) )
         ((and (file-exists-p (concat filebase ".cc"))
	       (not (string= major-mode "c++-mode")))
          (c++-mode) )
         ((and (file-exists-p (concat filebase ".m"))
	       (not (string= major-mode "objc-mode")))
          (objc-mode) )
         ((and (file-exists-p (concat filebase ".mm"))
	       (not (string= major-mode "objc-mode")))
          (objc-mode) )
         ((and t
	       (not (string= major-mode "c++-mode")))
          (c++-mode) )  )   )
    ) )

(add-hook 'c-mode-common-hook 'choose-header-file-mode)
그렇지 않으면 아래같은 에러가 생길 수 있습니다.
semantic-analyze-current-context: Wrong type argument: syntax-table-p, nil
eieio-generic-call: No method definition: semantic-analyze-type-constraint, (nil)

참고:
find-file-hook에 추가한 함수가 잘 작동이 안되면 c-mode-common-hook, after-change-major-mode-hook으로 옮겨 보거나
add-hook에 옵션 매개변수도 조정해 보세요.
(add-hook 'xxxxx 'xxxxx t t)

8.3. 매크로(#define) 때문에 자동완성이 안될 때

예를 들어 아래 같은 mfc 함수 같은 경우
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp() {...
AfxGetApp()->로 자동완성을 시도하면 CWinApp*형이 아니라 AFXAPI형으로 인식해서 자동완성이 안 되는데
아래를 추가해서 매크로를 무력화시키면 정상적으로 자동완성이 됩니다.(이전에 생성된 캐쉬 파일 삭제 필요)
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("_AFXWIN_INLINE" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("AFXAPI" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("AFX_CDECL" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("PASCAL" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("CALLBACK" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__cdecl" . ""))
(add-to-list 'semantic-lex-c-preprocessor-symbol-map '("__stdcal" . ""))
mfc외에도 wxWidget 등등의 라이브러리처럼 매크로가 많은 경우 활용 가능합니다.
참고:
CEDET wxWidgets 자동완성

8.4. MS 윈도우에서 cedet 컴파일 문제

MS 윈도우에서 EmacsW32, msys 등등의 버전 특성 때문에 cedet 컴파일할 때
아래와 같은 에러를 만날 수 있는데
Symbol's value as variable is void: outbuffer
Symbol's value as variable is void: filename
Cannot open load file: srecode-fields

Cannot open load file: eieio-load
Cannot open load file: semantic-load
Cannot open load file: srecode-load
Cannot open load file: ede-load
Cannot open load file: cogre-loaddefs
Cannot open load file: contrib-loaddefs
일단 공식 GNU Emacs를 사용하고
http://ftp.gnu.org/pub/gnu/emacs/

cedet-build.el 파일을 emacs로 읽어 들인 후
M-x eval-buffer
M-x cedet-build-in-default-emacs
이런식으로 emacs 내부에서 컴파일하세요.
컴파일하는데 꽤 시간이 오래 걸립니다.
그리고 "Done"이라는 문구가 나오는지 확인하세요.(참고 스샷: [http]cedet-compile-in-mswin.png)

9. 또 다른 자동완성

cedet의 semantic은 c,c++ 언어는 완벽하게 지원하는 반면에 다른 언어는 미미한 편입니다.
다른 툴 사용도 고려해 보세요.
참고:
http://www.emacswiki.org/emacs/CategoryCompletion




4) HTML 자동완성 예
Screenshot : [http]emacs-tag-completion.png
참고:
* http://www.emacswiki.org/emacs/NxhtmlMode
* http://kldp.org/node/104700
* 또 다른 방식인 [http]ZenCoding도 추천합니다.

5) JavaScript 자동완성 예
Screenshot : [http]emacs-javascript-completion.png

6) CSS 자동완성 예
Screenshot : [http]emacs-css-completion.png


8) Ruby 자동완성 예
Screenshot : [http]auto-complete-ruby.png
참고:
* http://kldp.org/node/110632

9) Java 자동완성 예
Screenshot : [http]jde-complete.png
참고:
* http://kldp.org/node/110967

10) Bash 자동완성 예
Screenshot : [http]sh-mode.png

11) Debian rules 자동완성 예
Screenshot : [http]rules(makefile-mode).png


(!) primewizard 20081026



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-11-25 09:37:32
Processing time 0.0327 sec