· 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

ID
Password
Join
Mind your own business, Spock. I'm sick of your halfbreed interference.


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.1127 sec