Emacs 에는 모드라는게 있어서 키 입력이나 상황에 따라 모드마다 라는 동작을 한다. 모드에는 크게 Major 모드와 Minor 모드가 있다. Emacs 모드에 대해서 GNU Emacs 매뉴얼의 내용을 보면서 정리했다.
Major 모드
Major 모드는 버퍼에 1개씩 할당되는 모드이다. Major 모드는 바꿀 수는 있지만 없앨 수는 없어서 버퍼마다 반드시 1개의 모드가 활성화되어야 하는 제약이 있다. Major 모드는 Emacs 윈도우의 하단 Mode Line 의 오른편에 있는 소괄호 안에 Minor 모드와 함께 (major minor) 식으로 표시된다.
매뉴얼에서는 Major 모드를 다시 크게 세 가지로 분류한다. ① 일반적인 문자 편집을 위한 것들로 예를 들어 Text Mode, HTML Mode, Tex Mode, Outline Mode 등이 있다. ② 프로그래밍을 위한 모드들로 C Mode, Fortan Mode 등이 그 예이다. ③ 특정 파일과 관계가 없는 모드들이 있는데, 예를 들어 터미널 안에서 파일탐색기 역할을 하는 Dired Mode, 이메일을 보낼 수 있는 Message Mode, Emacs 안에서 쉘을 열 수 있는 Shell Mode 등이 있다.
Major 모드는 반드시 버퍼당 1개가 할당되어야 하기 때문에 Emacs 에서 최소한 자동으로 지정되게 되어 있다. 강제 지정을 위해서는 M-x
xxx-mode
이런 식으로 입력하면 된다. 다시 한 번 말하지만 Major 모드는 끌 수가 없기 때문에 비활성화 하려면 다른 모드로 바꿔야 한다.
일반적으로 Major 모드는 파일 이름을 보고 결정하게 설정한다. auto-mode-alist
라는 변수(Association List)에 아래와 같이 등록하면 해당 파일 패턴에서 대응하는 Major 모드가 활성화된다.
;; glsl mode
(autoload 'glsl-mode "glsl-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.vert\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.frag\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.geom\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.fs\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.gs\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.vs\\'" . glsl-mode))
사실 파일 이름을 보고 Major 모드를 동작시키는 단계는 처리 순서상 비교적 뒤의 단계에 위치한다(5단계 중 4번째). 가장 우선 순위가 높은 모드선택은 파일로컬 변수에서 -*-
로 지정된 이름을 보고 결정하는 것이다. 두 번째는 재미있게도 스크립트 파일을 만들 때 제일 위의 라인에 해당 스크립트를 실행할 인터프리터 역할을 하는 파일을 #!
와 함께 적어주는데 이 파일의 이름을 보고 유추하여 모드를 선택한다. 예를 들어 어떤 스크립트 파일의 제일 윗줄에 #!/usr/local/bin/perl
이라고 적혀 있었으면, Perl Mode를 로드한다.
세 번째는 파일 내용의 앞단(어디까지인지는 모르겠지만)을 정규표현식 매칭하여 모드를 결정하는 단계가 있다. magic-mode-alist
라는 변수에 (정규표현식 . 모드)
이런 식으로 등록한다. nil
로 줄 경우 이 과정을 건너뛰며 기본값은 nil
이다.
네 번째가 앞서 언급한 파일이름 패턴을 보는 단계이고 마지막은 magic-fallback-mode-alist
라는 변수를 보고 역시 파일 앞부분의 내용을 보고 정규표현식 매칭하는 단계이다. 여기에는 기본값이 셋팅되어 있는데, 이미지 파일이나 HTML, JSON 파일 등을 대상으로 한다.
major-mode
라는 변수는 Major 모드의 이름을 나타내는 버퍼로컬 변수이다. 현재 활성화된 Major 모드를 나타내는데, 자동으로 설정되므로 웬만하면 수정하지는 말고, 필요할 때 읽어 쓰기만 하자. C-x b
로 버퍼를 새로 만들 때 기본으로 켜지는 모드를 지정할 수 있다라고 하는데 일단 기본값은 fundamental-mode
이고, nil
로 설정할 경우 이전 버퍼의 것을 그대로 가져다 써서 모드가 결정된다고 한다.
(Fundamental 모드를 제외한) 모든 Major 모드는 xxx-mode-hook
이런 이름으로 Hook 을 지정할 수 있다. 보통 이런 모드 hook 은 다른 Minor 모드들을 로드하는데 사용한다.
Minor 모드
Minor 모드는 무언가 옵션같은 느낌이다. Major 모드는 버퍼당 반드시 1개가 켜져있어야 하지만 Minor 모드는 동시에 여러개를 활성화시킬 수도 있고, 비활성화도 가능하다.
메뉴얼에서는 Minor 모드를 크게 2가지로 분류한다. ① 버퍼로컬 Minor 모드는 특정 몇몇 버퍼에서 활성화되고 그외에는 비활성화되는 특징을 갖는다. ② 글로벌 Minor 모드는 활성화되면 현재 Emacs 세션 전반에 걸쳐 영향을 준다.
대부분의 버퍼로컬 Minor 모드는 활성화 되었을 때 Mode Line 에서 Major 모드 옆에 표시된다(즉, 활성화된 모든 Minor 모드가 다 표시되는건 아님).
Major 모드와 마찬가지로 Minor 모드를 활성화시키는 명령어는 (xxx-mode)
이다. Minor 모드는 비활성화도 가능하기 때문에 활성화된 상태에서 해당 모드 명령어를 실행시키면 토글되어 비활성화된다. Minor 모드 활성화 명령어와 관련된 내용을 정리하면 아래와 같다.
- Prefix argument 없이
M-x
나 키바인딩으로 실행시킨 Minor 모드 커맨드는 현재 상태를 토글한다
- 위의 경우 Prefix argument 가 0이나 음수 값이라면 해당모드는 비활성화로 바뀌고, 다른 argument의 경우 활성화된다
- Lisp 코드로(소괄호 Call 방식) 실행시킬 경우 argument가
nil
또는 생략되었을 경우 비활성화 되고, 그 외 다른 값을 넣을 경우 활성화된다
대부분의 minor 모드는 해당 모드 커맨드와 같은 이름의 변수를 갖는데, 활성화된 상태에서 non-nil
값을, 비활성화된 상태에서 nil
값을 갖는다. major-mode
변수와 마찬가지로 이 변수는 자동 세팅되기 때문에 읽기만 하고 괜히 수정하는 것은 추천하지 않는다.
Major 모드는 대체로 특정 프로그래밍 언어나 특정 작업에 대한 기능을 제공하는 반면, Minor 모드는 비교적 작은 규모이지만 여러 다른 작업에 유연하게 적용될 수 있는 기능을 제공한다. Minor 모드 중에 auto-fill
이라는 모드를 예로 들어보자. 이 모드는 엔터키를 입력하여 줄바꿈을 하였을 때에 대한 처리를 제공한다. 이 모드는 text-mode
일때와 java-mode
일때 다르게 동작하는데, text-mode
일때는 줄이 너무 길어지면 word wrap을 실행하지만 jave-mode
에서는 word wrap을 실행하지 않는다. 하지만 java-mode
에서도 주석을 편집하는 경우는 word warp이 되어야 하는데 auto-fill
모드는 주석의 경우 알아서 word warp을 하도록 처리해 준다. 이렇듯 전세계의 Emacs 모드 개발자들은 Minor 모드가 Monor 모드의 정체성을 유지하도록 하기 위해 엄청나게 신경쓰고 있는 것이다(The authors of various Emacs modes have done a great job of making sure that things that should work as minor modes are minor modes).
참고