GNUEmacsManual:33

From 흡혈양파의 번역工房
Revision as of 15:03, 27 April 2016 by Onionmixer (talk | contribs) (GNU Emacs 33장 내용 추가)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
맞춤화(Customization)

맞춤화(Customization)

이번 장에서는 Emacs의 동작을 맞춤화하는 몇 가지 간단한 방법을 설명한다.


본문에 설명된 방법 외에 X 자원을 이용한 Emacs의 맞춤화에 관한 정보는 493 페이지의 부록 D [X 자원(X Resources)]을, 키보드 매크로의 기록과 재생에 관한 정보는 114 페이지의 14장 [키보드 매크로(Keyboard Macros)]를 참고한다. 좀 더 방대하고 확장 가능한 변경에는 Emacs Lisp 코드의 작성을 수반하는데, The Emacs Lisp Reference Manual을 참고한다.


쉬운 맞춤화 인터페이스(Easy Customization Interface)

Emacs는 사용자가 변경할 수 있는 많은 설정(settings)을 갖고 있다. 대부분의 설정은 맞춤화 가능한 변수로서 (420 페이지의 33.2절 [변수(Variables)] 참고) 사용자 옵션(user options)이라고 부르기도 한다. Emacs 동작의 수많은 측면을 제어하는 맞춤화 가능한 변수의 수는 엄청나게 많으며, 본 매뉴얼에 문서화된 변수는 568 페이지의 [변수 색인(Variable Index)]에 열거되어 있다. 이와 구분된 설정 클래스는 겉모습(faces)으로서, 폰트, 색상, 그 외 텍스트의 속성을 결정한다(74 페이지의 11.8절 [겉모습(Faces)] 참고).


설정(변수와 겉모습)을 살펴보고 수정하기 위해서는 M-x customize 를 입력한다. 이는 맞춤화 버퍼(customization buffer)를 생성하는데, 맞춤화 버퍼는 논리적으로 조직된 설정 목록을 탐색하고, 그 값을 편집 및 설정하며, 영구적으로 저장하도록 해준다.



맞춤화 그룹(Customization Groups)

맞춤화 설정은 맞춤화 그룹으로 조직된다. 이러한 그룹은 더 큰 그룹에 모여 가장 큰 그룹인 Emacs 라는 마스터 그룹까지 이어진다.


M-x customize 는 최상위 수준의 Emacs 그룹을 표시하는 맞춤화 버퍼를 생성한다. 그 일부분만 표시하자면 다음과 같다:

For help, see [Easy Customization] in the [Emacs manual].

------------------------------------------- [ Search ]

 Operate on all settings in this buffer: 
 [ Revert... ] [ Apply ] [ Apply and Save ]


Emacs group: Customization of the One True Editor.
      [State]: visible group members are all at standard values. 
      See also [Manual].

[Editing] : Basic text editing facilities. 
[Convenience] : Convenience features for faster editing.

more second-level groups


이 버퍼의 주요 부분은 '

Emacs

' 맞춤화 그룹을 표시하는데, 여기에는 몇 가지 다른 그룹도 포함되어 있다('

Editing

', '

Convenience

', 등). 이러한 그룹의 내용은 본문에 싣지 않고 각 문서에서 하나의 라인만 발췌하였다.


그룹의 상태(state)는 해당 그룹 내 설정이 편집, 설정 또는 저장되었는지 나타낸다. 413 페이지의 33.1.3절 [변수 변경하기(Changing a Variable)]를 참고한다.


맞춤화 버퍼 대부분은 읽기 전용이지만 사용자가 편집할 수 있는 몇 개의 편집 가능한 필드(editable fields)를 포함한다. 가령 맞춤화 버퍼의 최상단은 설정을 검색하기 위한 편집 가능한 필드이다(413 페이지의 33.1.2절 [브라우징 커스텀(Browing Custom)] 참고). 마우스를 이용해 클릭하거나 포인트를 이동시켜 RET 를 입력하면 활성화되는 버튼(buttons)과 링크(links)도 있다. 예를 들어 '

[Editing]

'과 같은 그룹명은 링크이고, 이러한 링크 중 하나를 활성화하면 해당 그룹에 대한 맞춤화 버퍼를 가져온다.


맞춤화 버퍼에서 TAB (

widget-forward

) 를 입력하면 다음 버튼 또는 편집 가능한 필드로 순방향 이동한다. S-TAB (

widget-backward

) 를 입력하면 이전 버튼 또는 편집 가능한 필드로 역방향 이동한다.


설정을 브라우징하고 검색하기

M-x customize 로 생성된 최상위 수준의 맞춤화 버퍼로부터 '

Emacs

' 맞춤화 그룹의 하위그룹까지 링크를 따라갈 수 있다. 이러한 하위그룹은 맞춤화 가능한 설정을 포함할 수 있으며, 이러한 그룹이 또 하위그룹을 포함하기도 하여 좀 더 특수화된 Emacs 의 하위시스템을 처리한다. 맞춤화 그룹의 계층구조를 탐색하는 동안 사용자는 맞춤화하고자 하는 설정을 발견할 것이다.


맞춤화 그룹 또는 특정 설정을 맞춤화하는 데에 관심이 있다면 M-x customize-option, M-x customize-face, M-x customize-group 명령어 중 하나를 이용해 직접 이동할 수 있다. 417 페이지의 33.1.6절 [구체적 맞춤화(Specific Customization)]를 참고한다.


맞춤화하고자 하는 설정이나 그룹을 정확히 알지 못한다면 맞춤화 버퍼마다 그 상단에 편집 가능한 검색 필드를 이용하여 검색할 수 있다. 여기서는 검색 용어에 입력하면 되는데, 공백으로 구분된 하나 또는 이상의 단어나 정규 표현식 중 하나에 해당한다(97 페이지의 12.6절 [Regexps] 참고). 이후 필드에서 RET 를 입력하거나 그 옆에 '

Search

' 버튼을 활성화하면 그러한 용어에 일치하는 설정과 그룹을 포함하는 맞춤화로 전환할 수 있다. 하지만 이 기능은 현재 Emacs 세션에서 로딩되는 설정과 그룹만 찾는다는 사실을 명심한다.


맞춤화 버퍼에서 검색 필드를 찾기를 원하지 않으면

custom-search-field

변수를

nil

로 변경한다.


M-x customize-apropos 명령어는 검색 필드의 사용과 유사한데, 미니버퍼를 이용해 검색 용어를 읽는다는 점은 다르다. 417 페이지의 33.1.6절 [구체적 맞춤화(Specific Customization)]를 참고한다.


M-x customize-browse 는 이용 가능한 설정을 브라우징하는 또 다른 방법이다. 이 명령어는 그룹과 설정의 이름만 구조화된 레이아웃으로 표시하는 특수 맞춤화 버퍼를 생성한다. 그룹명 옆에 '

[+]

' 버튼을 호출하여 동일한 버퍼에 그룹의 내용을 표시할 수 있다. 그룹 내용이 표시되면 버튼은 '

[-]

' 로 바뀌고, 그것을 호출하면 그룹 내용을 다시 숨긴다. 해당 버퍼에서 각 그룹 또는 설정은 '

[Group]

', '

[Option]

', 또는 '

[Face]

' 라고 말하는 링크를 갖는다. 해당 링크를 호출하면 해당 그룹, 옵션 또는 겉모습만 표시하는 일반 맞춤화 버퍼가 생성되는데, 이는 M-x customize-browse 를 이용해 검색한 설정을 변경하는 방법이다.


변수 변경하기(Changing a Variable)

변수 또는 사용자 옵션이 맞춤화 버퍼에서 어떤 모습인지 보여주는 예가 있다:

[Hide] Kill Ring Max: 60 
   [State]: STANDARD.
   Maximum length of kill ring before oldest elements are thrown away.


첫 행은

kill-ring-max

라고 명명된 변수를 보기 쉽게 '

Kill Ring Max

' 로 포맷팅되는 것을 보여준다. 값은 '

60

' 이다. '

[Hide]

'라는 버튼이 활성화되면 변수의 값과 상태를 숨기는데, 이는 값이 매우 긴 맞춤화 버퍼의 cluttering up 을 피하는 데에 유용하다(이러한 이유로 매우 긴 값을 가진 변수는 숨겨진 채로 시작될 수 있다). '

[Hide]

' 버튼을 사용할 경우 '

[Show Value]

' 로 변경되는데, 이것을 이용하면 값과 상태의 숨김을 활성화할 수 있다. 그래픽 디스플레이에서 '

[Hide]

' 와 '

[Show Value]

' 버튼은 각각 하향과 우측을 가리키는 그래픽 삼각형으로 대체된다.


변수명 다음 라인은 변수의 맞춤화 상태를 나타내는데, 이 예제에서 '

STANDARD

' 는 사용자가 변수를 변경하지 않았음을 의미하므로 그 값은 기본 값이다. '

[State]

' 버튼은 변수를 맞춤화하기 위한 연산으로 이루어진 메뉴를 제공한다.


맞춤화 상태 아래에는 변수에 대한 문서가 있다. 이는 C-h v 명령어가 표시할 법한 문서와 동일한 문서이다(421 페이지의 33.2.1절 [조사하기(Examining)] 참고). 문서 길이가 하나 이상의 라인으로 되어 있다면 하나의 라인만 표시될 것이다. 그럴 경우 그 라인은 '

[More]

' 버튼으로 끝나는데, 버튼을 활성화하면 전체 문서를 볼 수 있다.


'

Kill Ring Max

' 에 대한 새 값을 입력하기 위해서는 값으로 포인트를 이동시켜 편집한다. 가령 M-d 를 입력하면 '

60

' 을 삭제하고 다른 숫자를 입력한다. 텍스트의 수정을 시작하면 '

[State]

' 행이 변경될 것이다:

[State]: EDITED, shown value does not take effect until 
         you set or save it.


값을 편집한다고 해서 즉시 효과가 나타나지는 않는다. 이를 위해선 '

[State]

' 버튼을 활성화하고 '

Set for Current Session

' 을 선택함으로써 변수를 설정해야 한다. 이후 변수의 상태는 아래와 같아진다:

[State]: SET for current session only.


유효하지 않은 값을 명시할 경우를 염려하지 않아도 되는 것이 '

Set for Current Session

' 연산은 유효성을 검사하고 허용되지 않는 값은 설치하지 않기 때문이다.


파일명, 디렉터리명, Emacs 명령어 이름처럼 특정 종류의 값을 편집할 때는 C-M-i (

widget-complete

) 를 이용해 완성을 실행하거나 그와 동일한 키인 M-TAB 또는 ESC TAB 를 이용해도 좋다. 이는 미니버퍼 완성과 거의 비슷하게 동작한다(28 페이지의 5.4절 [완성(Completion)] 참고).


편집 가능한 값 필드에서 RET 를 입력하면 TAB 처럼 포인트를 다음 필드나 버튼으로 순방향 이동한다. 따라서 필드의 편집이 완료되면 RET 를 입력하여 다음 버튼이나 필드로 이동한다. 편집 가능한 필드 내에 개행 문자를 삽입하기 위해서는 C-o 또는 C-q C-j 를 사용한다.


일부 변수의 경우 유효한 값의 집합이 고정되어 있어 값의 직접 편집이 허용되지 않는다. 대신 값 앞에 '

[Value Menu]

' 버튼이 표시되는데, 이 버튼을 활성화하면 값의 선택을 표시한다. "on or off" 부울 값의 경우 버튼은 '

[Toggle]

' 이라고 말하고 값을 뒤집는다. '

[Value Menu]

' 또는 '

[Toggle]

' 버튼을 이용한 후에 선택된 값이 효과를 나타내기 위해선 변수를 다시 설정해야 한다.


일부 변수들은 복잡한 구조로 된 값을 가진다. 예를 들어

minibuffer-frame-alist

의 값은 관련 목록(association list)이다. 해당 목록은 맞춤화 버퍼에 다음과 같이 표시된다.

[Hide] Minibuffer Frame Alist:
[INS] [DEL] Parameter: width 
            Value: 80
[INS] [DEL] Parameter: height 
            Value: 2
[INS]
   [ State ]: STANDARD.
   Alist of parameters for the initial minibuffer frame. [Hide] 
   [...more lines of documentation...]


이런 경우 목록에 각 연관(association)은 두 개의 항목으로 구성되는데 하나는 '

Parameter

' 라고 불리고 다른 하나는 '

Value

' 라고 불리며, 둘 다 편집 가능한 필드이다. 연관 옆에 '

[DEL]

' 이란 버튼을 이용하면 목록에서 연관을 삭제할 수 있다. 연관을 추가하려면 삽입하고자 하는 위치에서 '

[INS]

' 버튼을 사용하고, 마지막으로 사용한 '

[INS]

' 버튼은 목록 끝에 삽입한다.


변수를 설정할 때 새로운 값은 현재 Emacs 세션에서만 효과를 보인다. 향후 세션에 사용할 값을 저장(save)하기 위해서는 '

[State]

' 버튼을 사용하여 '

Save for Future Sessions

' 연산을 선택한다. 416 페이지의 33.1.4절 [맞춤화 저장하기(Saving Customizations)]를 참고한다.


'

[State]

' 버튼을 이용하고 '

Erase Customization

' 연산을 선택하면 표준 값으로 변수를 복구시킬 수도 있다. 리셋 연산에는 사실상 네 가지가 있다:


'

Undo Edits

' 수정은 했지만 변수를 설정하지 않은 경우 이것은 맞춤화 버퍼 내 텍스트를 실제 값에 일치시키기 위해 복구시킨다.


'

Reset to Saved

' 변수의 값을 마지막으로 저장된 값으로 복구시키고, 그에 따라 텍스트를 업데이트한다.


'

Erase Customization

' 변수를 그것의 표준값으로 설정한다. 사용자가 저장한 값 역시 제거된다.


'

Set to Backup Value

' 변수를 이 세션에서 맞춤화 버퍼 내에 설정된 이전 값으로 설정한다. 변수를 맞춤화한 후 리셋하여 맞춤화된 값이 제거되었다면, 이 연산을 이용하여 제거된 값을 다시 얻을 수 있다.


때로는 구체적 맞춤화에 관한 주석을 기록하는 것이 유용하다. 주석을 입력하기 위한 필드를 생성하려면 '

[State]

' 메뉴로부터 '

Add Comment

' 항목을 사용한다.


맞춤화 버퍼의 상단 근처에는 두 개의 버튼 행이 있다:

[Set for Current Session] [Save for Future Sessions]
[Undo Edits] [Reset to Saved] [Erase Customization] [Exit]


첫 버튼 5개는 각각 명시된 연산, 즉 설정, 저장, 리셋 등 연산을 중요한 영향을 미치는 버퍼 내 모든 설정에 실행한다. 숨겨진 설정, 버퍼 내에 표시되지 않은 혹은 숨겨진 하위그룹에는 적용되지 않는다.


C-c C-c (

Custom-set

) 명령어는 '

[Set for Current Session]

' 버튼을 이용하는 것과 동일하다. C-x C-s (

Custom-save

) 명령어는 '

[Save for Future Sessions]

' 버튼을 이용하는 것과 같다.


'

[Exit]

' 버튼은 맞춤화 버퍼로부터 전환되어 버퍼를 버퍼 목록의 밑으로 bury시킨다. 맞춤화 버퍼를 대신 제거하도록 만들기 위해서는

custom-buffer-done-kill

변수를

t

로 변경한다.


맞춤화 저장하기(Saving Customizations)

맞춤화 버퍼에서는 '

[State]

' 버튼에서 '

Save for Future Sessions

' 를 선택함으로써 맞춤화 설정을 저장할 수 있다. C-x C-s (

Custom-save

) 명령어 또는 맞춤화 버퍼의 상단에 위치한 '

[Save for Future Sessions]

' 버튼은 버퍼 내 적용 가능한 설정을 모두 저장한다.


저장은 코드를 파일, 주로 초기화 파일에 작성함으로써 작동한다(437 페이지의 33.4절 [Init 파일(Init File)] 참고). 이후 Emacs 세션을 시작하면 이 파일을 자동으로 읽고 맞춤화를 다시 설정한다.


초기화 파일 이외의 위치로 맞춤화를 저장하도록 선택할 수 있다. 이를 가능하게 하려면 몇 개의 코드 라인을 초기화 파일로 추가하여

custom-file

변수를 원하는 파일명으로 설정하고 파일을 로딩해야 한다. 아래를 예로 들겠다.

(setq custom-file "~/.emacs-custom.el") 
(load custom-file)


아래와 같이 여러 Emacs 버전에 대한 여러 맞춤화 파일을 명시할 수도 있다:

(cond ((< emacs-major-version 22) 
       ;; Emacs 21 customization. 
       (setq custom-file "~/.custom-21.el")) 
      ((and (= emacs-major-version 22) 
            (< emacs-minor-version 3)) 
       ;; Emacs 22 customization, before version 22.3. 
       (setq custom-file "~/.custom-22.el")) 
      (t
       ;; Emacs version 22.3 or later.
       (setq custom-file "~/.emacs-custom.el")))

(load custom-file)


Emacs 가

-q

또는

--no-init-file

옵션으로 호출된 경우 (480 페이지의 C.2절 [초기 옵션(Initial Options)] 참고) 초기화 파일에 맞춤화를 저장하지 못하도록 할 것이다. 그 이유는, 그러한 세션의 맞춤화를 저장하면 초기화 파일에 가지고 있던 다른 맞춤화를 모두 제거해 버릴 것이기 때문이다.


겉모습 맞춤화하기(Customizing Faces)

Emacs 가 여러 유형의 텍스트를 어떻게 표시하는지를 결정하는 겉모습을 맞춤화할 수도 있다(74 페이지의 11.8절 [겉모습(Faces)] 참고). 맞춤화 그룹은 변수와 겉모습을 모두 포함할 수 있다.


예를 들어 프로그래밍 언어 모드에서 소스 코드 주석은

font-lock-comment-face

로 표시된다(78 페이지의 11.12절 [폰트 잠금(Font Lock)] 참고). 맞춤화 버퍼에서 그러한 겉모습은 다음과 같은 모습을 한다.

[Hide] Font Lock Comment Face:[sample] 
   [State] : STANDARD.
   Font Lock mode face used to highlight comments. 
   [ ] Font Family: --
   [ ] Font Foundry: -- 
   [ ] Width: -- 
   [ ] Height: -- 
   [ ] Weight: -- 
   [ ] Slant: -- 
   [ ] Underline: --
   [ ] Overline: -- 
   [ ] Strike-through: -- 
   [ ] Box around text: -- 
   [ ] Inverse-video: --
   [X] Foreground: Firebrick      [Choose]   (sample)
   [ ] Background: -- 
   [ ] Stipple: -- 
   [ ] Inherit: --
   [Hide Unused Attributes]


첫 3개 라인은 이름, '

[State]

' 버튼, 겉모습에 대한 문서를 표시한다. 그 아래에는 겉모습 속성(face attributes)의 목록이다. 각 속성 앞에는 체크박스가 있다. 체크박스가 채워진 '

[X]

' 는 겉모습이 해당 속성에 대한 값을 명시함을 의미하고, 빈 체크박스인 '

[ ]

' 는 겉모습이 속성에 대해 특별한 값을 명시하지 않음을 의미한다. 체크박스를 활성화하여 속성을 명시하거나 명시하지 않을 수 있다.


겉모습이 모든 단일 속성을 명시할 필요는 없으며 사실 대부분의 겉모습은 몇 가지 속성만 명시한다. 위의 예제에서

font-lock-comment-face

는 전경색만 명시한다. 명시하지 않은 속성은 속성이 모두 명시되어 있는

default

라는 특수 겉모습으로부터 취한다.

default

겉모습은 명시적으로 할당된 겉모습을 갖지 않은 텍스트를 모두 표시하는 데에 사용되는 겉모습으로, 그 배경색 속성은 프레임의 배경색 역할을 한다.


속성 목록의 끝에 위치한 '

Hide Unused Attributes

' 버튼은 겉모습의 명시되지 않은 속성을 모두 숨긴다. 속성이 숨겨져 있으면 버튼은 전체 속성 목록을 표시하는 '

[Show All Attributes]

' 로 변경한다. 맞춤화 버퍼는 명시되지 않은 속성은 숨긴 채로 시작하여 인터페이스의 cluttering 을 피한다.


속성이 명시되면 사용자는 일반적인 방식으로 그 값을 변경할 수 있다.


전경색과 배경색은 색상명 또는 RGB triplets 를 이용해 명시될 수 있다(75 페이지의 11.9절 [색상(Colors)] 참고). '

[Choose]

' 버튼을 이용해 색상명 목록으로 전환할 수도 있고, 해당 버퍼에서 RET 로 색상을 선택하여 값 필드에 색상명을 넣을 수도 있다.


겉모습의 설정, 저장, 리셋은 변수를 대상으로 한 연산과 마찬가지로 작동한다(413 페이지의 33.1.3절 [변수 변경하기(Changing a Variable)] 참고).


겉모습은 여러 유형의 디스플레이용으로 여러 모양을 명시할 수 있다. 가령 겉모습은 유색 디스플레이에서는 텍스트를 빨간색으로 만들지만 흑백 디스플레이에서는 굵은 폰트를 사용하도록 만들 수 있다. 겉모습에 여러 개의 모양을 명시하려면 '

[State]

' 를 호출하여 얻는 메뉴에서 '

For All Kinds of Displays

' 를 선택한다.


구체적 항목 맞춤화하기(Customizing Specific Items)

M-x customize-option RET option RET
M-x customize-variable RET option RET

한 명의 사용자 옵션 option에 대한 맞춤화 버퍼를 설정한다.


M-x customize-face RET face RET

하나의 겉모습 face 만을 위한 맞춤화 버퍼를 설정한다.


M-x customize-group RET group RET

하나의 그룹 group 만을 위한 맞춤화 버퍼를 설정한다.


M-x customize-apropos RET regexp RET

regexp 에 일치하는 모든 설정과 그룹에 대해 맞춤화 버퍼를 설정한다.


M-x customize-changed RET version RET

Emacs 버전 version 이후 의미가 변경된 모든 설정과 그룹에 대해 맞춤화 버퍼를 설정한다.


M-x customize-saved

맞춤화 버퍼로 저장한 모든 설정을 포함하는 맞춤화 버퍼를 설정한다.


M-x customize-unsaved

설정은 했지만 저장하지 않은 모든 설정을 포함하는 맞춤화 버퍼를 설정한다.


특정 사용자 옵션을 맞춤화하고 싶다면 M-x customize-option 을 입력한다. 이는 변수명을 읽고 하나의 사용자 옵션만을 이용해 맞춤화 버퍼를 설정한다. 변수명을 미니버퍼로 입력할 때는 완성을 이용할 수 있지만 Emacs로 로딩된 변수명만 가능하다.


마찬가지로 M-x customize-face 를 이용해 특정 겉모습을 맞춤화할 수도 있다. 특정 맞춤화 그룹에 대한 맞춤화 버퍼는 M-x customize-group 을 이용해 설정할 수 있다.


M-x customize-apropos 는 공백(스페이스)으로 구분된 하나 이상의 단어 또는 정규 표현식에 해당하는 검색 용어의 입력을 요구하고, 그에 일치하는 이름과 함께 모든 로딩된 설정 및 그룹에 대해 맞춤화 버퍼를 설정한다. 이것은 맞춤화 버퍼의 상단에서 검색 필드를 사용하는 것과 같다(412 페이지의 33.1.1절 [맞춤화 그룹(Customization Groups)] 참고).


새로운 Emacs 버전으로 업그레이드할 때는 새로운 설정, 그리고 의미 또는 기본 값이 변경된 설정의 맞춤화를 고려하고자 할 것이다. 이를 위해서는 M-x customize-changed 를 이용하고, 미니버퍼를 사용해 이전 Emacs 버전 번호를 명시한다. 그러면 명시된 버전 이후로 변경된 정의를 가진 설정 및 그룹을 모두 표시하는 맞춤화 버퍼를 생성하면서 필요 시 그들을 로딩한다.


설정을 변경한 후 변경된 내용이 실수였다고 결정하는 경우 변경 사항을 다시 방문하기 위해 두 개의 명령어를 사용할 수 있다. 사용자가 저장한 설정을 맞춤화하려면 M-x customize-saved 를 사용한다. 사용자가 설정하였으나 저장하지 않은 설정을 맞춤화하려면 M-x customize-unsaved 를 사용한다.


커스텀 테마(Custom Themes)

Custom 테마는 단위로 활성화되거나 비활성화될 수 있는 설정의 집합체이다. Custome 테마는 설정의 다양한 집합체들 간에 쉽게 전환하고 한 컴퓨터에서 다른 컴퓨터로 그러한 집합체를 전달하는 데에 사용할 수 있다.


Custom 테마는 Emacs Lisp 소스 파일로서 보관된다. Custom 테마명이 name 일 경우 테마 파일은

name-theme.el

이다. 테마 파일의 포맷과 그것을 만드는 방법에 관한 내용은 419 페이지의 33.1.8절 [커스텀 테마 생성하기(Creating Custom Themes)]를 참고한다.


Emacs 가 이해하는 Custom 테마를 열거한

*Custom Themes*

라는 버퍼로 전환하려면 M-x customize-themes 를 입력한다. 기본적으로 Emacs는 두 가지 위치에서 테마 파일을 검색하는데, 하나는

custom-theme-directory

변수가 명시한 디렉터리이고 (기본값이

~/.emacs.d/

), 다른 하나는 Emacs 설치에

etc/themes

로 명명된 디렉터리이다(

data-directory

변수 참고). 후자는 Emacs 와 함께 배포되는 여러 Custom 테마를 포함하는데, 이는 Emacs 의 겉모습이 다양한 색상 schemes 에 일치하도록 맞춤화한다. (하지만 Custom 테마를 이러한 용도로 제한할 필요는 없는 것이, 변수의 맞춤화에도 사용 가능하기 때문이다.)


Emacs 가 일부 다른 디렉터리에서 Custom 테마를 검색하길 원한다면

custom-theme-load-path

목록 변수로 디렉터리명을 추가한다. 그 기본값은

(custom-theme-directory t)

인데, 여기서

custom-theme-directory

심볼은

custom-theme-directory

변수의 값에 대해 특별한 의미를 가지며,

t

는 내장된(built-in) 테마 디렉터리

etc/themes

를 의미한다.

*Custom Themes*

버퍼에 열거된 테마는

custom-theme-load-path

에서 명시한 디렉터리에서 발견된다.


*Custom Themes*

버퍼에서는 Custom 테마 옆에 체크박스를 활성화하여 현재 Emacs 세션에 대한 테마를 활성화하거나 비활성화할 수 있다. Custom 테마가 활성화되면 그 모든 설정(변수와 겉모습)은 Emacs 세션에서 효력을 발휘한다. 추후 Emacs 세션으로 테마의 선택을 적용하려면 C-x C-s (

custom-theme-save

)를 입력하거나 '

[Save Theme Settings]

' 버튼을 사용한다.


Custom 테마를 처음으로 활성화하면 Emacs 는 테마 파일의 내용을 표시하면서 실제로 로딩하길 원하는지 질문한다. Custom 테마를 로딩하면 임의의 Lisp 코드를 실행할 수 있으므로 테마가 안전하다고 확신할 때에만 yes 로 답해야 하고, 이런 경우 Emacs는 테마가 안전함을 기억하도록 권한다(이는 파일의 SHA-256 해시를

custom-safe-themes

변수로 저장하여 이루어지는데, 모든 테마를 안전하다고 취급하길 원한다면 그 값을 t로 변경한다). Emacs와 함께 따라오는 테마들은 (

etc/themes

디렉터리에 위치) 이러한 검사에서 제외되며 항상 안전하다고 간주된다.


Custom 테마의 설정 또는 저장은 사실상

custom-enabled-themes

변수를 맞춤화하여 이루어진다. 이 변수의 값은 Custom 테마명의 목록이다(Lisp 심볼로서 tango 를 예로 들 수 있다).

custom-enabled-themes

를 설정하기 위해

*Custom Themes*

버퍼를 사용하는 대신 가령 M-x customize-option 과 같은 일반적인 맞춤화 인터페이스를 이용하여 변수를 맞춤화할 수도 있다. Custom 테마들이 자체적으로

custom-enabled-themes

를 설정하는 것은 허용되지 않음을 주목한다.


맞춤화 버퍼를 통해 이루어지는 맞춤화는 테마 설정보다 우선한다. 이는 사용자로 하여금 동의하지 않는 개별 테마 설정을 쉽게 오버라이드하도록 해준다. 두 가지 다른 테마의 설정이 중복될 경우

custom-enabled-themes

에 일찍 발생한 테마가 우선한다. 맞춤화 버퍼에서 설정이 Custom 테마에 의해 기본값으로부터 변경된 경우 그 '

State

' 디스플레이는 '

STANDARD

' 대신 '

THEMED

' 를 표시한다.


M-x load-theme 을 입력하면 현재 Emacs 세션에서 특정 Custom 테마를 활성화할 수 있다. 이는 테마명의 입력을 요하고, 테마 파일로부터 테마를 로딩하여 활성화한다. 테마 파일이 이전에 로딩된 적이 있다면 M-x enable-theme 을 입력하여 테마 파일을 로딩하지 않고 테마를 활성화할 수 있다. Custom 테마를 비활성화하려면 M-x disable-theme 을 입력한다.


Custom 테마의 설명을 확인하려면

*Custom Themes*

버퍼에서 해당 행에 ? 를 입력하거나, Emacs 아무 데서나 M-x describe-theme 을 입력한 후 테마 이름을 입력한다.


Custom 테마 생성하기(Creating Custom Themes)

M-x customize-create-theme 을 입력하면 맞춤화 버퍼와 유사한 인터페이스를 이용해 Custom 테마를 정의할 수 있다. 이는

*Custom Theme*

이라는 버퍼로 전환한다. 또한 일부 공통된 Emacs faces 를 테마로 삽입할 것을 권하기도 한다(Custom 테마가 face의 맞춤화에 사용되곤 하기 때문에 편의를 목적으로 한다). no 라고 답하면 테마는 처음에 어떠한 설정(settings)도 포함하지 않을 것이다.


*Custom Theme*

버퍼의 상단 주위에는 테마명과 설명을 입력할 수 있는 편집 가능 필드가 위치한다. 이름은 '

user

' 를 제외한 어떤 것이든 가능하다. 설명은 테마에 대해 M-x describe-theme 를 호출하면 표시될 이름이다. 첫 라인은 한 문장으로 된 간략한 요약을 표시하고, M-x customize-themes 로 만들어진 버퍼에서 이 문장은 테마명 옆에 표시된다.


테마에 새로운 설정을 추가하려면 '

[Insert Additional Face]

' 또는 '

[Insert Additional Variable]

' 버튼을 사용하라. 각 버퍼는 미니버퍼를 이용해 완성의 도움을 받아 face 또는 버퍼 이름을 읽고 겉모습 또는 변수에 대한 맞춤화 엔트리를 삽입한다. 변수 값이나 겉모습 속성도 일반 맞춤화 버퍼에서와 동일한 방식으로 편집할 수 있다. 겉모습 또는 변수를 테마에서 제거하려면 이름 옆의 체크박스를 체크 해제한다.


Custom 테마의 겉모습과 변수를 명시하고 나면 C-x C-s (

custom-theme-write

)를 입력하거나 버퍼의 '

[Save Theme]

' 버튼을 사용하라. 이는 테마명이 name

name-theme.el

이라는 테마 파일을

custom-theme-directory

가 명명한 디렉터리로 저장한다.


'

[Visit Theme]

' 버튼을 활성화하고 테마명을 명시하면

*Custom Theme*

버퍼에서 '기존 Custom 테마를 확인하고 편집할 수 있다. '

[Merge Theme]

' 버튼을 이용하면 또 다른 테마의 설정을 버퍼로 추가할 수도 있다. '

[Merge Theme]

' 버튼을 이용해 '

user

' 라는 특수 테마를 명시하면 테마 이외의(non-theme) 설정을 Custom 테마로 가져올 수도 있다.


테마 파일은 단순한 Emacs Lisp 소스 파일로, Custom 테마의 로딩은 Lisp 파일을 로딩하여 실행된다. 따라서

*Custom Theme*

버퍼를 사용하는 대신 테마 파일을 직접 편집할 수 있다. 상세한 내용은 The Emacs Lisp Reference Manual 의 "Custom Themes" 절을 참고한다.


변수(Variables)

변수(variable)는 값을 가진 Lisp 심볼로, 심볼명은 변수명(variable name)이라 부르기도 한다. 변수명은 파일에 표시할 수 있는 문자라면 뭐든 사용 가능하지만 대부분 변수명은 하이픈으로 구분된 일반 단어로 구성된다.


변수명은 변수의 역할에 대한 간략한 설명을 하기도 한다. 대부분의 변수는 변수의 목적, 변수가 가질 수 있는 값, 값을 사용하는 방법을 설명하는 문서 문자열(documentation string)을 가지기도 한다. 이러한 문서는 도움말 명령어인 C-h v (

describe-variable

) 를 입력하여 확인한다. 421 페이지의 33.2.1절 [조사하기(Examining)]를 참고한다.


Emacs 는 내부 기록 보관에 다수의 Lisp 변수를 사용하지만 프로그래머가 아닌 사용자에게 가장 흥미로운 변수들은 사용자가 변경하도록 만들어진 변수들로, 맞춤 가능한 변수(customizable variables) 또는 사용자 옵션(user options)이라고 부른다(412 페이지의 33.1절 [쉬운 맞춤화(Easy Customization)] 참고). 다음으로 소개할 절에서는 Customize 외부에서 Emacs 변수들을 설정하는 방법을 비롯해 변수들의 여러 측면들에 대해 설명하고자 한다.


Emacs Lisp는 (몇 가지만 제외한) 어떤 변수든 원하는 종류의 값을 가지도록 허용한다. 하지만 많은 변수들이 특정 유형의 값이 할당될 때에만 의미 있게 사용된다. 가령 링버퍼 제거(kill ring)의 최대 길이를 명시하는

kill-ring-max

의 값은 숫자일 때에만 의미가 있으며(55 페이지의 9.2.2절 [이전 제거 내용 붙여넣기(Earlier Kills)] 참고),

kill-ring-max

값으로 문자열을 제공하면 C-y (

yank

)와 같은 명령어들은 오류를 보낼 것이다. 반면 어떤 변수들은 값의 유형을 신경 쓰지 않는데, 가령 변수가

nil

값에 어떤 효과를 보이고 "non-

nil

" 값에 다른 효과를 보인다면

nil

심볼이 아닌 모든 값은 타입과 상관없이 두 번째 효과를 야기한다(관습에 따라 non-

nil

값을 명시할 때는 "true" 를 의미하는 심볼인

t

값을 주로 사용한다). 맞춤화 버퍼를 이용해 변수를 설정할 경우 무효한 타입을 제공하는 것을 염려하지 않아도 되는 것이, 맞춤화 버퍼는 주로 의미가 있는 값만 입력하도록 허용하기 때문이다. 확실치 않을 때는 C-h v (

describe-variable

) 를 이용하여 변수의 문서 문자열에서 그것이 기대하는 값의 유형을 확인하라(421 페이지의 33.2.1절 [조사하기(Examining)] 참고).


변수 조사하고 설정하기(Examining and Setting Variables)

C-h v var RET

변수 var 의 값과 문서를 표시한다(

describe-variable

).


M-x set-variable RET var RET value RET

변수 var 의 값을 value 로 변경한다.


변수의 값을 조사하기 위해서는 C-h v (

describe-variable

)를 사용하라. 이는 미니버퍼를 이용해 완성의 도움으로 변수명을 읽어 변수의 값과 그 문서를 표시한다. 가령 아래와 같이 사용하면,


C-h v fill-column RET


아래와 같은 내용을 표시한다:

fill-column is a variable defined in 'C source code', 
fill-column's value is 70


Automatically becomes buffer-local when set.
This variable is safe as a file local variable if its value
satisfies the predicate 'integerp'.


Documentation:
Column beyond which automatic line-wrapping should happen.
Interactively, you can set the local value with C-x f.


You can customize this variable.


"You can customize the variable" 이라고 적힌 라인은 이 변수가 사용자 옵션임을 나타낸다. C-h v 는 사용자 옵션으로 제한되어 있지 않으며 맞춤화가 불가능한(non-customizable) 변수도 허용한다.


가장 편리하게 특정 맞춤화 가능한 변수를 설정하는 방법은 M-x set-variable 을 사용하는 것이다. 이는 미니버퍼로 (완성을 이용해) 변수명을 읽은 다음 미니버퍼를 두 번째로 이용하여 새 값에 대한 Lisp 표현식을 읽는다(M-n 을 통해 편집하도록 미니버퍼로 오래된 값을 삽입할 수 있다). 아래를 예로 들면,

M-x set-variable RET fill-column RET 75 RET


fill-column 을 75 로 설정한다.


M-x set-variable 은 맞춤화 가능한 변수로 제한되지만 Lisp 표현식을 이용해 어떤 변수든 아래와 같이 설정할 수 있다:

(setq fill-column 75)


그러한 표현식을 실행하려면 M-: (

eval-expression

)을 입력한 후 미니버퍼에 표현식을 입력한다(278 페이지의 24.9절 [Lisp Eval] 참고). 아니면

*scratch*

버퍼로 이동하여 표현식을 입력하고 C-j 를 입력하도록 한다(279 페이지의 24.10절 [Lisp 상호작용(Lisp Interaction)] 참고).


따로 명시하지 않는 이상 변수의 설정은 Emacs 의 일반적인 맞춤화 방식과 마찬가지로 현재 Emacs 세션에만 영향을 미친다. 이후 세션에서 변수를 수정하려면 변수를 초기화 파일에 넣는 방법밖에 없다(437 페이지의 33.4절 [Init 파일(Init File)] 참고).


훅(Hooks)

훅(hooks)은 Emacs를 맞춤화하는 데에 중요한 메커니즘이다. 훅은 몇몇 잘 정의된 경우에 호출할 함수 목록을 보유한 Lisp 변수이다. (이것을 훅을 실행한다(running the hook)고 말한다.) 목록 내 각 함수는 훅의 훅 함수(hook functions)라고 부른다. 가령

kill-emacs-hook

훅은 Emacs 를 끝내기 직전에 실행된다(15 페이지의 3.2절 [끝내기(Exiting)] 참고).


대부분의 훅은 정상 훅(normal hooks)이다. 즉, Emacs 가 훅을 실행하면 인자 없이 훅 함수를 차례로 호출함을 의미한다. 우리는 대부분 훅을 일반 훅으로 유지하기 위해 최선을 다했기 때문에 획일화된 방식으로 이용할 수 있을 것이다. 이름이 '

-hook

' 으로 끝나는 함수는 정상 훅이다.


이에 반해 비정상 훅(abnormal hooks)도 몇 가지가 있는데, 이러한 훅의 이름은 '

-hook

' 이 아니라 '

-functions

' 로 끝난다(일부 오래된 코드는 '

-hooks

' 라는 오래된 접두어를 사용하기도 한다). 이러한 훅은 함수가 호출되는 방식 때문에 비정상이라고 부르는데, 함수에 인자가 제공되는 경우도 있고 그것이 리턴하는 값이 사용되기도 하기 때문이다. 가령

find-file-not-found-functions

는 어떤 훅 함수가 non-

nil

값을 리턴하는 즉시 나머지는 아예 호출되지 않기 때문에 비정상적인 훅이다(123 페이지의 15.2절 [방문하기(Visiting)] 참고). 비정상 훅 변수에 관한 각 문서에서 이러한 함수들이 어떻게 사용되는지 설명하고 있다.


다른 Lisp 변수와 마찬가지로 훅 변수 역시

setq

를 이용해 설정할 수 있지만 함수를 훅으로 (정상 훅이든 비정상 훅이든) 추가할 때는 아래에서 소개할

add-hook

을 사용하길 권한다. 상세한 내용은 The Emacs Lisp Reference Manual}} 의 "Hooks" 절을 참고한다.


대부분의 주 모드는 초기화 마지막 단계로 하나 또는 그 이상의 모드 훅(mode hooks)을 실행한다. 모두 훅은 각 모드의 동작을 간편하게 맞춤화하는 방법으로, 항상 정상 훅에 해당한다. 가령 Text 모드와 그를 바탕으로 한 다른 모드에서 Auto Fill 모드를 켜기 위해 훅을 설정하는 방법은 다음과 같다:

(add-hook 'text-mode-hook 'auto-fill-mode)


이것은 인자가 제공되지 않을 때 부 모드를 켜는

auto-fill-mode

를 호출함으로써 작동한다(200 페이지의 20.2절 [부 모드(Minor Modes)] 참고). 그 다음으로, Text 모드를 기반으로 하는 모드인 LaTeX 모드에서 Auto Fill 모드를 켜고 싶지 않다고 가정하자. 이때는 다음 라인을 이용할 수 있다:

(add-hook 'latex-mode-hook (lambda () (auto-fill-mode -1)))


여기서 익명의 함수를 구성하기 위해 특수 매크로

lambda

를 사용했는데 (The Emacs Lisp Reference Manual 의 "Lambda Expressions" 절 참고), 이것은 인자가

-1

auto-fill-mode

를 호출하여 부 모드를 끈다. LaTeX 모드는

text-mode-hook

을 실행한 후에

latex-mode-hook

을 실행하기 때문에 그 결과 Auto Fill 모드를 끈 채로 둔다.


C 코드의 들여쓰기를 맞춤화하기 위해 훅을 사용하는 방법을 보여주는 조금 더 복잡한 예를 소개하겠다:

(setq my-c-style
  '((c-comment-only-line-offset . 4)
   (c-cleanup-list . (scope-operator
                      empty-defun-braces 
                      defun-close-semi))))

(add-hook 'c-mode-common-hook
  (lambda () (c-add-style "my-style" my-c-style t)))


주 모드 훅은 오리지널(original) 모드에서 파생된(derived) 다른 주 모드에도 적용된다(The Emacs Lisp Reference Manual의 "Derived Modes"절 참고). 가령 HTML 모드는 Text 모드에서 파생되는데(228 페이지의 22.11절 [HTML Mode] 참고), HTML 모드가 켜지면

html-mode-hook

을 실행하기 전에

text-mode-hook

이 실행된다. 이는 하나의 훅을 이용해 여러 상관된 모드에 영향을 미치는 편리한 방법을 제공한다. 특히 훅 함수를 어떤 프로그래밍 언어 모드에든 적용하려면

prog-mode-hook

으로 추가하면 되는데, Prog 모드는 정확히 이러한 목적을 위해 다른 주 모드들이 그로부터 상속되도록 허용하는 것 외에는 하는 일이 거의 없는 주 모드다.


따라서 훅 함수가 실행되는 방식이 중요하지 않도록 함수를 설계하는 것이 최선이다. 순서에 의존하게 되면 문제가 발생할 수 밖에 없다. 하지만 훅 함수는 훅에 표시되는 순서대로 실행되기 때문에 순서의 예측이 가능하다.


add-hook

을 반복하여 호출함으로써 훅 함수의 다양한 버전을 추가하고자 한다면 당신이 추가한 버전들은 훅 변수에 모두 남아 있을 것이라는 사실을 명심하라. 이때 함수를 개별적으로 제거하려면

remove-hook

을 호출하고, 한 번에 모두 제거하려면

(setq hook-variable nil)

을 실행하라.


훅 변수가 버퍼 로컬 변수일 경우, 전역적 변수 대신 버퍼 로컬 변수가 사용될 것이다. 하지만 버퍼 로컬 변수가

t

요소를 포함할 경우 전역적 훅 변수 역시 실행될 것이다.


로컬 변수(Local Variables)

M-x make-local-variable RET var RET

변수 var가 현재 버퍼에 로컬 값을 갖도록 만든다.


M-x kill-local-variable RET var RET

변수 var가 현재 버퍼에서 전역적 값을 사용하도록 만든다.


M-x make-variable-buffer-local RET var RET

변수 var를 설정하면 당시 현재 버퍼에 제한되도록(local) 변수를 마크한다.


거의 모든 변수는 특정 Emacs 버퍼에 대해 제한되게(local) 만들 수 있다. 즉, 해당 버퍼 내에서 변수 값은 다른 버퍼 내 변수의 값과 무관하다는 의미다. 일부 변수들은 항상 모든 버퍼에서 제한되기도(local) 한다. 대부분의 Emacs 변수는 전역적 값을 가지는데, 이는 변수를 제한하지(local) 않은 모든 버퍼에 영향을 미친다.


M-x make-local-variable 은 변수명을 읽어와 현재 버퍼로 제한(local)한다. 해당 버퍼에서 그 값을 변경하면 다른 버퍼에는 영향을 미치지 않으며, 전역적 값을 변경하더라도 해당 버퍼에는 영향을 미치지 않을 것이다.


M-x make-variable-buffer-local 은 변수를 설정할 때마다 자동으로 제한(local)하도록 마크한다. 좀 더 정확히 말해, 변수를 이러한 방식으로 마크하고 나면 변수를 일반적인 방식으로 설정 시

make-local-variable

이 먼저 실행될 것임을 의미한다. 이러한 변수를 버퍼별(per-buffer) 변수라고 부른다. Emacs의 많은 변수들이 보통 버퍼별 변수들인데, 변수의 문서 문자열은 언제 그러한지를 알려준다. 버퍼별 변수의 전역적 값은 보통 어떤 버퍼에서도 절대 효과를 발휘하지 않지만 각 새 버퍼에 대한 변수의 초기값이라는 의미를 지닌다.


주 모드는 (199 페이지의 20.1절 [주 모드(Major Modes)] 참고) 항상 변수를 설정하기 전에 변수를 버퍼에 제한(local)되도록 만든다. 그래서 하나의 버퍼에서 주 모드를 변경하여도 다른 버퍼에는 영향을 미치지 않는 것이다. 부 모드는 항상 변수의 설정을 통해 작동하는데, 보통 부 모드마다 하나의 제어하는(controlling) 변수를 갖고 있으며 모드가 켜지면 non-nil 값을 가진다(200 페이지의 20.2절 [부 모드(Minor Modes)] 참고). 대다수의 부 모드의 경우 제어하는 변수가 버퍼별로 존재하므로 항상 버퍼 로컬(buffer-local)이다. 아니면 여느 다른 변수와 마찬가지로 특정 버퍼에서 로컬로 만들 수 있다.


일부 변수들은 각 디스플레이에 항상 로컬로 되어 있어 버퍼에 대해 로컬로 설정할 수가 없다(171 페이지의 18.10절 [다중 디스플레이(Multiple Displays)] 참고). 이러한 변수들 중 하나를 버퍼 로컬로 만들려고 시도하면 오류 메시지를 얻게 될 것이다.


M-x kill-local-variable 은 명시된 변수를 현재 버퍼에 제한되지(local) 않도록 만든다. 이후 변수의 전역적 값이 해당 버퍼에서 효력을 발휘한다. 주 모드를 설정하면 특히 영구적 로컬 변수(permanent locals)라고 마크된 변수 몇 개만 제외하고 버퍼의 로컬 변수를 모두 제거(kill)한다.


변수가 현재 버퍼에서 로컬 값을 갖는지 여부와 상관없이 변수의 전역적 값을 설정하려면 Lisp 구조체인

setq-default

를 사용할 수 있다. 이 구조체는

setq

와 같이 사용되지만 로컬 값 대신 변수의 전역적 값을 설정한다. 현재 버퍼가 로컬 값을 갖고 있다면 사용자가 다른 버퍼로 전환할 때까지 새로운 전역적 값이 표시되지 않을지도 모른다. 예를 들어보겠다:

(setq-default fill-column 75)


setq-default

make-variable-buffer-local

을 이용해 마크된 변수의 전역적 값을 설정하는 유일한 방법이다.


Lisp 프로그램은 변수의 기본값을 살펴보기 위해

default-value

를 사용할 수 있다. 이 함수는 심볼을 인자로 취하고 그 기본값을 리턴한다. 이후 인자가 평가되는데, 보통은 사용자가 명시적으로 인용(quote)해야 한다. 가령

fill-column

의 기본값을 얻는 방법은 다음과 같다:

(default-value 'fill-column)


파일 내 로컬 변수(Local Variables in Files)

파일은 Emacs로 편집 시 사용할 로컬 변수 값을 명시할 수 있다. 파일을 열면 로컬 변수 명세를 확인하면서 자동으로 이러한 변수들을 버퍼에 제한(local)되도록 만들고, 변수를 파일에 명시된 값으로 설정한다.

파일 변수 명시하기(Specifying File Variables)

파일 로컬 변수의 값을 명시하는 방법에는 두 가지가 있다: 첫 라인에 명시하거나 로컬 변수 목록을 이용하는 방법이다. 첫 번째 라인에 명시하는 방법은 다음과 같다.

-*- mode: modename; var: value; ... -*-


이러한 방식으로 원하는 수만큼 변수/값 쌍을 명시하고, 각 쌍은 콜론과 세미콜론을 포함한다. 특수 변수/값 쌍인

mode: modename;

이 존재할 경우 주 모드를 명시한다. values 는 그대로 사용되고 평가되지 않는다.


수동으로 엔트리를 추가하는 대신 M-x add-file-local-variable-prop-line 을 사용할 수 있다. 이 명령어는 변수의 값을 입력하도록 요하여 값을 적절한 방법으로 첫 라인에 추가한다. M-x delete-file-local-variable-prop-line 명령어는 변수의 입력을 요하고, 라인으로부터 그 엔트리를 삭제한다. M-x copy-dir-locals-to-file-locals-prop-line 명령어는 현재 디렉터리에 로컬인(directory-local) 변수를 첫 라인으로 복사한다(427 페이지의 33.2.5절 [디렉터리 변수(Directory Variables)] 참고).


Lisp 모드를 명시하고 두 변수를 수치적 값으로 설정하는 첫 라인의 예를 들어보겠다:

;; -*- mode: Lisp; fill-column: 75; comment-column: 50; -*-


mode

이외에 파일 변수로서 특별한 의미를 지닌 다른 키워드로는

coding

,

unibyte

,

eval

이 있다. 이를 아래에서 설명하겠다.


셸 스크립트에서 첫 라인은 스크립트 해석기를 식별하는 데에 사용되므로 그곳에는 어떠한 로컬 변수도 넣어선 안 된다. 이를 위해서는 첫 라인에 해석기가 명시되어 있을 경우 Emacs 는 두 번째 라인에서 로컬 변수 명세를 검색한다. Troff 전처리기 목록을 명시하기 위해 마법의 문자열 '

'\"

'로 시작하는 (모두 그런 것은 아니다) 맨 페이지(man page)의 경우도 마찬가지다.


'

-*-

' 라인을 이용하는 것 외에도 파일의 끝부분 근처에 로컬 변수 목록(local variables list)을 이용해 파일 로컬 변수를 정의할 수 있다. 로컬 변수 목록의 시작은 파일 끝에서 3000 개 이하의 문자여야 하고, 파일이 여러 페이지로 나누어져있다면 마지막 페이지에 위치해야 한다.


파일이 로컬 변수 목록과 '

-*-

' 라인을 모두 갖고 있다면 Emacs 는 '

-*-

' 라인에서 먼저 모든 것(everything)을 처리한 다음 로컬 변수 목록의 모든 것을 처리해야 한다. 단, 주 모드 명세는 제외된다. Emacs는 주 모드 명세가 나타날 때마다 먼저 적용하는데, 대부분의 주 모드는 모든 로컬 변수를 초기화의 일부로서 죽이기(kill) 때문이다.


로컬 변수 목록은 '

Local Variables:

' 문자열을 포함한 라인으로 시작하여 '

End:

' 문자열을 포함하는 라인으로 끝난다. 그 중간에는 아래와 같이 하나의 라인마다 변수명과 값이 위치한다:

/* Local Variables:    */ 
/* mode: c             */
/* comment-column:   0 */ 
/* End:                */


이 예제에서 각 라인은 '

/*

' 접두사로 시작하여 '

*/

' 접미사로 끝난다. Emacs는 목록의 첫 번째 라인에서 마법의 문자열 '

Local Variables:

' 로 둘러싸인 접두사와 접미사를 검색하여 그들을 인식한 후, 목록의 다른 라인에서 그것들을 자동으로 삭제(discard)한다. 접두사와 접미사를 사용하는 일반적인 이유는 파일의 용도가 다른 프로그램에서 혼동하지 않도록 주석에 로컬 변수 목록을 포함(embed)시키기 위함이다. 위는 주석이 '

/*

' 로 시작하여 '

*/

' 로 끝나는 C 프로그래밍 언어를 예로 든 것이다.


로컬 변수 목록에 직접 입력하는 대신 M-x add-file-local-variable 명령어를 사용하는 방법도 있다. 이 명령어를 사용하면 변수와 값을 입력하도록 요구하여 목록으로 추가하고, 필요 시에는 '

Local Variables:

' 문자열과 시작 및 끝 마커도 추가한다. M-x delete-file-local-variable 명령어는 목록에서 변수를 삭제한다. 그리고 M-x copy-dir-locals-to-file-locals 명령어는 디렉터리에 로컬로 된(directory-local) 변수를 목록으로 복사한다(427 페이지의 33.2.5절 [디렉터리 변수(Directory Variables)] 참고).


'

-*-

' 라인과 마찬가지로 로컬 변수 목록 내 변수들은 문자 그대로 사용되고 먼저 평가되지 않는다. 파일의 여러 행에 걸쳐 긴 문자열 값을 나누고 싶을 경우, 백슬래시-새 행을 이용하면 Lisp 문자열 상수에서 무시되므로 각 라인마다 접두사와 접미사를 위치시켜야 하는데, 심지어 문자열 내에서 시작되거나 끝나는 라인에도 위치시켜야만 목록에서 처리하면서 사라질 것이다(stripped off).

# Local Variables:
# compile-command: "cc foo.c -Dfoo=bar -Dhack=whatever \
#   -Dmumble=blaah"
# End:


몇몇 "변수명(variable names)"은 로컬 변수 목록에서 특별한 의미를 지닌다:

  • mode
    는 명시된 주 모드를 켠다.
  • eval
    은 명시된 Lisp 표현식을 평가한다(해당 표현식이 리턴한 값은 무시된다).
  • coding
    은 이 파일의 문자 코드 변환에 사용할 코딩 시스템을 명시한다. 183 페이지의 19.5절 [코딩 시스템(Coding Systems)]을 참고한다.
  • unibyte
    는 값이
    t
    일 경우 Emacs Lisp 의 파일을 유니바이트 모드로 로딩하거나 컴파일하라고 말한다. GNU Emacs Lisp Reference Manual 의 "Disabling Multibyte Characters" 절을 참고한다.


이 4개의 키워드는 사실상 변수가 아니며, 다른 컨텍스트에서 설정할 경우 어떤 특별한 의미도 지니지 않는다.


부 모드에

mode

키워드를 사용하지 말라. 로컬 변수 목록에서 부 모드를 켜거나 끄려면 모드 명령어를 실행하는 Lisp 표현식으로 eval 키워드를 사용하라(200 페이지의 20.2절 [부 모드(Minor Modes)] 참고). 예를 들어, 다음 로컬 변수 목록은 인자 없이

eldoc-mode

를 호출(인자를

1

로 하여 호출하여도 동일한 일을 수행한다)함으로써 Eldoc 모드를 켜고 (200 페이지의 20.2절 [부 모드(Minor Modes)] 참고),

-1

을 인자로 하여

font-lock-mode

를 호출함으로써 Font Lock 모드를 끈다(78 페이지의 11.12절 [폰트 잠금(Font Lock)] 참고).

;; Local Variables: 
;; eval: (eldoc-mode) 
;; eval: (font-lock-mode -1) 
;; End:


하지만 이런 방식으로 부 모드를 명시하는 방법이 실수로 작용하는 경우도 종종 있다. 부 모드는 사용자 개인설정(user preferences)을 나타내기 때문에 파일을 편집하고자 하는 다른 사용자에게 당신의 개인설정을 강요하는 것이 부적절할지도 모르기 때문이다. 상황에 따라 부 모드를 자동으로 켜거나 끄길 원한다면 주 모드 훅에서 이를 실행하는 편이 더 나을지도 모른다(422 페이지의 33.2.2절 [훅(Hooks)] 참고).


로컬 변수 목록을 비롯해 내용과 파일명에 따라 버퍼의 주 모드 및 로컬 변수를 리셋하려면 M-x normal-mode 명령어를 사용하라. 관련 내용은 202 페이지의 20.3절 [모드 선택하기(Choosing Modes)]를 참고한다.


파일 변수의 안전성(Safety of File Variables)

파일 로컬 변수(file-local variables)는 당신이 다른 사람의 파일을 열 때 그 로컬 변수 목록이 당신의 Emacs에 어떠한 일을 수행할 것인지 알려줄 방법이 없기 때문에 위험할 수가 있다.

eval

"변수", 그리고

load-path

와 같은 다른 변수들의 부적절한 값 역시 의도하지 않은 Lisp 코드의 실행을 야기할 수도 있다.


따라서 Emacs 가 안전하다고 알려지지 않은 파일 로컬 변수 값을 마주칠 때마다 파일의 전체 로컬 변수 목록을 표시하고, 설정 전에 사용자의 확인을 요청할 것이다. 로컬 변수 목록을 실행하려면 y 또는 SPC 를 입력하고, 무시하려면 n 을 입력하라. Emacs 가 배치(batch) 모드에서 실행되는 경우 (480 페이지의 C.2절 [초기 옵션(Initial Options)] 참고) 사용자에게 질문할 수가 없으므로 답이

n

일 것이라고 추측한다.


Emacs 는 보통 특정 변수/값 쌍을 안전하다고 인식한다. 가령

comment-column

이나

fill-column

에는 어떤 정수 값을 제공하든 안전하다. 파일이 안전하다고 알려진 변수/값 쌍만 명시할 경우 Emacs 는 설정 전에 확인을 요청하지 않는다. 하지만 안전하다고 확인되지 않으면 사용자는 확인 프롬프트에서 ! 를 입력함으로써 Emacs에게 이 파일 내 모든 변수/값 쌍을 안전함을 기록하도록 알릴 수 있다. Emacs 가 이후 동일한 파일이나 다른 파일에서 이러한 변수/값 쌍을 마주치면 안전하다고 추측할 것이다.


load-path

와 같은 일부 변수들은 특히 위험한(risky) 것으로 간주되는데, 이러한 변수들을 로컬 변수로 명시하는 경우가 드물며, 그 값을 변경할 경우 위험에 처할 수 있다. 파일이 위험한 로컬 변수만 포함할 경우 Emacs는 확인 프롬프트에서 ! 를 입력값으로 권하지도 않고 허용하지도 않는다. 파일 내 로컬 변수의 일부만 위험하고 일부는 잠재적으로 안전하지 않은 경우 프롬프트에 ! 를 입력할 수 있다. 이것은 모든 변수에 적용되지만 추후 위험하지 않은 변수들만 마크한다. 위험한 변수에 대해 안전한 값을 기록하고 싶다면 '

safe-local-variable-values

' 를 맞춤화하여 직접 기록하라(412 페이지의 33.1절 [쉬운 맞춤화(Easy Customization)] 참고).


enable-local-variables

변수는 Emacs 가 로컬 변수를 처리하는 방법을 변경하도록 해준다. 기본값

t

는 위에서 설명한 동작을 명시한다. 값이

nil

일 경우 Emacs 는 모든 파일 로컬 변수를 단순히 무시한다.

:safe

는 안전한 값만 사용하고 나머지는 무시함을 의미한다. 그 외 모든 값은 안전하다고 알려진 값인지 결정하지 말고 로컬 변수를 가진 파일마다 사용자에게 질의(query)하도록 알릴 것이다.


enable-local-eval

변수는 Emacs 가

eval

변수를 처리할 것인지를 제어한다. 변수의 가능한 값으로는

enable-local-variables

와 마찬가지로 세 가지가 있는데

t

,

nil

, 그 외의 값이다. 기본값은

t

,

nil

이 아닌

mayb

e 로, Emacs 는

eval

변수의 처리와 관련해 확인을 요청하는 것이 보통이다.


한 가지 예외가 있는데,

eval

이란 형태가

safe-local-eval-forms

변수 내에서 발생할 경우

eval

폼을 평가할 것인지에 대한 확인을 절대 요청하지 않는다.


디렉터리별 로컬 변수(Per-Directory Local Variables)

가끔은 동일한 로컬 변수 집합을 특정 디렉터리 및 그 하위디렉터리 (예: 대규모 소프트웨어 프로젝트의 디렉터리 트리) 내 모든 파일로 정의하길 원할 경우도 있을 것이다. 이때 디렉터리 로컬 변수(directory local variables)를 이용하면 된다.


디렉터리 로컬 변수(directory-local variables)는 보통

.dir-locals.el

[1] 로 명명된 파일을 디렉터리에 넣어 명시한다. Emacs 가 해당 디렉터리나 그 하위디렉터리에 위치한 파일을 열 때마다

.dir-locals.el

에 명시된 디렉터리 로컬 변수가 마치 파일 로컬 변수(file-local variables)로 정의된 것처럼 디렉터리 로컬 변수로 적용될 것이다(424 페이지의 33.2.4절 [파일 변수(File Variables)] 참고). Emacs 는 연 파일의 디렉터리에서 시작하여 디렉터리 트리의 상향으로 이동하면서

.dir-locals.el

을 검색한다. 속도 지연을 피하려면 원격 파일의 검색을 건너뛰어야 한다. 필요 시

enable-remote-dir-locals

변수를

t

로 설정하여 원격 파일로 검색을 확장할 수도 있다.


.dir-locals.el

파일은 주 모드명(심볼)을 alist로 매핑하는 특별하게 구성된 목록을 보유해야 한다(The Emacs Lisp Reference Manual 의 "Association Lists"절 참고). alist 엔트리는 명시된 주 모드가 켜지면 해당 변수로 할당할 디렉터리 로컬 값과 변수명으로 구성되어 있다. 모드명 대신 alist가 어떠한 모드로든 적용됨을 나타내는 '

nil

' 을 명시하거나, alist 가 해당 하위디렉터리 내 모든 파일에 적용됨을 나타내도록 하위디렉터리명(문자열)을 명시할 수도 있다.


.dir-locals.el

파일의 예를 들어보겠다:

((nil . ((indent-tabs-mode . t) 
         (fill-column . 80))) 
 (c-mode . ((c-file-style . "BSD")
            (subdirs . nil))) 
 ("src/imported" 
  . ((nil . ((change-log-default-name
              . "ChangeLog.local"))))))


이는 디렉터리 트리의 어떤 파일이든 '

indent-tabs-mode

' 와

fill-column

을 설정하고, C 소스 파일에 대한 들여쓰기 스타일을 설정한다.

subdirs

라는 특수 요소는 변수는 아니지만 C 모드 설정이 아무 하위디렉터리가 아닌 현재 디렉터리에서만 적용됨을 의미하는 특수 키워드이다. 마지막으로 이는

src/imported

하위디렉터리 내 어떤 파일이든 다른

ChangeLog

파일명을 명시한다.


수동으로

.dir-locals.el

파일을 편집하는 대신 M-x add-dir-local-variable 명령어를 사용할 수도 있다. 이는 모드 또는 하위디렉터리 이름, 변수, 값을 입력하도록 요구하고, 디렉터리 로컬 변수를 정의하는 엔트리를 추가한다. M-x delete-dir-local-variable 은 엔트리를 삭제한다. M-x copy-file-locals-to-dir-locals 는 현재 파일의 파일 로컬 변수를

.dir-locals.el

파일로 복사한다.


디렉터리 로컬 변수를 명시하는 또 다른 방법은

dir-locals-set-class-variables

함수를 이용해 변수/값 쌍으로 된 그룹을 디렉터리 클래스(directory class)에서 정의한 후,

dir-locals-set-directory-class

함수를 이용해 Emacs에게 어떤 디렉터리가 클래스에 일치하는지 알려주는 방법이다. 이러한 함수 호출은 보통 초기화 파일로 이동한다(437 페이지의 33.4절 [Init 파일(Init File)] 참고). 이 방법은 어떤 이유로 디렉터리에

.dir-locals.el

을 넣을 수 없을 때 유용하다. 가령 쓰기가 불가능한(unwritable) 디렉터리로 설정을 적용할 때 이 방식을 사용할 수 있겠다:

(dir-locals-set-class-variables 'unwritable-directory 
   '((nil . ((some-useful-setting . value)))))

(dir-locals-set-directory-class
   "/usr/include/" 'unwritable-directory)


변수가 만일 명시된 디렉터리 로컬 값과 파일 로컬 값을 모두 가진다면 파일 로컬 값이 적용된다. 안전하지 않은 디렉터리 로컬 변수는 안전하지 않은 파일 로컬 변수와 동일하게 처리된다(426 페이지의 33.2.4.2절 [안전한 파일 변수(Safe File Variables)] 참고).


디렉터리 로컬 변수는 Dired 버퍼처럼 파일을 직접 열지는 않지만 디렉터리 내에서 작업을 실행하는 특정 버퍼에서도 효과를 발휘한다(315 페이지의 27장 [Dired] 참고).


키 바인딩 맞춤화하기(Customizing Key Bindings)

이번 절에서는 키를 명령어로 매핑하는 키 바인딩과 키 바인딩을 기록하는 키맵(keymaps)에 대해 설명하고자 한다. 또한 사용자의 init 파일을 편집함으로써 이루어지는 키 바인딩의 맞춤화 방법도 설명할 것이다(432 페이지의 33.3.6절 [Init 재바인딩(Init Rebinding)] 참고).

키맵(Keymaps)

12 페이지의 2.3절 [명령어(Commands)]에 설명한 바와 같이 각 Emacs 명령어는 상호작용적인 사용을 위해 제공하는 정의를 가진 Lisp 함수이다. 모든 Lisp 함수와 같이 명령어는 함수명을 가지는데, 함수명은 주로 소문자로 된 글자와 하이픈으로 구성된다.


키 시퀀스(key sequence; 줄여서 key)는 하나의 단위로서 의미를 가진 입력 이벤트(input events)의 시퀀스이다. 입력 이벤트는 문자, 기능키, 마우스 버튼을 비롯해 컴퓨터로 전송할 수 있는 모든 입력을 포함한다. 키 시퀀스는 그것이 실행하는 명령어를 알려주는 바인딩으로부터 의미를 얻는다.


키 시퀀스와 명령어 함수 간 바인딩은 키맵(keymaps)이라는 데이터 구조에 기록된다. Emacs는 각각 특정한 경우에 사용되는 키맵을 다수 포함한다.


전역적(global) 키맵은 항상 실행되기 때문에 가장 중요한 키맵이다. 전역적 키맵은 Fundamental 모드에 대한 키를 정의하고 (199 페이지의 20.1절 [주 모드(Major Modes)] 참고), 이러한 정의 대부분은 대다수 또는 모든 주 모드에 공통된다. 주 모드 또는 부 모드마다 일부 키에 대한 전역적 정의를 오버라이드하는 고유의 키맵을 가질 수 있다.


예를 들어,

g

와 같이 자체 삽입되는 문자는 전역적 키맵이 그것을

self-insert-command

명령어로 바인딩하기 때문에 자체 삽입된다. C-a 와 같은 표준 Emacs 편집 문자들은 전역적 키맵으로부터 표준 의미를 얻는다. 또한 M-x global-set-key 와 같이 키를 재바인딩하는 명령어들은 전역적 맵에서 적절한 위치에 새 바인딩을 보관함으로써 작동한다(431 페이지의 33.3.5절 [재바인딩(Rebinding)] 참고).


대부분의 현재 키보드는 문자 키뿐만 아니라 기능키도 갖고 있다. 기능 키는 문자 키와 마찬가지로 입력 이벤트를 전송하고, 키맵은 그에 대한 바인딩을 가질 수 있다. 키 시퀀스는 기능키와 문자를 혼합할 수 있다. 가령 키보드에 Home 기능키가 있다면 Emacs 는 C-x Home 과 같은 키 시퀀스를 인식할 수 있다는 의미다. 심지어 S-down-mouse-1 과 같이 마우스 이벤트와 키보드 이벤트를 혼합할 수도 있다.


텍스트 터미널 시스템에서 기능키를 입력하면 사실상 문자의 시퀀스를 컴퓨터로 전송하는데, 시퀀스의 세부적인 내용은 기능키와 터미널 타입에 따라 좌우된다. (시퀀스는 종종 ESC [ 로 시작된다.) Emacs 가 터미널 타입을 적절하게 이해하면 그러한 시퀀스를 단일 입력 이벤트로 자동 처리한다.


접두 키맵(Prefix Keymaps)

내부적으로 Emacs는 키맵마다 하나의 이벤트만 기록한다. 여러 이벤트로 된 키 시퀀스를 해석하는 데에는 키맵 사슬(chain)이 수반되는데, 첫 번째 키맵은 또 다른 키맵에 해당하는 첫 번째 이벤트에 대한 정의를 제공하고, 시퀀스에서 두 번째 이벤트를 검색하는 데에 사용되는 식이다. 따라서 C-x 또는 ESC 와 같은 접두 키는 해당 접두어 바로 뒤에 따라오는 이벤트에 대한 정의를 보유하는 고유의 키맵을 갖는다.


접두 키의 정의는 주로 다음 이벤트를 검색하는 데에 사용할 키맵이다. 정의는 뒤에 따라오는 키맵을 함수 정의로 가진 Lisp 심볼이 될 수 있으며, 효과 역시 동일하지만 접두 키의 용도에 대한 설명으로 사용 가능한 접두 키에 대해 명령어 이름을 제공한다. 따라서 C-x 의 바인딩은 C-x 명령어에 대한 키맵을 함수 정의로 가진

Control-X-prefix

심볼이다. 접두 키로서 C-c, C-x, C-h, ESC 의 정의는 전역적 맵에 나타나므로 이러한 접두 키는 언제든 이용 가능하다.


일반 접두 키 외에도 메뉴 바를 표시하는 가상의 "접두 키(prefix key)"도 있는데, 메뉴 바 키 바인딩에 관한 특별한 정보는 The Emacs Lisp Reference Manual 의 "Menu Bar"절을 참고한다. 팝업 메뉴를 호출하는 마우스 버튼 이벤트 역시 접두 키이며, 상세한 내용은 The Emacs Lisp Reference Manual 의 "Menu Keymaps"절을 참고한다.


일부 접두 키맵은 이름을 이용해 변수에 보관된다.

  • ctl-x-map
    C-x 뒤에 따라오는 문자에 사용되는 맵에 대한 변수명이다.
  • help-map
    C-h 뒤에 따라오는 문자에 적용된다.
  • esc-map
    ESC 뒤에 따라오는 문자에 적용된다. 따라서 모든 Meta 문자는 사실상 이 맵이 정의한다.
  • ctl-x-4-map
    C-x 4 뒤에 따라오는 문자에 적용된다.
  • mode-specific-map
    C-c 뒤에 따라오는 문자에 적용된다.


로컬 키맵(Local Keymaps)

지금까지 전역적 맵에 관해 상세히 설명해왔다. 주 모드는 로컬 키맵(local keymaps)에서 고유의 키 바인딩을 제공함으로써 Emacs를 맞춤화한다. 가령 C 모드는 TAB 을 오버라이드하여 C 모드에 대한 현재 라인을 들여쓰도록 만든다. 부 모드 역시 로컬 키맵을 가질 수 있어서 부 모드가 켜질 때마다 그 키맵에 위치한 정의는 주 모드의 로컬 키맵과 전역적 키맵을 모두 오버라이드한다. 또한 버퍼 내 텍스트 부분들은 다른 모든 키맵을 오버라이드하는 고유의 키맵을 명시할 수 있다.


로컬 키맵은 키를 접두 키맵으로서 재정의할 수 있다. 키가 이미 전역적으로 접두어로서 정의된 경우 그 로컬 정의와 전역적 정의(두 키맵 모두)가 효과적으로 결합되어, 접두 키를 따르는 이벤트를 검색하는 데에 두 가지 정의 모두 사용된다. 가령 로컬 키맵이 C-c 를 접두 키맵으로 정의하고, 해당 키맵은 C-z 를 명령어로 정의하는 경우, 이는 C-c C-z 에 대한 로컬 의미를 제공한다. 그렇다고 해서 C-c 로 시작하는 다른 시퀀스에 영향을 미치는 것은 아니며, 그러한 시퀀스들이 고유의 로컬 바인딩을 갖고 있지 않을 경우 전역적 바인딩이 사용된다.


이를 이해하는 또 다른 방법으로, 전체 키 시퀀스로 된 바인딩의 경우 Emacs는 여러 키맵을 검색함으로써 다중 이벤트 키 시퀀스를 처리한다는 사실을 들 수 있다. 먼저 Emacs 는 부 모드 키맵에서 켜져 있는 부모드를 확인하고, 주 모드의 키맵을 확인한 후 전역적 키맵을 확인한다. 키 검색이 정확히 이러한 방식으로 작동하지는 않지만 일반적 상황에서 결과를 이해하기엔 충분하다.


미니버퍼 키맵(Minibuffer Keymaps)

미니버퍼에는 고유의 로컬 키맵 집합이 있어서 다양한 완성 및 종료 명령어를 포함한다.

  • minibuffer-local-map
    은 일반 입력에 사용된다(완성을 이용하지 않음).
  • minibuffer-local-ns-map
    은 위와 유사하나 SPC 를 사용 시 RET 를 사용하는 것과 동일하다는 점에서 차이가 있다.
  • minibuffer-local-completion-map
    은 관대한(permissive) 완성에 사용된다.
  • minibuffer-local-must-match-map
    은 엄격한 완성과 주의적(cautious) 완성에 사용된다.
  • minibuffer-local-filename-completion-map
    minibuffer-local-filename-must-match-map 은 앞의 두 명령어와 같지만 파일명 완성에 구체적으로 사용된다. SPC 를 바인딩하지 않는다.


키 바인딩을 대화형으로 변경하기(Changing Key Bindings Interactively)

Emacs 키를 재정의하는 방법은 그 엔트리를 키맵에서 변경하는 것이다. 전역적 키맵을 변경할 수도 있지만 이런 경우 모든 주 모드에 변경내용이 적용된다(동일한 이름으로 된 고유의 오버라이딩 로컬 바인딩을 가진 주 모드는 제외). 아니면 동일한 주 모드를 사용하는 버퍼 모두에 영향을 미치는 로컬 키맵을 변경하는 방법도 있다.


이번 절에서는 현재 Emacs 세션에 사용할 키를 재바인딩하는 방법을 설명하겠다. 향후 Emacs 세션에 영향을 미치도록 키 바인딩을 만드는 방법은 432 페이지의 33.3.6절 [Init 재바인딩(Init Rebinding)]을 참고한다.


M-x global-set-key RET key cmd RET

cmd 를 실행하도록 key 를 전역적으로 정의한다.


M-x local-set-key RET key cmd RET

cmd 를 실행하도록 key 를 (현재 켜진 주 모드에서) 로컬로 정의한다.


M-x global-unset-key RET key

전역 맵에 key 를 정의되지 않은 상태로 만든다.


M-x local-unset-key RET key

(현재 켜진 주 모드에서) key 를 로컬로 정의되지 않은 상태로 만든다.


예를 들어 아래의 경우 C-z

shell

명령어로 바인딩하여 (384 페이지의 31.4.2절 [대화형 셸(Interactive Shell)] 참고) C-z 의 일반 전역적 정의를 대체한다:


M-x global-set-key RET C-z shell RET


global-set-key

명령어는 키 다음에 명령어 이름을 읽는다. 키를 누르고 나면 이와 같은 메시지가 나타나므로 원하는 키를 바인딩하고 있는지 확인할 수 있다:


Set key C-z to command:


기능키와 마우스 이벤트도 동일한 방법으로 재정의가 가능하므로 재바인딩할 키를 명시할 시간이 되면 기능키를 입력하거나 마우스를 클릭한다.


하나 이상의 이벤트를 포함하는 키도 똑같은 방식으로 재정의할 수 있다. Emacs 는 완전 키(접두 키가 아닌)가 될 때까지 재바인딩할 키를 계속 읽는다. 따라서 key 에 대해 C-f 를 입력하기만 하면 cmd 를 읽기 위해 미니버퍼로 즉시 들어간다. 하지만 접두어 C-x 를 입력하면 다른 문자를 읽으므로 또 다른 접두 문자인

4

일 경우 문자 하나를 더 읽게 된다. 아래를 예로 들어보면,


M-x global-set-key RET C-x 4 $ spell-other-window RET


spell-other-window

라는 (가상의) 명령어를 실행하도록 C-x 4 $ 를 재정의한다.


global-unset-key

를 이용하면 키의 전역적 정의를 제거할 수 있다. 이것은 키를 정의되지 않은 상태(undefined)로 만들기 때문에 사용자가 키를 입력하면 Emacs 는 삐 소리를 낼뿐이다. 이와 비슷하게

local-unset-key

는 현재 주 모드 키맵에서 키를 정의되지 않은 상태로 만들어 전역적 정의(혹은 하나가 결여된)가 해당 주 모드에서 다시 효력을 발휘한다.


키를 재정의(또는 정의 취소)하였다가 곧바로 변경을 취소하고 싶을 때 키를 정의 취소한다고 해서 해결되는 것이 아니라 키를 표준 정의로 재정의해야만 한다. 키의 표준 정의 이름을 찾기 위해서는 새로 Emacs 를 시작하여 Fundamental 모드 버퍼로 가서 C-h c 를 이용한다. 본 매뉴얼의 키에 관한 문서를 참고하면 그러한 명령어 이름 목록을 확인할 수 있다.


실수로 명령어를 실행하는 일이 없도록 하려면 키를 재정의하기보다 명령어를 끄는 편이 낫다. 정말로 원한다면 명령어를 끄는 편이 덜 번거롭다. 관련 내용은 437 페이지의 33.3.11절 [비활성화하기(Disabling)]를 참고한다.


Init 파일에서 키 재바인딩하기(Rebinding Keys in Your Init File)

항상 사용하고 싶은 키 바인딩 집합이 있으면 Lisp 코드를 작성하여 초기화 파일에서 그러한 집합을 명시하면 된다. 초기화 파일에 관한 설명은 437 페이지의 33.4절 [Init 파일(Init File)]을 참고한다.


Lisp 를 이용해 키 바인딩을 쓰는 방법에는 여러 가지가 있다. 가장 단순한 방법은 본 매뉴얼에서 키 시퀀스를 쓰는 방법과 비슷하게 키 시퀀스의 텍스트 표현을

global-set-key

에 인자로 전달 가능한 형태로 변환하는

kbd

함수를 사용하는 방법이다. 가령 C-z

shell

명령어로 바인딩하는 방법을 소개하겠다(384 페이지의 31.4.2절 [대화형 셸(Interactive Shell)]을 참고한다:

(global-set-key (kbd "C-z") 'shell)


명령어 이름

shell

앞에 작은 따옴표는 명령어 이름을 변수가 아니라 상수 심볼로 마크한다. 이 따옴표를 생략하면 Emacs 는

shell

을 변수로서 평가한다. 이는 오류를 발생시키므로 원하지 않을 것이다.


기능키와 마우스 이벤트의 바인딩을 포함해 몇 가지 예를 더 들어보겠다:

(global-set-key	(kbd "C-c y") 'clipboard-yank)
(global-set-key	(kbd "C-M-q") 'query-replace)
(global-set-key	(kbd "<f5>") 'flyspell-mode)
(global-set-key	(kbd "C-<f5>") 'linum-mode)
(global-set-key	(kbd "C-<right>") 'forward-sentence)
(global-set-key	(kbd "<mouse-2>") 'mouse-save-then-kill)


kbd

를 사용하는 대신 Lisp 문자열이나 벡터(vector)를 이용해 키 시퀀스를 명시할 수도 있다. 문자열을 이용하면 더 단순해지지만 ASCII 문자와 Meta-modified ASCII 문자에만 효과가 있다. 예를 들면 C-x M-1

make-symbolic-link

로 바인딩하는 방법은 다음과 같다(140 페이지의 15.10절 [다양한 파일 연산(Misc File Ops)]을 참고한다:

(global-set-key "\C-x\M-l" 'make-symbolic-link)


TAB, RET, ESC, 또는 DEL 을 문자열에 넣으려면 각각 Emacs Lisp escape 시퀀스 '

\t

', '

\r

', '

\e

', 또는 '

\d

' 를 사용하라. C-x TAB

indent-rigidly

로 바인딩하는 예는 다음과 같다(205 페이지의 21장 [들여쓰기(Indentation)] 참고):

(global-set-key "\C-x\t" 'indent-rigidly)


키 시퀀스가 기능키나 마우스 버튼 이벤트, 또는 C-=H-a 와 같은 non-ASCII 문자를 포함하면 벡터를 이용해 키 시퀀스를 명시할 수 있다. 벡터 내 각 요소(element)는 입력 이벤트를 의미하며, 요소는 공백으로 구분되어 한 쌍의 사각 괄호 안에 위치한다. 벡터 요소가 문자일 경우 Lisp 문자 상수로 써라: 문자열에서 표시되듯 '

?

' 다음에 문자가 따라올 것이다. 기능키는 심볼로 표현되는데(433 페이지의 33.3.8절 [기능키(Function Keys)] 참고), 구분 문자나 구두점 없이 단순히 심볼 이름만 쓰도록 한다. 몇 가지 예를 소개하겠다:

(global-set-key	[?\C-=] 'make-symbolic-link)
(global-set-key	[?\M-\C-=] 'make-symbolic-link)
(global-set-key	[?\H-a] 'make-symbolic-link)
(global-set-key	[f7] 'make-symbolic-link) 
(global-set-key [C-mouse-1] 'make-symbolic-link)


간단한 경우에도 벡터를 사용할 수 있다:

(global-set-key [?\C-z ?\M-l] 'make-symbolic-link)


언어 및 코딩 시스템은 non-ASCII 문자에 대한 키 바인딩 시 문제를 야기할 수도 있다. 관련 내용은 442 페이지의 33.4.5절 [Init Non-ASCII]를 참고한다.


430 페이지의 33.3.3절 [로컬 키맵(Local Keymaps)]에 설명한 바와 같이 주 모드와 부 모드는 로컬 키맵을 정의할 수 있다. 이러한 키맵은 세션에서 모드가 처음으로 사용될 때 구성된다. 이러한 키맵 중 하나를 변경하길 원한다면 모드 훅(mode hook)을 사용해야 한다(422 페이지의 33.2.2절 [훅(Hooks)]을 참고한다.


가령 Texinfo 모드는

texinfo-mode-hook

훅을 실행한다. 훅을 이용하여 Texinfo 모드에서 C-c nC-c p 에 대한 로컬 바인딩을 추가하는 방법은 다음과 같다:

(add-hook 'texinfo-mode-hook 
          (lambda ()
            (define-key texinfo-mode-map "\C-cp"
                        'backward-paragraph) 
            (define-key texinfo-mode-map "\C-cn" 
                        'forward-paragraph)))


수식키(Modifier Keys)

Emacs 에서 기본 키 바인딩은 수정된 알파벳 문자가 대, 소문자에 민감하지 않도록 설정된다. 다시 말해 C-AC-a 와 동일한 일을 수행하고, M-AM-a 와 동일한 일을 수행한다. 이는 알파벳 문자에만 해당하며, 다른 키의 "시프팅된(shifted)" 버전에는 적용되지 않으므로 C-@C-2 와 동일하지 않다.


Control

-modified 알파벳 문자는 항상 대, 소문자에 민감하지 않은 것으로 간주되어 Emacs 는 C-A 를 항상 C-a 로, C-BC-b 로 취급한다. 오랜 세월 이런 방식으로 사용되었기 때문이다.


그 외 모든 수식키는 Emacs를 맞춤화할 때 수정된 알파벳 문자를 대, 소문자에 민감하게 만들면 된다. 가령 M-aM-A 가 다른 명령어를 실행하도록 만들 수 있겠다.


공통으로 사용되는 키는 ControlMETA 수식키밖에 없지만 Emacs 는 세 가지 수식키를 추가로 지원한다. 이러한 키를 Super, Hyper, Alt 라고 부른다. 이 수식키의 사용 방법을 제공하는 터미널은 거의 없으며, 대부분 키보드에서 Alt 로 표시된 키는 Alt 가 아니라 META 수식키(modifier)를 발생시킨다(issue). Emacs에서 표준 키 바인딩은 이러한 수식키를 이용한 어떤 문자도 포함하지 않는다. 하지만 사용자가 그에 의미를 할당하도록 Emacs 를 맞춤화할 수는 있다. 수식키 비트(modifier bits)에는 각각 '

s-

', '

H-

', '

A-

'로 라벨이 붙는다.


키보드에 추가 수식키가 없다 하더라도 C-x C-x @ h 를 이용해 입력하면 다음 문자에 "hyper" 플래그가 추가되고, C-x @ s 를 이용하면 "super" 플래그를, C-x @ a 는 "alt" 플래그를 추가한다. 예를 들어 C-x @ h C-a

Hyper-Control-a

를 입력하는 한 방법이다. (아쉽게도 동일한 문자에 C-x @ 를 두 번 사용하여 두 개의 수식키를 추가하는 방법은 효과가 없는데, 첫 번째 사용 시 C-x 에만 적용되기 때문이다.)


기능키 재바인딩하기(Rebinding Function Keys)

키 시퀀스는 일반 문자는 물론이고 기능키를 포함할 수 있다. Lisp 문자(사실상 정수)가 키보드 문자를 표현하는 것처럼 Lisp 심볼은 기능키를 나타낸다. 기능키의 라벨이 단어인 경우 그에 해당하는 Lisp 심볼의 이름에도 그 단어가 사용된다. 공통된 기능키에 사용되는 일반적인 Lisp 이름은 다음과 같다:


LEFT

,

UP

,

RIGHT

,

DOWN
커서 화살표 키.


Begin

,

End

,

Home

,

next

,

prior
다른 커서 위치조정(repositioning) 키.


select

,

print

,

execute

,

backtab

,

insert

,

undo

,

redo

,

clearline

,

insertline

,

deleteline

,

insertchar

,

deletechar
다양한 기능키.


f1

,

f2

, ...

f35
숫자로 매겨진 기능키(키보드 상단에 걸쳐).


kp-add

,

kp-subtract

,

kp-multiply

,

kp-divide

,

kp-backtab

,

kp-space

,

kp-tab

,

kp-enter

,

kp-separator

,

kp-decimal

,

kp-equal
이름이나 구두점이 있는 키패드 키(일반 키보드의 우측으로).


kp-0

,

kp-1

, ...

kp-9
숫자가 있는 키패드 키.


kp-f1

,

kp-f2

,

kp-f3

,

kp-f4
키패드 PF 키.


이는 전형적인 이름들이지만 일부 시스템에서는 (특히 X 를 사용하는 시스템) 다른 이름을 사용할 수도 있다. 자신의 터미널에 주어진 기능키에 어떤 심볼이 사용되도록 확보하기 위해서는 C-h c 를 입력한 다음 해당 키를 눌러라.


기능키의 바인딩 예제는 432 페이지의 33.3.6절 [Init 재바인딩(Init Rebinding)]을 참고한다.


대다수 키보드에는 우측에 "숫자 키패드(numeric keypad)"가 있다. 키패드의 숫자 키는 커서 움직임 키를 두 배로 높이고(double up), 'Num Lock'이라는 라벨이 붙여진 키를 이용해 기능이 토글된다. 기본적으로 Emacs는 이러한 키를 메인 키보드에 상응하는 키로 해석한다. 가령 'Num Lock' 이 켜져 있으면 숫자 키패드의 '8' 키는 kp-8 을 생성하여 8로 해석되는데, 'Num Lock'이 꺼져 있으면 동일한 키를 사용 시 kp-up 를 생성하여 UP 로 해석된다. 8 이나 UP 과 같은 키를 재바인딩할 경우 그와 동일한 키패드 키에도 영향을 미친다. 하지만 '

kp-

' 키를 직접 재바인딩하면 비 키패드(non-keypad)에 해당하는 부분에는 영향을 미치지 않는다. 수정된(modified) 키는 해석되지 않음을 명심해야 하는데, 가령 META 키를 누르면서 숫자 키패드의 '8' 키를 누르면 M-kp-8 을 생성할 것이다.


Emacs 는

keypad-setup

,

keypad-numlock-setup

,

keypad-shifted-setup

,

keypad-numlock-shifted-setup

변수들을 이용해 숫자 키패드 키를 편리하게 바인딩하는 방법을 제공한다. 이러한 키들은 '

keyboard

' 맞춤화 그룹에서 찾을 수 있다(412 페이지의 33.1절 [쉬운 맞춤화(Easy Customization)] 참고). 이러한 키가 수치적 접두 인자를 발행(issue)하는 등의 다른 작업을 수행하도록 재바인딩하는 것도 가능하다.


명명된 ASCII 제어 문자(Named ASCII Control Characters)

TAB, RET, BS, LFD, ESC, DEL 은 특정 ASCII 제어 문자에 대한 이름으로 시작되어 자주 사용되자 고유의 특수 키를 갖게 되었다. 가령 TABC-i 의 또 다른 이름이다. 이후 사용자들은 Emacs 에서 이러한 키들을 Ctrl 키로 입력하는 "동일한" 제어 문자로부터 구별하는 것이 편리함을 깨달았다. 따라서 대부분의 최신 터미널 시스템에서는 더 이상 동일하지 않으므로 TABC-i 와 다르다.


이러한 두 가지 유형의 입력값을 키보드가 구별할 수 있다면 Emacs 도 구별할 수 있다. Emacs 는 "특수" 키를

tab

,

return

,

backspace

,

linefeed

,

escape

,

delete

로 명명된 기능키로 취급한다. 이러한 기능키들은 고유의 바인딩을 갖고 있지 않은 경우 그에 상응하는 ASCII 문자로 자동 해석된다. 그 결과 사용자와 Lisp 프로그램은 그러한 차이가 중요하지 않은 한 신경 쓰지 않아도 된다.


(예를 들어) TABC-i 를 구분하지 않길 원한다면 ASCII 문자 TAB에 (8진 코드 011) 하나의 바인딩만 만들어라. 단, 둘을 구별하려면 ASCII 문자에 하나의 바인딩을 만들고 "기능키" TAB 에 또 하나의 바인딩을 만들라.


일반 ASCII 터미널을 사용할 경우 TABC-i(같은 관계의 다른 쌍들도 마찬가지로)를 구별할 방법이 없는데, 터미널에서 두 가지 경우에서 동일한 문자를 전송하기 때문이다.


마우스 버튼 재바인딩하기(Rebinding Mouse Buttons)

Emacs 는 마우스 버튼을 지정하기 위해 Lisp 심볼을 사용하기도 한다. Emacs 에서 일반 마우스 이벤트는 클릭(click) 이벤트로, 사용자가 버튼을 눌렀다가 마우스를 이동하지 않고 해제할 때 발생한다. 버튼을 누른 상태에서 마우스를 이동하면 드래그(drag) 이벤트를 얻을 수도 있다. 드래그 이벤트는 버튼을 최종적으로 놓을 때 발생한다.


기본 클릭 이벤트에 대한 심볼은 제일 왼쪽 버튼의 경우 mouse-1, 다음 버튼에 mouse-2 식으로 되어 있다. 현재 창을 나누기 위해 두 번째 마우스 버튼을 재정의하는 방법은 아래와 같다:

(global-set-key [mouse-2] 'split-window-below)


드래그 이벤트에 대한 심볼도 이와 비슷하지만 '

mouse

' 라는 단어 앞에 '

drag-

' 라는 접두어가 붙는다. 가령 첫 번째 버튼을 드래그하면 drag-mouse-1 이벤트가 생성된다.


마우스를 누르고 있는 동안 발생하는 이벤트에 대한 바인딩을 정의할 수도 있다. 이러한 이벤트는 '

drag-

' 가 아니라 '

down-

' 으로 시작한다. 그러한 이벤트들은 키 바인딩을 갖고 있을 때에만 생성된다. 버튼다운 이벤트를 얻으면 그에 해당하는 클릭이나 마우스 이벤트가 항상 따를 것이다.


원한다면 한 번, 두 번, 세 번 클릭을 구별할 수도 있다. 두 번 클릭은 대략 동일한 위치에서 마우스 버튼을 두 번 클릭함을 의미한다. 첫 번째 클릭은 일반 클릭 이벤트를 발생시킨다. 그리고 머지않아 두 번째 클릭을 실행하면 더블 클릭(double-click) 이벤트를 발생시킨다. 더블 클릭에 대한 이벤트 타입은 '

double-

' 로 시작되어 double-mouse-3 와 같은 형태를 띤다.


이는 동일한 위치에서 실행되는 두 번째 클릭에 특별한 의미를 부여할 수 있다는 의미지만, 일반적인 한 번 클릭 정의가 첫 번째 클릭이 수신될 때 실행되었다는 가정에서 행동해야 한다.


이는 더블 클릭으로 실행할 수 있는 행동을 제약하지만 사용자 인터페이스 디자이너들은 어떤 경우에서든 이러한 제약이 따라야 한다고 말한다. 더블 클릭은 한 번 클릭과 비슷한 동작을 "좀 더" 많이 취해야 한다. 더블 클릭 이벤트에 대한 명령어는 더블 클릭에 대해 추가 작업을 실행해야 한다.


더블 클릭 이벤트에 바인딩이 없을 경우 그에 상응하는 단일 클릭 이벤트로 변경된다. 따라서 특정 더블 클릭을 특별하게 정의하지 않으면 단일 클릭(single-click) 명령어를 두 번 실행하는 데 그친다.


Emacs 는 '

triple-

' 로 시작하는 이름을 가진 세 번 클릭(triple-click) 이벤트도 지원한다. Emacs는 네 번 클릭은 이벤트 타입으로 구별하지 않으며, 세 번을 넘게 클릭 시 세 번 클릭 이벤트를 추가로 발생시킨다. 하지만 전체 클릭 수는 이벤트 목록에 기록되므로 Emacs Lisp 를 이해하는 사람이라면 원하는 바를 구별할 수 있을 것이다(The Emacs Lisp Reference Manual 의 "Click Events"절 참고). 세 번을 초과하는 클릭에 대해 별도의 의미를 부여하는 것은 권장하지 않지만 가끔은 세 가지 의미로 구성된 동일한 집합을 순환하도록 사용되어 네 번 클릭은 한 번 클릭, 다섯 번 클릭은 두 번 클릭, 여섯 번 클릭은 세 번 클릭과 동일하게 취급하는 것이 유용하다.


Emacs 는 드래그와 버튼다운(button-down) 이벤트에서 여러 번 누름(multiple presses)을 기록하기도 한다. 가령 버튼을 두 번 누른 채로 마우스를 이동시키면 Emacs 는 '

double-drag-

' 이벤트를 얻는다. 그리고 두 번째로 그것을 누르는 순간 Emacs는 '

double-down-

' 이벤트를 얻는다(바인딩이 없을 경우 여느 버튼다운 이벤트와 마찬가지로 무시된다).


double-click-time

변수는 클릭들 간 얼마의 시간이 흘러야 다중 클릭으로 그룹화를 허용할 것인지 명시한다. 그 값은 밀리초 단위로 되어 있다. 값이

nil

이면 더블 클릭이 전혀 감지되지 않는다. 값이

t

일 경우 시간 제한이 없다. 기본값은 500이다.


double-click-fuzz

변수는 클릭들 간 마우스가 얼마나 이동해야 다중 클릭으로 그룹화를 허용할 것인지 명시한다. 그 값은 windowed 디스플레이 시스템에서는 픽셀 단위로, 텍스트 모드(text-mode) 터미널 시스템에서는 문자 셀의 1/8 단위로 표시되며 기본값은 3이다.


마우스 이벤트에 대한 심볼은 수식키의 상태를 나타내기도 하며 '

C-

', '

M-

', '

H-

', '

s-

', '

A-

', '

S-

' 를 일반적인 접두어로 한다. 이들은 항상 '

double-

' 이나 '

triple-

' 보다 우선시되고, '

double-

' 과 '

triple-

' 은 항상 '

drag-

' 나 '

down-

' 보다 우선시된다.


프레임은 모드 라인과 스크롤 바와 같이 버퍼의 텍스트를 표시하지 않는 영역을 포함한다. 더미(dummy) "접두 키"를 이용하면 마우스 버튼이 화면의 특수 영역에서 비롯된 것인지 알 수 있다. 가령 모드 라인에서 마우스를 클릭하면 일반 마우스버튼 심볼 이전에

mode-line

접두 키를 얻게 된다. 따라서

scroll-up-command

를 실행하기 위해 모드 라인의 첫 번째 버튼을 클릭하도록 명령어를 정의하는 방법은 다음과 같다:

(global-set-key [mode-line mouse-1] 'scroll-up-command)


그리고 이러한 더미 접두 키와 그 의미에 대한 전체 목록은 다음과 같다:


mode-line

마우스가 창의 모드 라인에 위치하였다.


vertical-line

마우스가 나란히 위치한 창을 구분하는 수직선에 위치하였다. (스크롤 바를 사용하면 이러한 수직선 대신 표시된다.)


vertical-scroll-bar

마우스가 세로 스크롤 바에 위치하였다. (Emacs가 현재 지원하는 유일한 유형의 스크롤 바에 해당한다.)


menu-bar

마우스가 메뉴 바에 위치하였다.


header-line

마우스가 헤더 라인에 위치하였다.


키 시퀀스에 하나 이상의 마우스 버튼을 놓을 수 있지만 보통은 그렇게 하지 않는다.


명령어 끄기(Disabling Commands)

명령어를 끈다는(disabling) 것은 대화형으로 호출하여 사용자의 확인을 요청함을 의미한다. 명령어를 끄는 것은 사용자가 실수로 명령어를 실행하는 일을 막기 위함으로 초보자들이 혼동할 수 있는 명령어에 대해 기능을 실행한다.


꺼진 명령어를 Emacs에서 대화형으로 호출하면 명령어 이름, 문서, 즉시 무엇을 실행할지에 대한 지시사항을 포함한 창을 표시한 후 요청대로 명령어를 실행할 것인지, 명령어를 켜고 실행할 것인지, 혹은 취소할 것인지를 알리는 입력값을 요청할 것이다. 명령어를 켜기로 결정하면 영구적으로 켤 것인지 아니면 현재 세션에서만 켤 것인지에 대한 질문에도 응답해야 한다. (영구적으로 켜는 기능은 초기화 파일을 자동으로 편집하여 이루어진다.) 현재 세션에서만 모든(all) 명령어를 활성화하려면 !를 입력하면 된다.


명령어를 끄는 직접적 메커니즘은 명령어에 대해 Lisp 심볼에

nil

값이 아닌

disabled

프로퍼티를 주는 것이다. 여기에 사용하는 Lisp 프로그램은 다음과 같다:

(put 'delete-region 'disabled t)


disabled

프로퍼티 값이 문자열일 경우 명령어가 사용될 때 표시되는 메시지에 그 문자열이 포함된다:

(put 'delete-region 'disabled
     "It's better to use 'kill-region' instead.\n")


초기화 파일을 직접 편집하거나 초기화 파일을 사용자 대신 편집해주는 M-x disable-command 명령어를 이용하면 명령어를 끌 수 있다. 마찬가지로 M-x enable-command 를 이용해 명령어를 영구적으로 켜도록 초기화 파일을 편집할 수도 있다. 437 페이지의 33.4절 [Init 파일(Init File)]을 참고한다.


-q

또는

--no-init-file

옵션을 이용해 Emacs를 호출한 경우 (480 페이지의 C.2절 [초기 옵션(Initial Options)] 참고) 초기화 파일을 편집하지 않을 것이다. Emacs 가 초기화 파일을 읽지 않았으므로 편집할 경우 정보를 손실할 수 있다.


명령어가 꺼졌는지 여부는 어떤 키를 이용해 명령어가 호출되었는지와는 무관하며, M-x 를 이용해 명령어를 호출할 경우 끌 때도 적용된다. 하지만 명령어를 끈다고 해서 Lisp 프로그램으로부터 그것을 함수로서 호출하는 데에 영향을 미치지는 않는다.


Emacs 초기화 파일(The Emacs Initialization File)

Emacs가 시작되면 보통 초기화 파일(initialization file) 또는 줄여서 init 파일(init file)에서 Lisp 프로그램의 로딩을 시도한다. 이 파일이 존재할 경우 Emacs를 어떻게 초기화할 것인지를 명시한다. Emacs 가

~/.emacs

,

~/.emacs.el

, 또는

~/.emacs.d/init.el

라는 파일명을 이용해 init 파일을 검색하는데, 사용자는 이 중에서 원하는 이름을 선택할 수 있다(442 페이지의 33.4.4절 [Init 찾기(Find Init)] 참고). 여기서

~/

는 홈 디렉터리를 의미한다.


Init 파일의 로딩을 막기 위해서는 '

-q

' 명령 행 스위치를, 다른 사용자의 init 파일을 명시하기 위해서는 '

-u

'(또는 '

--user

') 를 사용한다(480 페이지의 C.2절 [초기 옵션(Initial Options)] 참고).


라이브러리의 표준 검색 경로를 통해 발견되는

default.el

이라는 라이브러리인 기본 init 파일(default init file)도 존재할 수 있다. Emacs 배포판에는 그러한 라이브러리가 포함되어 있지 않으므로 사이트에서 로컬 맞춤화(local customization)를 위해 하나 생성할 수도 있을 것이다. 이러한 라이브러리가 존재할 경우 사용자가 Emacs 를 시작할 때마다 로딩된다(단, 사용자가 '

-q

' 를 명시하였을 때는 제외다). 하지만 사용자의 init 파일이 있다면 그 파일이 먼저 로딩되는데, 단

inhibit-default-init

nil

이 아닌 값이어야만

default

가 로딩되지 않는다.


사이트에 site startup file 이 포함된 경우도 있는데, 존재할 경우

site-start.el

로 명명되어 있을 것이다.

default.el

와 마찬가지로 Emacs 는 Lisp 라이브러리에 대한 표준 검색 경로를 통해 이 파일을 검색한다. Emacs 는 사용자의 init 파일을 로딩하기 전에 이 라이브러리를 로딩한다. 이 라이브러리의 로딩을 막기 위해서는 '

--no-site-file

' 옵션을 사용하라. 480 페이지의 C.2절 [초기 옵션(Initial Options)]을 참고한다.

site-start.el

을 사용 시 변경되는 사항은 일부 사용자가 탐탁지 않아할 것으로 판단되므로 사용을 권장하지 않는다. 사용자가 좀 더 쉽게 오버라이드할 수 있도록

default.el

에 넣는 편이 낫다.


Emacs 가 Lisp 라이브러리를 검색하는 디렉터리라면 어디든

default.el

site-start.el

을 위치시킬 수 있다.

load-path

변수는 (276 페이지의 24.8절 [Lisp 라이브러리(Lisp Libraries)] 참고) 이러한 디렉터리를 명시한다. 많은 사이트에서 이 파일들을 Emacs 설치 디렉터리 내에

site-lisp

라는 하위디렉터리(예:

/usr/local/share/emacs/site-lisp

) 에 넣어둔다.


Init 파일의 바이트 컴파일(byte-compiling)은 권장하지 않는다(Emacs Lisp Reference Manual 의 "Byte Compilation"절 참고). 이는 시작 속도를 높이지 못할뿐더러 사용자가 파일의 재컴파일을 잊어버리면 문제를 야기하곤 한다. 따라서 사용자가 Emacs를 시작해야 하는 횟수를 줄이기 위해 Eamcs 서버를 사용하는 방법이 더 낫다(393 페이지의 31.5절 [Emacs 서버(Emacs Server)] 참고). 사용자의 init 파일이 다수의 함수를 정의할 경우 해당 init 파일에서 사용자가 로딩하는 (바이트 컴파일된) 별도의 파일로 이동시키는 방도를 고려하라.


약간의 맞춤화가 아니라 Emacs Lisp 프로그램 자체를 쓸 생각이라면 Emacs Lisp Reference Manual 을 정독해야 한다.


Init 파일 구문(Init File Syntax)

Init 파일은 하나 또는 이상의 Lisp 표현식을 포함한다. 이러한 파일은 각각 함수명 뒤에 인자로 구성되는데, 모두 괄호에 포함되어 있다. 예를 들어

(setq fill-column 60)

setq

함수를 호출하여

fill-column

변수를 60 으로 설정한다(212 페이지의 22.5절 [채우기(Filling)] 참고).


setq

를 이용하면 어떠한 Lisp 변수든 설정 가능하지만 특정 변수에서는

setq

만으로

.emacs

파일에서 원하는 결과를 얻을 수 없을 것이다. 일부 변수는

setq

로 설정하면 자동으로 버퍼 로컬이 되는데, 사용자는

.emacs

에서

setq-default

를 이용한 기본값 설정을 원할 것이다. 일부 맞춤화 가능한 부 모드 변수들은 Customize 로 설정 시 모드를 활성화하기 위해 특별한 일을 수행하지만 일반적인

setq

는 그렇지 않으므로

.emacs

파일에서 모드를 활성화하려면 부 모드 명령어를 호출해야 한다. 다음 절에서는 이 두 가지 방법의 예를 제시하겠다.


setq

로 주어지는 두 번째 인자는 변수의 새 값에 대한 표현식이다. 그 값은 상수, 변수, 또는 함수 호출 표현식이 될 수 있다.

.emacs

에서는 상수가 사용되는 것이 보통이다. 가능한 값은 다음과 같다:


Numbers:

10진수 숫자가 쓰이고 처음 마이너스 부호는 선택적이다.


Strings:

Lisp 문자열 구문은 몇 가지 추가 기능이 더해진 C 문자열 구문과 동일하다. 쌍따옴표 문자를 이용해 문자열 상수의 시작과 끝을 알린다.
문자열에서는 개행 문자와 특수 문자를 포함할 수 있다. 하지만 백슬래시 시퀀스를 사용하는 편이 더 깔끔하기도 하다. (개행 문자에 '
\n
', 백스페이스에 '
\b
', 캐리지 리턴에 '
\r
', 탭에 '
\t
', formfeed 에 '
\f
'(control-L), escape에 '
\e
', 백슬래시에 '
\\
', 큰따옴표에 '
\"
', 8진 코드가 ooo인 문자에는 '
\ooo
') 백슬래시와 큰따옴표는 백슬래시 시퀀스를 의무적으로 사용하는 유일한 문자이다.
'
\C-
'는 제어 문자에 대한 접두어(예: ASCII control-S 에 '
\C-s
')로 사용 가능하며, '
\M-
' 은 Meta 문자에 대한 접두어(예:
META-A
에 '
\M-a
' 나
Ctrl-META-A
에 '
\M-\C-a
')로 이용할 수 있다.
Init 파일에 non-ASCII 를 포함하는 것에 관한 정보는 442 페이지의 33.4.5절 [Init Non-ASCII]를 참고한다.


Characters:

Lisp 상수 구문으로, '
?
' 뒤에 문자 또는 '
\
' 로 시작하는 escape 시퀀스로 구성된다. 예로,
?x
,
?\n
,
?\"
,
?\
)를 들 수 있다. 문자열과 문자는 Lisp 에서 동일하게 사용할 순 없으며, 컨텍스트마다 둘 중 하나를 필요로 함을 명심한다.
Non-ASCII 문자를 전송하는 키에 대한 명령어의 바인딩에 관한 정보는 442 페이지의33.4.5절 [Init Non-ASCII]를 참고한다.


True:

t
는 'true'를 나타낸다.


False:

nil
은 'false'를 나타낸다.


기타 Lisp 객체:

작은 따옴표(
'
) 다음에 원하는 Lisp 객체를 써라.


Init File 예제(Init File Examples)

Lisp 표현식을 이용해 자주 실행하는 것들을 예로 보이고자 한다:


  • load-path
    변수로 디렉터리를 추가하라. 그러면 Emacs 에 포함되지 않은 Lisp 라이브러리를 해당 디렉터리로 넣을 수 있고, M-x load-library 를 이용해 로딩할 수 있다. 276 페이지의 24.8절 [Lisp 라이브러리(Lisp Libraries)]를 참고한다.
    (add-to-list 'load-path "/path/to/lisp/libraries")
    
  • 포인트가 라인 중간에 위치할 경우 C 모드에서 TAB 을 이용하면 탭을 삽입하도록 만들어라.
    (setq c-tab-always-indent nil)
    
    'true' 에 보통
    t
    를 값으로 하고 'false' 에는
    nil
    을 값으로 하는 함수를 갖게 된다.
  • 검색은 기본적으로 대, 소문자를 구별하도록 만들어라(이것을 오버라이드하지 않는 모든 버퍼에서).
    (setq-default case-fold-search nil)
    
    이는 변수에 대한 로컬 값을 갖고 있지 않은 모든 버퍼에 효과적인 기본값을 설정한다(423 페이지의 33.2.3절 [로컬(Locals)] 참고).
    case-fold-search
    setq
    로 설정하면 현재 버퍼의 로컬 값에만 영향을 미치기 때문에 init 파일에서는 원하는 결과를 얻기 힘들 것이다.
  • Emacs가 당신의 이메일 주소를 올바로 알아내지 못할 경우 직접 명시하라.
    (setq user-mail-address "cheney@torture.gov")
    
    Message 모드와 같은 다양한 Emacs 패키지에서 당신의 이메일 주소를 알아야 할 때는
    user-mail-address
    로 문의하라. 351 페이지의 29.2절 [메일 헤더(Mail Headers)]를 참고한다.
  • Text 모드를 새 버퍼에 대한 기본 모드로 설정하라.
    (setq-default major-mode 'text-mode)
    
    text-mode
    는 Text 모드로 들어가는 명령어라는 이유로 사용된다. 그 앞에 작은 따옴표를 사용하면 심볼은 상수가 되고, 그 외의 경우
    text-mode
    는 변수명으로 취급될 것이다.
  • Western Europe 언어 대부분을 지원하는 Latin-1 문자 집합에 대해 기본값을 설정한다.
    (set-language-environment "Latin-1")
    
  • 전역적 부 모드인 Line Number 모드를 끈다.
    (line-number-mode 0)
    
  • Text 모드 및 관련 모드에서 Auto Fill모드를 자동으로 켠다(422 페이지의 33.2.2절 [훅(Hooks)] 참고).
    (add-hook 'text-mode-hook 'auto-fill-mode)
    
  • foo라는 이름으로 설치된 Lisp 라이브러리를 로딩한다(표준 Emacs 디렉터리에서는
    foo.elc
    또는
    foo.el
    이란 파일이다).
    (load "foo")
    
    load
    에 대한 인자가 '
    /
    ' 또는 '
    ~
    ' 로 시작하지 않는 상대적 파일명일 경우
    load
    load-path
    에서 디렉터리를 검색한다(276 페이지의 24.8절 [Lisp 라이브러리(Lisp Libraries)] 참고).
  • 홈 디렉터리에서
    foo.elc
    라는 컴파일된 Lisp 파일을 실행하라.
    (load "~/foo.elc")
    
    여기서는 전체 파일명이 사용되므로 어떤 검색도 실행되지 않는다.
  • mypackage
    라는 Lisp 라이브러리를 로딩하여 Emacs 에게
    myfunction
    함수에 대한 정의를 찾으라고 말한다(예:
    mypackage.elc
    또는
    mypackage.el
    파일).
    (autoload 'myfunction "mypackage" "Do what I say." t)
    
    여기서 "
    Do what I say.
    "라는 문자열은 함수의 문서 문자열이다. 이것을
    autoload
    정의에서 명시하면 패키지가 로딩되지 않아도 도움말 명령어에 이용할 수 있게 된다. 마지막 인자
    t
    는 이 함수가 상호작용적임을 나타내므로 M-x myfunction RET 를 입력하거나 키로 바인딩을 하여 상호작용적으로 호출할 수 있다. 함수가 상호작용적이지 않으면
    t
    를 생략하거나
    nil
    값을 사용하라.
  • C-x l 키를
    make-symbolic-link
    함수를 실행하도록 재바인딩하라(432 페이지의 33.3.6절 [Init 재바인딩(Init Rebinding)] 참고).
    (global-set-key "\C-xl" 'make-symbolic-link)
    
    또는
    (define-key global-map "\C-xl" 'make-symbolic-link)
    
    여기서도 작은 따옴표를 이용해 변수의 값이 아니라
    make-symbolic-link
    심볼을 변수로 참조함을 주의한다.
  • Lisp 전용 모드에서도 마찬가지로 실행한다.
    (define-key lisp-mode-map "\C-xl" 'make-symbolic-link)
    
  • 이제 Fundamental 모드에서
    next-line
    을 실행하는 모든 키가
    forward-line
    을 실행하도록 재정의하라.
    (substitute-key-definition 'next-line 'forward-line
                               global-map)
    
  • C-x C-v 를 정의되지 않은 상태로 만들어라.
    (global-unset-key "\C-x\C-v")
    
    키를 정의해제(undefined)하는 한 가지 이유는 접두어로 만들 수 있기 때문이다. 단순히 C-x C-v anything 을 정의하면 C-x C-v 를 접두어로 만들지만 C-x C-v 를 먼저 일반적인 비접두어 정의에서 해제(free)시켜야 한다.
  • '
    $
    ' 를 Text 모드에서 구두점의 구문을 갖게 만들어라. '
    $
    ' 에 대한 문자 상수의 사용을 주의하라.
    (modify-syntax-entry ?\$ "." text-mode-syntax-table)
    
  • 확인을 요청하지 않고
    narrow-to-region
    명령어의 사용을 가능하게 하라.
    (put 'narrow-to-region 'disabled nil)
    
  • 설정을 다양한 플랫폼과 Emacs 버전으로 조정하라.
  • 사용자는 일반적으로 Emacs 가 모든 시스템에서 동일하게 행동하길 원하고, init 파일 역시 모든 플랫폼에서 동일하게 작동하길 원한다. 하지만 Emacs 를 맞춤화하는 데에 사용하는 함수를 일부 플랫폼이나 오래된 Emacs 버전에서는 이용할 수 없는 경우가 발생하곤 한다. 이러한 상황에 대처하기 위해서는 아래와 같이 함수나 기능을 이용할 수 있는지 시험하는 조건문(conditional)에 맞춤화를 넣는다.
    (if (fboundp 'blink-cursor-mode) 
        (blink-cursor-mode 0))
    
    (if (boundp 'coding-category-utf-8)
        (set-coding-priority '(coding-category-utf-8)))
    
    함수가 정의되지 않았다면 발생하는 오류를 단순히 삭제할 수도 있다.
    (condition case ()
        (set-face-background 'region "grey75") 
      (error nil))
    
    존재하지 않는 변수에서
    setq
    를 사용하더라도 일반적으로 해가 되지 않으므로 조건문을 필요로 하지 않는다.


터미널 특정적 초기화(Terminal-specific Initialization)

터미널 타입마다 Emacs를 실행할 때 Emacs로 로딩되어야 하는 Lisp 라이브러리를 가질 수 있다. termtype 이라는 터미널 타입에서는 '

.elc

' 와 '

.el

' 이라는 접두어로

load-path

디렉터리를 검색하면

term/termtype

이라는 라이브러리를 찾을 수 있다. 보통은 대부분의 Emacs 라이브러리가 보관되는 디렉터리의 term 하위디렉터리에 표시된다.


터미널 특정적 라이브러리의 일반적인 용도는

input-decode-map

을 이용해 (또는 그 전에

function-key-map

을 이용해) 터미널의 기능키에 사용되는 escape 시퀀스를 좀 더 의미 있는 이름으로 매핑하기 위함이다. 매핑 방법은

term/lk201.el

파일에서 예를 살펴보도록 한다. 많은 기능키들이 Termcap 데이터 기반으로 된 정보에 따라 자동 매핑되는데, 터미널 특정적 라이브러리는 Termcap 이 명시하지 않는 기능키만 매핑할 필요가 있다.


터미널 타입에 하이픈이 포함되어 있으면 하이픈 앞에 이름 부분이 라이브러리명을 선택하는 데에 중요해진다. 따라서 터미널 타입 '

aaa-48

' 과 '

aaa-30-rv

' 는 모두

term/aaa

라이브러리를 사용한다. 라이브러리 내 코드는

(getenv "TERM")

을 이용해 터미널 타입의 전체 이름을 찾는다.


라이브러리명은

term-file-prefix

변수의 값과 터미널 타입을 결합하여 구성된다. 사용자의

.emacs

파일은

term-file-prefix

nil

로 설정하여 터미널 특정적인 라이브러리가 로딩되는 것을 막을 수 있다.


Emacs 는

.emacs

파일과 터미널 특정적 라이브러리가 읽힌 뒤에 초기화 끝에서

tty-setup-hook

훅을 실행한다. 터미널 특정적 라이브러리의 일부를 오버라이드하고 라이브러리를 갖고 있지 않은 터미널에 대해 초기화를 정의하고 싶다면 이 훅에 훅 함수를 추가하라. 422 페이지의 33.2.2절 [훅(Hooks)]을 참고한다.


Emacs가 Init 파일을 찾는 방법(How Emacs Finds Your Init File)

보통 Emacs 는

HOME

이란 환경 변수를 이용하여 (483 페이지의 C.4.1절 [일반 변수(General Variables)] 참고)

.emacs

를 찾는데, 파일명에 포함된 '

~

' 는 바로 이러한 의미를 지닌다.

~/

에서 (또는

.emacs.el

에서)

.emacs

가 발견되지 않으면 Emacs 는

~/.emacs.d/init.el

(

~/.emacs.el

과 마찬가지로 바이트 컴파일 가능)을 검색한다.


하지만

su

로 시작된 셸로부터 Emacs 를 실행할 경우 Emacs 는 사용자가 현재 흉내 내는 것이 아니라 사용자 고유의

.emacs

를 찾으려 한다. 이는 사용자가 super user 로 실행하더라도 고유의 에디터 맞춤화를 확보하기 위함이다.


좀 더 정확히 말해 Emacs 는 사용할 사용자의 init 파일을 먼저 결정한다. 환경변수

LONGNAME

USER

에서 사용자 이름을 얻는데, 이러한 환경변수가 존재하지 않으면 효과적인 사용자 ID를 사용한다. 해당하는 사용자 이름이 실제 사용자 ID 와 일치하면 Emacs 는

HOME

을 사용하고, 일치하지 않으면 사용자 시스템의 데이터 기반에서 그 사용자 이름에 해당하는 홈 디렉터리를 검색한다.


Init 파일에 포함된 Non-ASCII 문자(Non-ASCII Characters in Init Files)

Init 파일의 문자열이나 키 바인딩에 강세 문자와 같은 non-ASCII 문자가 포함되어 있을 경우 언어와 코딩 시스템은 문제를 야기할 수 있다.


Init 파일에서 non-ASCII 문자를 사용하고 싶다면 init 파일의 첫 라인에 '

-*-coding: coding-system-*-

' 태그를 놓고, 의심이 가는 문자를 지원하는 코딩 시스템을 명시해야 한다. 185 페이지의 19.6절 [코딩 인식하기(Recognize Coding)]를 참고한다. 이러한 문제는 Emacs가 그러한 문자열을 사용하는 init 파일의 부분을 읽을 당시 non-ASCII 텍스트를 디코딩하는 기본값이 설정되지 않아 Emacs 가 문자열을 올바르지 않은 방식으로 디코딩하여 발생된다. 따라서

set-language-environment

의 호출을 비롯해 다른 방식으로 코딩 시스템을 수정하는 Emacs Lisp 코드는 추가해선 안 된다.


Non-ASCII 키를 바인딩하려면 벡터(vector)를 사용해야만 한다(432 페이지의 33.3.6절 [Init 재바인딩(Init Rebinding)] 참고). Non-ASCII 문자는 메타 키로 해석될 것이기 때문에 문자열 구문은 사용해선 안 된다. 아래를 예로 들면,

(global-set-key [?char] 'some-function)


C-q 를 입력한 다음 바인딩하고자 하는 키를 눌려 char 를 삽입한다.


경고: 키보드 인코딩을 변경하거나 다중바이트와 단일바이트 모드를 변경하거나 C-q 가 해당 문자에 대해 삽입할 코드를 변경시킬만한 작업을 수행할 경우, 이 키는 작동을 중단할지도 모른다. 따라서 편집하는 파일을 비롯해 init 파일에는 하나의 코딩 시스템만 사용할 것을 권한다. '

latin-1

' 코딩 시스템과 '

latin-9

' 코딩 시스템을 함께 사용해선 안 되겠다.


Notes

  1. MS-DOS에서는 DOS filesystems의 한계로 인해 이 파일명이
    _dir-locals.el
    로 되어 있을 것이다. Filesystem 이 8+3 파일명으로 제한되어 있다면 파일명은 OS 에 의해
    _dir-loc.el
    로 절단될 것이다.