GNUEmacsManual:26

From 흡혈양파의 번역工房
Jump to navigation Jump to search
약어

약어

정의된 약어(abbrev)는 사용자가 다른 텍스트로 삽입하면 확장되는 단어를 의미한다. 약어는 구체적인 방식으로 확장되도록 사용자에 의해 정의된다. 가령 사용자는 '

foo

' 를 '

find outer otter

' 로 확장되는 축약어로 정의할 수 있다. 그리고

f o o SPC

를 입력하면 '

find outer otter

' 를 버퍼로 삽입할 수 있다.


두 번째 종류의 축약 기능은 동적 약어 확장이라고 불린다. 버퍼에서 포인트 앞 문자를 확장하여 버퍼에서 그러한 글자로 시작하는 다른 단어를 살펴보는 직접적 명령어로 동적 약어 확장을 이용할 수 있다. 313 페이지의 26.6절 [동적 약어]를 참고한다.


"히피(Hippie)" 확장은 약어 확장을 일반화한다. Features for Automatic Typing 의 "Hippie Expansion"절을 참고한다.


약어 개념

약어(abbrev)는 명시된 확장(expansion)으로 확장되도록 정의된 단어이다. 약어 다음에 단어를 구분하는 문자를 삽입하면 약어를 확장하여 약어를 그 확장으로 대체한다. 가령 '

foo

' 가 '

find outer otter

' 로 확장되는 약어로 정의되면

f o o

를 입력 시 '

find outer otter

' 가 삽입될 것이다.


약어는 Abbrev 모드라는 버퍼 로컬 부 모드가 활성화되었을 때에만 확장된다. Abbrev 모드를 비활성화한다고 해서 약어 정의가 잊혀지는 것은 아니지만 Abbrev 모드가 다시 활성화될 때까지는 확장되지 않는다. M-x abbrev-mode 명령어는 Abbrev 모드를 토글하며, 수치적 인자를 이용해 인자가 양수일 경우 Abbrev 모드를 켜고 그 외의 경우 모드를 끈다. 200 페이지의 20.2절 [부 모드]를 참고한다.


약어는 모드 특정적 정의를 가질 수 있고, 이는 하나의 주 모드에서만 활성화된다. 약어는 모든 주 모드에서 활성화되는 전역적 정의를 가질 수도 있다. 동일한 약어는 전역적 정의와 다른 주 모드들에 걸쳐 다양한 모드 특정적 정의를 가질 수 있다. 현재 주 모드에 대한 모드 특정적 정의는 전역적 정의를 오버라이드한다.


Abbrev 모드의 활성화 여부와 상관없이 편집 세션 중에는 약어를 상호작용적으로 정의할 수 있다. 약어 정의 목록을 파일에 저장하여 이후 세션에서 재로딩하여 사용할 수도 있다.


약어 정의하기

C-x a g

포인트 앞에 하나 또는 이상의 단어를 확장으로 이용하여 약어를 정의한다(

add-global-abbrev

).


C-x a l

유사하지만 현재 주 모드에 특정적인 약어를 정의한다(

add-mode-abbrev

).


C-x a i g

버퍼에서 단어를 약어로 정의한다(

inverse-add-global-abbrev

).


C-x a i l

버퍼에서 단어를 모드 특정적인 약어로 정의한다(

inverse-add-mode-abbrev

).


M-x define-global-abbrev RET abbrev RET exp RET

abbrevexp 로 확장되는 약어로서 정의한다.


M-x define-mode-abbrev RET abbrev RET exp RET

abbrevexp 로 확장되는 모드 특정적 약어로서 정의한다.


M-x kill-all-abbrevs

모든 약어 정의를 제거하고 비어둔다(blank slate).


약어를 정의하는 일반적인 방법은 약어를 확장시키려는 텍스트를 입력하고, 그 뒤에 포인트를 위치시킨 후 C-x a g (

add-global-abbrev

)를 입력하는 방법이다. 그러면 미니버퍼를 이용해 약어 자체가 읽힌 후 포인트 앞에 하나 또는 이상의 단어에 대한 약어로서 정의된다. 수치적 인자를 이용해 포인트 앞에 얼마나 많은 단어를 확장으로 취급할 것인지 명시한다. 예를 들어 위에서 언급한 '

foo

' 약어를 정의하려면 '

find outer otter

' 텍스트를 삽입한 다음 C-u 3 C-x a g f o o RET 을 입력한다.


C-x a g 에 대한 인자가 0일 경우 영역의 내용을 정의되는 약어의 확장으로 이용할 것을 의미한다.


C-x a l (

add-mode-abbrev

) 명령어도 비슷하지만 현재 주 모드에 대한 모드 특정적 약어를 정의한다. 인자는 C-x a g 에서와 동일하게 작동한다.


C-x a i g (

inverse-add-global-abbrev

) 와 C-x a i l (

inverse-add-mode-abbrev

)는 상반된 과제를 수행하는데, 약어 텍스트가 이미 버퍼에 있는 경우 이러한 명령어를 이용해 미니버퍼에서 확장을 명시함으로써 약어를 정의한다. 이러한 명령어들은 정의에 사용된 약어 텍스트를 확장시킬 것이다.


define-global-abbrev

명령어를 이용하면 버퍼에서 약어 또는 그 확장을 삽입하지 않고 약어를 정의할 수 있다. 이는 두 개의 인자, 즉 약어와 확장을 읽는다.

define-mode-abbrev

명령어도 마찬가지로 모드 특정적인 약어에 대해 실행된다.


약어의 정의를 변경하려면 그냥 새 정의를 만든다. 약어가 기존 정의를 갖고 있다면 약어 정의 명령어는 새로운 정의로 대체하기 전에 확인을 요청한다.


약어 정의를 제거하려면 약어 정의 명령어에 음의 인자를 제공한다: C-u - C-x a g 또는 C-u - C-x a l. 전자는 전역적 정의를 제거하는 반면 후자는 모드 특정적 정의를 제거한다. M-x kill-all-abbrevs 는 전역 및 로컬을 포함해 모든 약어 정의를 제거한다.


약어 확장 제어하기

Abbrev 모드가 활성화되면 버퍼에서 포인트 앞에 존재할 때 사용자가 자체 삽입되는 공백이나 구두점 문자(SPC, 콤마 등)를 입력할 때마다 약어가 확장된다. 좀 더 엄밀히 말해 단어 구성소가 아닌 어떤 문자든 약어로 확장되고, 단어 구성소 문자는 무엇이든 약어의 일부가 될 수 있다. 가장 흔히 약어를 사용하는 방법은 약어를 삽입한 후 구두점이나 공백 문자를 삽입하여 확장하는 방법이다.


약어 확장은 대, 소문자를 유지하므로 '

foo

' 는 '

find outer otter

' 로, '

Foo

' 는 '

Find outer otter

' 로 확장된다. '

FOO

'는 기본적으로 '

Find Outer Otter

' 로 확장되지만

abbrev-all-caps

변수를

nil

이 아닌 값으로 변경하면 '

FIND OUTER OTTER

'로 확장된다.


이러한 명령어들이 약어 확장을 제어하는 데에 사용된다:


M-'

잇따라 확장될 약어로부터 접두어를 분리시킨다(

abbrev-prefix-mark

).


C-x a e

포인트 앞의 약어를 확장한다(

expand-abbrev

). Abbrev 모드가 활성화되지 않을 때에도 효과적이다.


M-x expand-region-abbrevs

영역에서 발견된 일부 또는 모든 약어를 확장한다.


사용자는 약어를 확장시켜 확장 앞에 접두어를 추가하길 원할지도 모르는데, 가령 '

cnst

' 가 '

construction

' 으로 확장될 경우 사용자는 그것을 이용하여 '

reconstruction

' 을 입력할 수 있다.

recnst

를 입력하도록 작동하지는 않을 것인데, 이것이 꼭 정의된 약어일 필요는 없기 때문이다. 사용자가 할 수 있는 일은 접두어 '

re

' 와 약어 '

cnst

' 사이에 M-' (

abbrev-prefix-mark

) 명령어를 사용하는 것이다. 먼저 '

re

'를 삽입한다. 이후 M-' 를 입력하는데, 그러면 할 일을 마쳤음을 표시하기 위해 버퍼에 하이픈이 삽입된다. 그리고 나서 약어 '

cnst

' 를 삽입하면 버퍼는 이제 '

re-cnst

' 를 포함한다. 이제 비단어 문자를 삽입하여 약어 '

cnst

'를 '

construction

' 으로 확장한다. 이러한 확장 단계는 M-' 가 사용되었음을 나타내는 하이픈을 삭제할 것이다. 그 결과 원하는 '

reconstruction

' 이 된다.


버퍼에 사실상 확장이 아니라 약어의 텍스트를 원한다면 C-q 를 이용해 그 뒤에 따라오는 구두점을 삽입하는 방법이 있다. 따라서 foo C-q , 는 버퍼에서 'foo,' 를 확장하는 대신 남겨둔다.


약어를 실수로 확장시켰다면 C-/ (undo)를 입력하여 확장을 실행 취소한다. 관련 내용은 109 페이지의 13.1절 [실행취소]를 참고한다. 그러면 약어 확장의 삽입을 실행 취소하고 약어 텍스트를 다시 가져온다. 사용자가 원하는 결과가 끝의 비단어 문자와 더불어 확장되지 않는 약어일 경우 사용자는 끝나는 문자를 다시 삽입하여 C-q 로 인용 부호를 이용해야 한다. M-x unexpand-abbrev 명령어를 이용해 끝나는 문자를 삭제하지 않고 마지막 확장을 취소할 수도 있다.


M-x expand-region-abbrevs 는 영역에서 정의된 약어를 검색하고, 발견되는 약어마다 그 확장으로 대체할 것인지 질문한다. 이 명령어는 사용자가 약어를 이용해 텍스트에 입력하였는데 Abbrev 모드를 먼저 켜야 한다는 사실을 잊었을 때 유용하다. 또 한 번에 여러 개의 전역적 대체를 실행하기 위해 특별한 약어 정의 집합과 함께 사용할 때도 유용하다. 이 명령어는 Abbrev 모드가 활성화되지 않았을 때에도 효과적이다.


expand-abbrev

함수는

abbrev-expand-function

이 명시하는 함수를 호출함으로써 확장을 실행한다. 이 함수를 변경하면 사용자는 약어 확장에 임시 변경을 적용할 수 있다. The Emacs Lisp Reference Manual 의 "Abbrev Expansion"절을 참고한다.


약어 조사하고 편집하기

M-x list-abbrevs

모든 약어 정의의 목록을 표시한다. 수치적 인자를 이용해 로컬 약어만 열거한다.


M-x edit-abbrevs

약어 목록을 편집하고, 사용자는 정의를 추가, 수정 또는 삭제할 수 있다.


M-x list-abbrevs 에서 얻은 출력은 다음과 같은 모양을 한다:

various other tables... 
(lisp-mode-abbrev-table) 
"dk"          0    "define-key"
(global-abbrev-table) 
"dfn"         0    "definition"

(구문적 의미가 없는 일부 빈 행과 그 외 일부 약어 테이블은 생략되었다.)


괄호에 이름이 포함된 행은 특정 약어 테이블에서 약어에 대한 헤더(header)로서,

global-abbrev-table

은 모든 전역적 약어를 포함하고, 주 모드의 이름에 따라 명명된 그 외 약어 테이블은 모드 특정적인 약어를 포함한다.


각 약어 테이블 내에서는 비어 있지 않은 행마다 하나의 약어를 정의한다. 행의 시작에 위치한 워드가 약어이다. 그 뒤에 따라오는 숫자는 약어가 확장된 횟수이다. Emacs는 이를 추적하여 사용자가 사실상 사용하는 약어를 확인하도록 해주기 때문에 사용자는 자주 사용하지 않는 것을 삭제할 수 있다. 행 끝에 있는 문자열이 확장이다.


일부 약어에는 '

(sys)

'라고 표시된다. 이러한 "시스템" 약어는 (The Emacs Lisp Reference Manual 의 "Abbrevs" 절을 참고) 다양한 모드에서 사전에 정의되며, 사용자의 약어 파일로 저장되지 않는다. "시스템" 약어를 비활성화하려면 그 자체로 확장되는 것과 동일한 이름의 약어를 정의하여 사용자의 약어 파일로 저장한다.


M-x edit-abbrevs 는 사용자가 Emacs 버퍼로 약어 정의 목록을 편집하여 추가, 변경 또는 제거하도록 해준다. 목록은 위에 설명된 것과 동일한 포맷을 가진다. 약어의 버퍼는

*Abbrevs*

라고 불리고, Edit-Abbrevs 모드에 위치한다. 해당 버퍼에서 C-c C-c 를 입력하면 버퍼에 명시된 바와 같이 약어 정의를 설치하고, 열거되지 않은 약어 정의는 모두 삭제한다.


edit-abbrevs

명령어는

*Abbrevs*

버퍼를 선택하지만

list-abbrevs

는 다른 창에 표시하는 데에 그친다는 점에서 차이가 있지만 이 차이를 제외하곤

list-abbrevs

와 사실상 동일하다.


약어 저장하기

이 명령어들은 편집 세션들 간에 약어 정의를 유지하도록 해준다.


M-x write-abbrev-file RET file RET

모든 정의된 약어를 설명하는 파일 file 을 쓴다.


M-x read-abbrev-file RET file RET

file 파일을 읽어와 그곳에 명시된 대로 약어를 정의한다.


M-x define-abbrevs

현재 버퍼의 정의로부터 약어를 정의한다.


M-x insert-abbrevs

모든 약어와 확장을 현재 버퍼로 삽입한다.


M-x write-abbrev-file 은 미니버퍼를 이용해 파일명을 읽은 후 모든 현재 약어 정의의 설명을 해당 파일로 쓴다. 이는 향후 세션에서 사용할 수 있는 약어 정의를 저장하는 데에 사용된다. 파일에 보관되는 텍스트는 실행되면 사용자가 현재 갖고 있는 것과 동일한 약어를 정의하는 일련의 Lisp 표현식이다.


M-x read-abbrev-file 은 미니버퍼를 이용해 파일명을 읽은 후 파일 내용에 따라 약어를 정의하며 파일을 읽는다. 에코 영역에 메시지를 표시하지 않는다는 점을 제외하면

quietly-read-abbrev-file

함수도 비슷하며, 대화형으로 호출할 수 없고 보통 init 파일에서 사용된다(437 페이지의 33.4절 [Init 파일] 참고). 이러한 함수들 중 하나라도

nil

을 인자로 하여 호출되면

abbrev-file-name

변수가 제공한 파일, 즉

~/.emacs.d/abbrev_defs

를 기본값으로 사용한다. 이것이 사용자의 표준 약어 정의 파일로, Emacs는 시작 시 그로부터 자동으로 약어를 로딩한다. (예외로 Emacs는 약어 파일이 배치 모드에서 시작될 경우 파일을 로딩하지 않는다. 배치 모드에 대한 설명은 480 페이지의 C.2절 [초기 옵션]을 참고한다.)


사용자가 약어를 변경하였다면 Emacs 는 모든 파일을 저장할 것을 권장할 때마다 (C-x s 또는 C-x C-c 의 경우) 자동으로 약어를 저장하도록 권장할 것이다. 이는

abbrev-file-name

이 명시한 파일에 저장한다. 이러한 기능은 save-abbrevs 변수를 nil로 설정하면 억제할 수 있다.


M-x insert-abbrevsM-x define-abbrevs 명령어는 이전 명령어들과 유사하지만 Emacs 버퍼 내 텍스트에 작업한다. M-x insert-abbrevs 는 현재 버퍼에서 포인트 이후에 텍스트를 삽입하고 모든 현재 약어 정의를 설명하며, M-x define-abbrevs 는 전체 현재 버퍼를 파싱하고 그에 따라 약어를 정의한다.


동적 약어 확장

위의 약어 기능은 사용자가 텍스트를 입력할 때 자동으로 작동하지만 모든 약어는 직접 명시되어야 한다. 반면 동적 약어는 약어의 의미가 버퍼의 내용에서 자동으로 결정되도록 허용하지만 동적 약어 확장은 사용자가 명시적으로 요청할 때에만 발생한다.


M-/

버퍼에서 포인트 앞의 단어를 동적 약어로 확장하고, 그 약어로 시작하는 단어를 버퍼에서 검색한다(

dabbrev-expand

).


C-M-/

포인트 앞의 단어를 동적 약어로 완성한다(

dabbrev-completion

).


가령 버퍼가 '

does this follow

' 를 포함하고 사용자가

f o M-/

를 입력하면 '

follow

' 를 삽입하는 효과가 발생하는데, 이것이 버퍼에서 '

fo

' 로 시작하는 마지막 단어이기 때문이다. M-/ 로의 수치적 인자는 두 번째, 세 번째 식으로 발견된 구분된 확장을 취하여 포인트로부터 역방향으로 살펴보라고 말한다. M-/ 를 반복하면 더 뒤로 살펴보면서 대안 확장을 검색한다. 포인트 앞의 모든 텍스트를 스캔한 후에는 포인트 뒤의 텍스트를 검색한다.

dabbrev-limit

변수가

nil

이 아닌 경우 버퍼에서 확장을 얼마나 멀리까지 검색할 것인지 명시한다.


현재 버퍼를 스캔하고 나면 사용자가

dabbrev-check-all-buffers

nil

로 설정하지 않는 이상 M-/ 는 보통 다른 버퍼를 검색한다.


스캔할 버퍼를 좀 더 정밀하게 관리하려면

dabbrev-ignored-buffer-regexps

변수를 맞춤화한다. 그 값은 정규 표현식으로 된 목록이다. 버퍼명이 이러한 정규 표현식에 매칭할 경우 동적 약어 확장은 해당 버퍼를 건너뛴다.


C-u - M-/ 에서와 마찬가지로 M-/ 에 음의 인자를 사용하면 포인트 다음에 확장을 먼저 검색하고, 다른 버퍼로 이동하는데, 포인트 앞의 확장은 최후의 수단으로 간주한다. M-/ 를 반복하여 다른 확장을 검색할 경우 인자를 명시하지 말라. M-/ 를 반복하면 포인트 이후 모든 확장을 순환한 후 포인트 앞의 확장을 순환한다.


동적 약어를 확장한 후에는 원본 컨텍스트에서 확장을 따르는 추가 단어를 복사할 수 있다. 복사하고자 하는 추가 단어마다 SPC M-/ 를 입력하면 된다. 단어들 간 간격과 구두점은 단어와 함께 복사된다.


C-M-/ (

dabbrev-completion

) 명령어는 동적 약어의 완성을 실행한다. 가능한 확장을 하나씩 시도하는 대신 모두 찾아서 공통으로 가진 텍스트를 삽입한다. 공통으로 가진 것이 아무 것도 없다면 C-M-/ 는 사용자가 일반적인 방식으로 선택할 수 있는 완성 목록이 표시된다. 28 페이지의 5.4절 [완성]을 참고한다.


동적 약어 확장은 Abbrev 모드와 전적으로 무관하며, M-/ 를 이용한 단어 확장은 일반 약어로서 정의를 갖고 있는지 여부와 전혀 상관없다.


동적 약어 맞춤화하기

보통 동적 약어 확장은 확장을 검색할 때 대, 소문자를 무시한다. 즉, 확장은 사용자가 확장하려는 단어의 대, 소문자와 일치하지 않아도 된다는 의미다.


이 기능은

dabbrev-case-fold-search

변수에 의해 제어된다. 이 값이

t

일 경우 대, 소문자가 검색에서 무시되고,

nil

일 경우 단어와 확장은 대, 소문자가 일치해야 한다. 값이

case-fold-search

일 경우(기본값)

case-fold-search

변수는 확장 검색 시 대, 소문자를 무시할 것인지 결정한다(102 페이지의 12.9절 [검색 대, 소문자] 참고).


보통 동적 약어 확장은 확장을 대, 소문자 패턴으로 변환시킴으로써 사용자가 확장 중인 동적 약어의 대, 소문자 패턴을 유지한다.


dabbrev-case-replace

변수는 동적 약어의 대, 소문자 패턴을 유지할 것인지 여부를 제어한다. 이 값이

t

일 경우 동적 약어의 대, 소문자 패턴은 대부분의 경우 유지되지만 nil일 경우 확장은 항상 복사된 축어(copied verbatim)가 된다. 값이

case-replace

(기본값)일 경우

case-replace

변수는 확장 축어를 복사할 것인지를 결정한다(104 페이지의 12.10.3절 [대체와 대, 소문자] 참고).


하지만 확장이 복잡하게 섞인 대, 소문자 패턴을 포함하고 동적 약어가 어느 정도 이 패턴에 일치할 경우 확장은 그러한 변수들과 상관없이 항상 복사된 축어가 된다. 따라서 가령 버퍼가

variableWithSillyCasePattern

을 포함하고 사용자가 v a M-/ 를 입력하면 확장의 대, 소문자 패턴을 포함해 확장 축어(expansion verbatim)를 복사한다.


dabbrev-abbrev-char-regexp

변수가

nil

이 아닌 경우 동적 확장을 목적으로 할 때 어떤 문자들이 단어의 일부로 간주되는지를 제어한다. 정규 표현식은 하나의 문자에만 일치해야 하고, 절대 두 개 또는 이상의 문자에 일치해선 안 된다. 동일한 정규 표현식으로 어떤 문자가 확장의 일부인지를 결정하기도 한다.

nil

값은 특별한 의미를 지니는데, 동적 약어는 단어 문자로 구성되지만 확장은 단어와 심볼 문자로 구성된다는 점이다.


셸 스크립트와 makefile 에서 변수명 앞에는 때때로 '

$

'가 붙기도 하고 때로는 붙지 않는다. 이러한 유형의 텍스트에 대한 주 모드는 동적 약어 확장이 선택적 접두어를 처리하도록 맞춤화할 수 있는데, 이는

dabbrev-abbrev-skip-leading-regexp

변수를 설정하여 이루어진다. 그 값은 동적 약어 표현식이 무시해야 하는 선택적 접두어에 매칭하는 정규 표현식이어야 한다.


Notes