GNUEmacsManual:26
- 약어
약어
정의된 약어(abbrev)는 사용자가 다른 텍스트로 삽입하면 확장되는 단어를 의미한다. 약어는 구체적인 방식으로 확장되도록 사용자에 의해 정의된다. 가령 사용자는 '
' 를 '
' 로 확장되는 축약어로 정의할 수 있다. 그리고
를 입력하면 '
' 를 버퍼로 삽입할 수 있다.
두 번째 종류의 축약 기능은 동적 약어 확장이라고 불린다. 버퍼에서 포인트 앞 문자를 확장하여 버퍼에서 그러한 글자로 시작하는 다른 단어를 살펴보는 직접적 명령어로 동적 약어 확장을 이용할 수 있다. 313 페이지의 26.6절 [동적 약어]를 참고한다.
"히피(Hippie)" 확장은 약어 확장을 일반화한다. Features for Automatic Typing 의 "Hippie Expansion"절을 참고한다.
약어 개념
약어(abbrev)는 명시된 확장(expansion)으로 확장되도록 정의된 단어이다. 약어 다음에 단어를 구분하는 문자를 삽입하면 약어를 확장하여 약어를 그 확장으로 대체한다. 가령 '
' 가 '
' 로 확장되는 약어로 정의되면
를 입력 시 '
' 가 삽입될 것이다.
약어는 Abbrev 모드라는 버퍼 로컬 부 모드가 활성화되었을 때에만 확장된다. Abbrev 모드를 비활성화한다고 해서 약어 정의가 잊혀지는 것은 아니지만 Abbrev 모드가 다시 활성화될 때까지는 확장되지 않는다. M-x abbrev-mode 명령어는 Abbrev 모드를 토글하며, 수치적 인자를 이용해 인자가 양수일 경우 Abbrev 모드를 켜고 그 외의 경우 모드를 끈다. 200 페이지의 20.2절 [부 모드]를 참고한다.
약어는 모드 특정적 정의를 가질 수 있고, 이는 하나의 주 모드에서만 활성화된다. 약어는 모든 주 모드에서 활성화되는 전역적 정의를 가질 수도 있다. 동일한 약어는 전역적 정의와 다른 주 모드들에 걸쳐 다양한 모드 특정적 정의를 가질 수 있다. 현재 주 모드에 대한 모드 특정적 정의는 전역적 정의를 오버라이드한다.
Abbrev 모드의 활성화 여부와 상관없이 편집 세션 중에는 약어를 상호작용적으로 정의할 수 있다. 약어 정의 목록을 파일에 저장하여 이후 세션에서 재로딩하여 사용할 수도 있다.
약어 정의하기
포인트 앞에 하나 또는 이상의 단어를 확장으로 이용하여 약어를 정의한다(
).
유사하지만 현재 주 모드에 특정적인 약어를 정의한다(
).
버퍼에서 단어를 약어로 정의한다(
).
버퍼에서 단어를 모드 특정적인 약어로 정의한다(
).
abbrev 를 exp 로 확장되는 약어로서 정의한다.
abbrev 를 exp 로 확장되는 모드 특정적 약어로서 정의한다.
모든 약어 정의를 제거하고 비어둔다(blank slate).
약어를 정의하는 일반적인 방법은 약어를 확장시키려는 텍스트를 입력하고, 그 뒤에 포인트를 위치시킨 후 C-x a g (
)를 입력하는 방법이다. 그러면 미니버퍼를 이용해 약어 자체가 읽힌 후 포인트 앞에 하나 또는 이상의 단어에 대한 약어로서 정의된다. 수치적 인자를 이용해 포인트 앞에 얼마나 많은 단어를 확장으로 취급할 것인지 명시한다. 예를 들어 위에서 언급한 '
' 약어를 정의하려면 '
' 텍스트를 삽입한 다음 C-u 3 C-x a g f o o RET 을 입력한다.
C-x a g 에 대한 인자가 0일 경우 영역의 내용을 정의되는 약어의 확장으로 이용할 것을 의미한다.
C-x a l (
) 명령어도 비슷하지만 현재 주 모드에 대한 모드 특정적 약어를 정의한다. 인자는 C-x a g 에서와 동일하게 작동한다.
C-x a i g (
) 와 C-x a i l (
)는 상반된 과제를 수행하는데, 약어 텍스트가 이미 버퍼에 있는 경우 이러한 명령어를 이용해 미니버퍼에서 확장을 명시함으로써 약어를 정의한다. 이러한 명령어들은 정의에 사용된 약어 텍스트를 확장시킬 것이다.
명령어를 이용하면 버퍼에서 약어 또는 그 확장을 삽입하지 않고 약어를 정의할 수 있다. 이는 두 개의 인자, 즉 약어와 확장을 읽는다.
명령어도 마찬가지로 모드 특정적인 약어에 대해 실행된다.
약어의 정의를 변경하려면 그냥 새 정의를 만든다. 약어가 기존 정의를 갖고 있다면 약어 정의 명령어는 새로운 정의로 대체하기 전에 확인을 요청한다.
약어 정의를 제거하려면 약어 정의 명령어에 음의 인자를 제공한다: C-u - C-x a g 또는 C-u - C-x a l. 전자는 전역적 정의를 제거하는 반면 후자는 모드 특정적 정의를 제거한다. M-x kill-all-abbrevs 는 전역 및 로컬을 포함해 모든 약어 정의를 제거한다.
약어 확장 제어하기
Abbrev 모드가 활성화되면 버퍼에서 포인트 앞에 존재할 때 사용자가 자체 삽입되는 공백이나 구두점 문자(SPC, 콤마 등)를 입력할 때마다 약어가 확장된다. 좀 더 엄밀히 말해 단어 구성소가 아닌 어떤 문자든 약어로 확장되고, 단어 구성소 문자는 무엇이든 약어의 일부가 될 수 있다. 가장 흔히 약어를 사용하는 방법은 약어를 삽입한 후 구두점이나 공백 문자를 삽입하여 확장하는 방법이다.
약어 확장은 대, 소문자를 유지하므로 '
' 는 '
' 로, '
' 는 '
' 로 확장된다. '
'는 기본적으로 '
' 로 확장되지만
변수를
이 아닌 값으로 변경하면 '
'로 확장된다.
이러한 명령어들이 약어 확장을 제어하는 데에 사용된다:
잇따라 확장될 약어로부터 접두어를 분리시킨다(
).
포인트 앞의 약어를 확장한다(
). Abbrev 모드가 활성화되지 않을 때에도 효과적이다.
영역에서 발견된 일부 또는 모든 약어를 확장한다.
사용자는 약어를 확장시켜 확장 앞에 접두어를 추가하길 원할지도 모르는데, 가령 '
' 가 '
' 으로 확장될 경우 사용자는 그것을 이용하여 '
' 을 입력할 수 있다.
를 입력하도록 작동하지는 않을 것인데, 이것이 꼭 정의된 약어일 필요는 없기 때문이다. 사용자가 할 수 있는 일은 접두어 '
' 와 약어 '
' 사이에 M-' (
) 명령어를 사용하는 것이다. 먼저 '
'를 삽입한다. 이후 M-' 를 입력하는데, 그러면 할 일을 마쳤음을 표시하기 위해 버퍼에 하이픈이 삽입된다. 그리고 나서 약어 '
' 를 삽입하면 버퍼는 이제 '
' 를 포함한다. 이제 비단어 문자를 삽입하여 약어 '
'를 '
' 으로 확장한다. 이러한 확장 단계는 M-' 가 사용되었음을 나타내는 하이픈을 삭제할 것이다. 그 결과 원하는 '
' 이 된다.
버퍼에 사실상 확장이 아니라 약어의 텍스트를 원한다면 C-q 를 이용해 그 뒤에 따라오는 구두점을 삽입하는 방법이 있다. 따라서 foo C-q , 는 버퍼에서 'foo,' 를 확장하는 대신 남겨둔다.
약어를 실수로 확장시켰다면 C-/ (undo)를 입력하여 확장을 실행 취소한다. 관련 내용은 109 페이지의 13.1절 [실행취소]를 참고한다. 그러면 약어 확장의 삽입을 실행 취소하고 약어 텍스트를 다시 가져온다. 사용자가 원하는 결과가 끝의 비단어 문자와 더불어 확장되지 않는 약어일 경우 사용자는 끝나는 문자를 다시 삽입하여 C-q 로 인용 부호를 이용해야 한다. M-x unexpand-abbrev 명령어를 이용해 끝나는 문자를 삭제하지 않고 마지막 확장을 취소할 수도 있다.
M-x expand-region-abbrevs 는 영역에서 정의된 약어를 검색하고, 발견되는 약어마다 그 확장으로 대체할 것인지 질문한다. 이 명령어는 사용자가 약어를 이용해 텍스트에 입력하였는데 Abbrev 모드를 먼저 켜야 한다는 사실을 잊었을 때 유용하다. 또 한 번에 여러 개의 전역적 대체를 실행하기 위해 특별한 약어 정의 집합과 함께 사용할 때도 유용하다. 이 명령어는 Abbrev 모드가 활성화되지 않았을 때에도 효과적이다.
함수는
이 명시하는 함수를 호출함으로써 확장을 실행한다. 이 함수를 변경하면 사용자는 약어 확장에 임시 변경을 적용할 수 있다. The Emacs Lisp Reference Manual 의 "Abbrev Expansion"절을 참고한다.
약어 조사하고 편집하기
모든 약어 정의의 목록을 표시한다. 수치적 인자를 이용해 로컬 약어만 열거한다.
약어 목록을 편집하고, 사용자는 정의를 추가, 수정 또는 삭제할 수 있다.
M-x list-abbrevs 에서 얻은 출력은 다음과 같은 모양을 한다:
various other tables...
(lisp-mode-abbrev-table)
"dk" 0 "define-key"
(global-abbrev-table)
"dfn" 0 "definition"
(구문적 의미가 없는 일부 빈 행과 그 외 일부 약어 테이블은 생략되었다.)
괄호에 이름이 포함된 행은 특정 약어 테이블에서 약어에 대한 헤더(header)로서,
은 모든 전역적 약어를 포함하고, 주 모드의 이름에 따라 명명된 그 외 약어 테이블은 모드 특정적인 약어를 포함한다.
각 약어 테이블 내에서는 비어 있지 않은 행마다 하나의 약어를 정의한다. 행의 시작에 위치한 워드가 약어이다. 그 뒤에 따라오는 숫자는 약어가 확장된 횟수이다. Emacs는 이를 추적하여 사용자가 사실상 사용하는 약어를 확인하도록 해주기 때문에 사용자는 자주 사용하지 않는 것을 삭제할 수 있다. 행 끝에 있는 문자열이 확장이다.
일부 약어에는 '
'라고 표시된다. 이러한 "시스템" 약어는 (The Emacs Lisp Reference Manual 의 "Abbrevs" 절을 참고) 다양한 모드에서 사전에 정의되며, 사용자의 약어 파일로 저장되지 않는다. "시스템" 약어를 비활성화하려면 그 자체로 확장되는 것과 동일한 이름의 약어를 정의하여 사용자의 약어 파일로 저장한다.
M-x edit-abbrevs 는 사용자가 Emacs 버퍼로 약어 정의 목록을 편집하여 추가, 변경 또는 제거하도록 해준다. 목록은 위에 설명된 것과 동일한 포맷을 가진다. 약어의 버퍼는
라고 불리고, Edit-Abbrevs 모드에 위치한다. 해당 버퍼에서 C-c C-c 를 입력하면 버퍼에 명시된 바와 같이 약어 정의를 설치하고, 열거되지 않은 약어 정의는 모두 삭제한다.
명령어는
버퍼를 선택하지만
는 다른 창에 표시하는 데에 그친다는 점에서 차이가 있지만 이 차이를 제외하곤
와 사실상 동일하다.
약어 저장하기
이 명령어들은 편집 세션들 간에 약어 정의를 유지하도록 해준다.
모든 정의된 약어를 설명하는 파일 file 을 쓴다.
file 파일을 읽어와 그곳에 명시된 대로 약어를 정의한다.
현재 버퍼의 정의로부터 약어를 정의한다.
모든 약어와 확장을 현재 버퍼로 삽입한다.
M-x write-abbrev-file 은 미니버퍼를 이용해 파일명을 읽은 후 모든 현재 약어 정의의 설명을 해당 파일로 쓴다. 이는 향후 세션에서 사용할 수 있는 약어 정의를 저장하는 데에 사용된다. 파일에 보관되는 텍스트는 실행되면 사용자가 현재 갖고 있는 것과 동일한 약어를 정의하는 일련의 Lisp 표현식이다.
M-x read-abbrev-file 은 미니버퍼를 이용해 파일명을 읽은 후 파일 내용에 따라 약어를 정의하며 파일을 읽는다. 에코 영역에 메시지를 표시하지 않는다는 점을 제외하면
함수도 비슷하며, 대화형으로 호출할 수 없고 보통 init 파일에서 사용된다(437 페이지의 33.4절 [Init 파일] 참고). 이러한 함수들 중 하나라도
을 인자로 하여 호출되면
변수가 제공한 파일, 즉
를 기본값으로 사용한다. 이것이 사용자의 표준 약어 정의 파일로, Emacs는 시작 시 그로부터 자동으로 약어를 로딩한다. (예외로 Emacs는 약어 파일이 배치 모드에서 시작될 경우 파일을 로딩하지 않는다. 배치 모드에 대한 설명은 480 페이지의 C.2절 [초기 옵션]을 참고한다.)
사용자가 약어를 변경하였다면 Emacs 는 모든 파일을 저장할 것을 권장할 때마다 (C-x s 또는 C-x C-c 의 경우) 자동으로 약어를 저장하도록 권장할 것이다. 이는
이 명시한 파일에 저장한다. 이러한 기능은 save-abbrevs 변수를 nil로 설정하면 억제할 수 있다.
M-x insert-abbrevs 와 M-x define-abbrevs 명령어는 이전 명령어들과 유사하지만 Emacs 버퍼 내 텍스트에 작업한다. M-x insert-abbrevs 는 현재 버퍼에서 포인트 이후에 텍스트를 삽입하고 모든 현재 약어 정의를 설명하며, M-x define-abbrevs 는 전체 현재 버퍼를 파싱하고 그에 따라 약어를 정의한다.
동적 약어 확장
위의 약어 기능은 사용자가 텍스트를 입력할 때 자동으로 작동하지만 모든 약어는 직접 명시되어야 한다. 반면 동적 약어는 약어의 의미가 버퍼의 내용에서 자동으로 결정되도록 허용하지만 동적 약어 확장은 사용자가 명시적으로 요청할 때에만 발생한다.
버퍼에서 포인트 앞의 단어를 동적 약어로 확장하고, 그 약어로 시작하는 단어를 버퍼에서 검색한다(
).
포인트 앞의 단어를 동적 약어로 완성한다(
).
가령 버퍼가 '
' 를 포함하고 사용자가
를 입력하면 '
' 를 삽입하는 효과가 발생하는데, 이것이 버퍼에서 '
' 로 시작하는 마지막 단어이기 때문이다. M-/ 로의 수치적 인자는 두 번째, 세 번째 식으로 발견된 구분된 확장을 취하여 포인트로부터 역방향으로 살펴보라고 말한다. M-/ 를 반복하면 더 뒤로 살펴보면서 대안 확장을 검색한다. 포인트 앞의 모든 텍스트를 스캔한 후에는 포인트 뒤의 텍스트를 검색한다.
변수가
이 아닌 경우 버퍼에서 확장을 얼마나 멀리까지 검색할 것인지 명시한다.
현재 버퍼를 스캔하고 나면 사용자가
를
로 설정하지 않는 이상 M-/ 는 보통 다른 버퍼를 검색한다.
스캔할 버퍼를 좀 더 정밀하게 관리하려면
변수를 맞춤화한다. 그 값은 정규 표현식으로 된 목록이다. 버퍼명이 이러한 정규 표현식에 매칭할 경우 동적 약어 확장은 해당 버퍼를 건너뛴다.
C-u - M-/ 에서와 마찬가지로 M-/ 에 음의 인자를 사용하면 포인트 다음에 확장을 먼저 검색하고, 다른 버퍼로 이동하는데, 포인트 앞의 확장은 최후의 수단으로 간주한다. M-/ 를 반복하여 다른 확장을 검색할 경우 인자를 명시하지 말라. M-/ 를 반복하면 포인트 이후 모든 확장을 순환한 후 포인트 앞의 확장을 순환한다.
동적 약어를 확장한 후에는 원본 컨텍스트에서 확장을 따르는 추가 단어를 복사할 수 있다. 복사하고자 하는 추가 단어마다 SPC M-/ 를 입력하면 된다. 단어들 간 간격과 구두점은 단어와 함께 복사된다.
C-M-/ (
) 명령어는 동적 약어의 완성을 실행한다. 가능한 확장을 하나씩 시도하는 대신 모두 찾아서 공통으로 가진 텍스트를 삽입한다. 공통으로 가진 것이 아무 것도 없다면 C-M-/ 는 사용자가 일반적인 방식으로 선택할 수 있는 완성 목록이 표시된다. 28 페이지의 5.4절 [완성]을 참고한다.
동적 약어 확장은 Abbrev 모드와 전적으로 무관하며, M-/ 를 이용한 단어 확장은 일반 약어로서 정의를 갖고 있는지 여부와 전혀 상관없다.
동적 약어 맞춤화하기
보통 동적 약어 확장은 확장을 검색할 때 대, 소문자를 무시한다. 즉, 확장은 사용자가 확장하려는 단어의 대, 소문자와 일치하지 않아도 된다는 의미다.
이 기능은
변수에 의해 제어된다. 이 값이
일 경우 대, 소문자가 검색에서 무시되고,
일 경우 단어와 확장은 대, 소문자가 일치해야 한다. 값이
일 경우(기본값)
변수는 확장 검색 시 대, 소문자를 무시할 것인지 결정한다(102 페이지의 12.9절 [검색 대, 소문자] 참고).
보통 동적 약어 확장은 확장을 대, 소문자 패턴으로 변환시킴으로써 사용자가 확장 중인 동적 약어의 대, 소문자 패턴을 유지한다.
변수는 동적 약어의 대, 소문자 패턴을 유지할 것인지 여부를 제어한다. 이 값이
일 경우 동적 약어의 대, 소문자 패턴은 대부분의 경우 유지되지만 nil일 경우 확장은 항상 복사된 축어(copied verbatim)가 된다. 값이
(기본값)일 경우
변수는 확장 축어를 복사할 것인지를 결정한다(104 페이지의 12.10.3절 [대체와 대, 소문자] 참고).
하지만 확장이 복잡하게 섞인 대, 소문자 패턴을 포함하고 동적 약어가 어느 정도 이 패턴에 일치할 경우 확장은 그러한 변수들과 상관없이 항상 복사된 축어가 된다. 따라서 가령 버퍼가
을 포함하고 사용자가 v a M-/ 를 입력하면 확장의 대, 소문자 패턴을 포함해 확장 축어(expansion verbatim)를 복사한다.
변수가
이 아닌 경우 동적 확장을 목적으로 할 때 어떤 문자들이 단어의 일부로 간주되는지를 제어한다. 정규 표현식은 하나의 문자에만 일치해야 하고, 절대 두 개 또는 이상의 문자에 일치해선 안 된다. 동일한 정규 표현식으로 어떤 문자가 확장의 일부인지를 결정하기도 한다.
값은 특별한 의미를 지니는데, 동적 약어는 단어 문자로 구성되지만 확장은 단어와 심볼 문자로 구성된다는 점이다.
셸 스크립트와 makefile 에서 변수명 앞에는 때때로 '
'가 붙기도 하고 때로는 붙지 않는다. 이러한 유형의 텍스트에 대한 주 모드는 동적 약어 확장이 선택적 접두어를 처리하도록 맞춤화할 수 있는데, 이는
변수를 설정하여 이루어진다. 그 값은 동적 약어 표현식이 무시해야 하는 선택적 접두어에 매칭하는 정규 표현식이어야 한다.