Emacs와 함께 더 많은 배터리
출처: Hacker News
Emacs 기능들이 가시성 문제를 안고 있어, 우리는 매번 데모 하나씩 해결해 나가고 있습니다. 이전 글을 쓴 지 몇 년이 지나면서 더 놀라운 유용한 발견들이 나왔기 때문에 다시 한 번 ‘배터리 포함’ 보고서를 올릴 차례입니다.
참고 이 시리즈의 세 번째 글로, 유용하지만 널리 알려진 Emacs 기능들을 소개합니다.
파트 1 & 2:
‘덜 알려진’은 주관적인 판단입니다. 대략적으로, 이는 작성 시점에 저에게 지난 20년간 온라인 Emacs 담론에서 이 기능들이 다섯 번 미만으로 언급된 것을 의미합니다 – 그리고 종종 전혀 언급되지 않았습니다.
If you’re a new Emacs user, don’t start here. This is not a getting‑started guide. You will be better served by grokking basic Emacs concepts and sticking to the most widely recommended packages. Once you’ve experienced the Emacs equivalents of thoughts like “Why didn’t anyone think to put wheels on luggage until 1990?”, this series might be more helpful.
제 경험 법칙은, 아직 ‘취소 영역’(undo‑in‑region)을 알지 못하면 여전히 쉽게 가져올 수 있는 과제가 많이 남아 있으며, 그 자원이 소진될 때 다시 이 글을 찾아 보세요!
Veteran Emacs users tend to use some relatively niche Emacs features, but in my experience it’s always a different subset for each user. So if you’ve been around the block a few times, I promise there will still be surprises below for you as well!
앞과 같은 규칙들입니다:
-
패키지 없이 스톡 Emacs 전용
-
급격한 학습 곡선 없음. 각 기능을 5분 이내에 익히거나 포기하라.
-
가짜 요소 없음. No
doctor,tetris,snake,dunnet,zone,butterfly… 네, 우리는dissociated-press에 대해 알고 있습니다. 바로 진행하겠습니다. -
오직 차이점만.
Flymake,doc-view,outline-minor-mode,gnus,eww같은 패키지는 없으며, Emacs가 자동으로 제공하거나 nonspecific Google 검색으로 쉽게 찾을 수 있는 것이 아닙니다.
현대적인 Emacs(28.1 이상)를 가정합니다.
또한, Emacs에 아직 익숙하지 않고 계속 읽고 있는 경우:
Emacs 용어
현대 식 표현
M-x
Alt + x
C-x
Ctrl + x
프레임 (윈도우)
Emacs 창
윈도우 (분할/패널)
버퍼
연속적인 텍스트/데이터 조각
포인트 (커서 위치)
활성 영역 (텍스트 선택)
Region (텍스트 선택, 하이라이트되지 않음)
Face (폰트, 색상 및 표시 특성)
I’m Sorry.
Okay? Let’s go:
사전 호버 (M-x dictionary-tooltip-mode)
dictionary-tooltip-mode를 켜면 마우스를 hovering(오버)할 때 단어가 의미하는 툴팁을 볼 수 있습니다:

Of course, tooltip-mode도 기본적으로 활성화되어 있어야 하지만, 대부분은 이미 켜져 있습니다. 지역 사전을 사용하고 있다면 먼저 그 사전을 시도합니다. Emacs 사전은 일반적으로 위키낱말사전(위키백과)를 통해 현대 용어와 슬랭도 검색할 수 있습니다:
find-file 및 dired 와일드카드
두 가장 자주 사용되는 Emacs 명령어인 find-file와 dired를 활용할 수 있는 놀라운 팁이 있습니다: 인터랙티브하게 와일드카드를 사용할 수 있습니다.
find-file(C-x C-f)을 사용해 *foo*.txt와 같은 와일드카드로 한 번에 여러 파일을 열 수 있습니다. Dired에서 디렉터리를 열고 파일명 와일드카드를 지정하면 특정 파일의 맞춤형 목록을 만들 수 있습니다.
다음은 두 기능을 활용해 오래된 TeX 컴파일 아티팩트를 정리하고 동시에 여러 LaTeX 파일을 여는 데모입니다:
[동영상: Emacs Dired 및 Find-File 와일드카드 데모]
Play by play
Run Dired에 “두 레벨” 와일드카드 */*_region_*를 사용해 _region_이 포함된 파일명을 하위 디렉터리까지 검색합니다. Dired는 이러한 파일들의 목록을 표시합니다. (이들은 AucTeX에서 만든 임시 파일입니다.)
t에 바인딩된dired-toggle-marks를 사용해 모두 선택하고 삭제합니다.- 와일드카드를 사용해 하위 디렉터리의 모든 TeX 파일을 엽니다.
- 버퍼 목록을 확인하여 여러 TeX 파일이 열렸다는 것을 확인합니다. (
consult-buffer명령을 사용해 열린 버퍼 목록을 확인하고,Corfu가 완전성을 제공합니다.)
프로그래밍적으로 호출할 때는 함수 시그니처만으로도 명백히 가능함을 알 수 있지만, 인터랙티브하게 사용한다는 사실을知るには 전체 문서 문자열을 읽어야 하는데 아무도 시간이 없습니다!
실제로는 consult-find와 같은 현대적인 워크플로우가 embark-export에 의해 Dired 버퍼로 내보내는 방식으로 와일드카드 기능을 대체하지만, 이 방법은 바로 사용 가능합니다.
Emacs의 ‘파일 경로에서 찾기’(ffap) 기능에 익숙할 수 있습니다. 이 명령은 커서가 유효한 파일 경로인지 확인하고 열기를 제안합니다. 또한 ffap-menu라는 덜 알려진 하지만 유용한 명령이 동반됩니다.
ffap-menu는 전체 버퍼를 스캔하여 파일 경로나 URL처럼 보이는 모든 항목을 제시합니다:
completing-read 인터페이스를 제공하므로 여러 가능성을 열게 됩니다: 필터링된 결과를 버퍼에 내보내거나, 모두 또는 일부를 복사하거나 바로 Embark을 사용해 액션을 수행할 수 있습니다.
Addendum: Listing propertized links
많은 Emacs 애플리케이션(예: EWW)은 URL을 일반 텍스트가 아닌 텍스트 특성으로 포함하고 있으며, ffap-menu에서는 이를 놓칩니다. ffap-menu를 영감으로 삼아 직접 만든 버전이 이러한 링크도 가져올 수 있게 합니다.
Play by play
- EWW가 Wikipedia 페이지를 보여주고, 왼쪽에 imenu가 표시됩니다.
my/search-occur-browse-url이라는ffap-menu를 영감으로 얻은 커스텀 명령을 호출합니다.- 페이지 링크 목록을 스クロll하고, 페이지 자체도 스クロll합니다.
향상된 버전:
(defun my/search-occur-browse-url (&optional use-generic-p)
"버퍼 내에서 URL을 클릭하여 브라우저로 이동합니다.
사용할 웹 브라우저는 변수 `browse-url-browser-function`'의 값에 따라 결정됩니다.
또한 `my/search-occur-url`'도 참고하십시오."
(interactive "P")
(let ((match nil)
(match-data nil)
(context
(lambda (beg &optional shrp)
(let*
((before (string- replace "\n" "" (buffer-substring-no-properties (max (line-beginning-position) (- beg 30)))))
(link (string- replace "\n" "" (buffer-substring-no-properties beg (point))))
(after (buffer-substring-no-properties (point) (min (line-end-position) (+ (point) 30)))))
(concat (propertize " " 'display '(space :align-to 65))
(propertize (concat "…" before) 'face 'shadow)
(if shrp
(propertize link 'face '(:inherit shadow :weight bold :underline t))
link)
(propertize (concat after "…") 'face 'shadow)))))
(save-excursion
(goto-char (point-min))
(while (search-forward-regexp my/search-url-regexp nil t)
(push (cons (match-string-no-properties 0)
(funcall context (match-beginning 0)))
match-data))
(goto-char (point-min))
(while (setq match (text-property- search-forward 'shr-url nil nil))
(push (cons (prop-match-value match)
(funcall cont...)))))