Emacsにさらに多くのバッテリー同梱機能が追加
(karthinks.com)- Emacsの基本機能には、別パッケージなしで使えるものの目立ちにくいツールが多く、現代の Emacs 28.1+ でも 5 分以内に覚えられる実用機能が今なお見つかる
- ファイルを開く・URL を集める・比較する・変更を追跡するといった日常作業は、
find-file、dired、ffap-menu、compare-windows、highlight-changes-modeだけでもかなりの部分をこなせる - バックアップファイルとバージョン管理ファイルは、
vc-diff系のコマンドを拡張すれば 以前のバージョンと比較する という 1 つの作業モデルにまとめられる - 編集・探索・表示の作業は、
apropos系、find-function-on-key、kmacro-edit-lossage、subword-mode、画像操作キーマップのような、すでに含まれている機能だけでも素早く改善できる - 重要な takeaway は、Emacs の
lispディレクトリがそれほど大きくなくても、標準内蔵機能だけで作業フローを広げる余地がまだまだ残っているという点である
概要と範囲
- Emacs の機能には発見しにくさという問題があり、この記事は、あまり知られていないが便利な内蔵機能を 1 つずつ紹介する形でその問題を和らげようとする試みである
- 今回の記事は、Emacs に標準で含まれている便利だがあまり知られていない機能を扱う 3 本目の記事である
- 「あまり知られていない」は主観的な判断であり、過去 20 年にわたってオンラインの Emacs 談義を見てきた中で、その機能が 5 回未満しか言及されていない、あるいは一度も見たことがない場合をおおむね指す
- 新しい Emacs ユーザーはここから始めないほうがよく、基本概念や広く推奨されるパッケージに慣れてからのほうが、この一覧はより役に立つ
- 基準としては、パッケージなしの 素の Emacs のみを使い、急な学習曲線がなく、遊び的な機能やよく話題になる機能を除き、現代の Emacs 28.1+ を前提とする
マウスオーバー辞書: M-x dictionary-tooltip-mode
dictionary-tooltip-modeを有効にすると、単語の上にマウスを置いたときにツールチップで意味を見られるtooltip-modeも有効である必要があるが、これはデフォルトで有効になっている- ローカル辞書が設定されていればまずそれを使い、Emacs の辞書は通常 Wiktionary 経由で現代的な用語やスラングも見つけられる
find-file と dired のワイルドカード
find-fileとdiredは対話的に使う場合でも ワイルドカード を使えるfind-fileで*foo*.txtのようなパターンを使えば、複数ファイルを一度に開ける- Dired でディレクトリを開くときにファイル名ワイルドカードを指定すると、特定のファイルだけを集めたカスタム一覧を作れる
- 例の流れでは、
*/*_region_*パターンでサブディレクトリの AucTeX 一時ファイルを探し、Dired で選択して削除し、その後またワイルドカードでサブディレクトリ内の複数の TeX ファイルを開く - この機能は関数シグネチャ上はプログラミング呼び出しで分かるものの、対話的な利用でも可能だという点は docstring 全体を読まないと気づきにくい
- Dired のワイルドカード機能は、
consult-findとembark-exportで作る現代的な Dired フローに押されがちだが、素の状態でそのまま動く
バッファ内の URI 一覧: M-x ffap-menu
ffapは、カーソル位置が有効なファイルパスまたは URL かどうかを判定して開けるようにする find-file-at-point 機能であるffap-menuはバッファ全体を走査し、ファイルパスや URL のように見える項目を見つけて一覧として提示するcompleting-readインターフェースを使うため、絞り込んだ候補一覧をバッファへエクスポートしたり、一部または全部をコピー・開く・Embark で処理したりできる-
属性付きリンクの一覧化
- EWW のような Emacs アプリケーションは、URL を通常のテキストリンクではなくテキスト属性として埋め込むことがあり、
ffap-menuはそれを見逃す - これを補うには、
ffap-menuに着想を得たユーザー定義コマンドでshr-urlテキスト属性まで収集できる - 例のコマンド
my/search-occur-browse-urlは、通常の URL 正規表現とshr-url属性の両方を見つけて補完候補を作り、選んだ URL をbrowse-urlまたはbrowse-url-genericで開くように構成されている
- EWW のような Emacs アプリケーションは、URL を通常のテキストリンクではなくテキスト属性として埋め込むことがあり、
ウィンドウ比較: M-x compare-windows
- Emacs には、
diff、diff-buffers、diff-backup、dired-diff、vc-diff、さまざまなediff-*コマンドのように比較コマンドが多い compare-windowsは 2 つのウィンドウのカーソル位置からテキストを比較し、次の不一致箇所で停止してそれを報告する- 比較対象はアクティブなウィンドウと、
other-windowが選ぶウィンドウであり、Ediff や diff より機能は少ないが、実行はより簡単で速い - バッファの種類、変更状態、ファイル、バージョン管理状態に関係なく、2 つのウィンドウに表示されている実際のテキストだけを比較する
- 同じバッファの別の部分を 2 つのウィンドウに表示すれば、同じバッファ内の 2 つのテキスト片も比較できる
- ディレクトリ一覧も比較でき、例ではファイルの更新時刻が最初の不一致として検出される
- 前置引数を与えると空白の違いを無視できる
Dired でディレクトリ比較: M-x dired-compare-directories
dired-compare-directoriesは Dired で比較するディレクトリを尋ね、2 つの Dired 一覧で名前が異なるファイルを表示する- この方法は、最も一般的なディレクトリ比較のユースケースを処理できる
- ファイルレベルの比較なので、更新時刻やサイズなどのファイル属性を含むカスタムの一致条件を与えられる
(> mtime2 mtime1)条件なら、より新しく更新されたファイルを表示できる(/= size1 size2)条件なら、名前は同じだがサイズが異なるファイルを表示できる- より対話的な比較が必要なら
ediff-directoriesも使える
バッファ変更の強調表示: M-x highlight-changes-mode
highlight-changes-modeはファイルの変更箇所を強調表示する機能で、diff-buffer-with-fileのような diff コマンドの「ライブ」代替として使える- 基本動作では、モードを有効にした時点から無効にするまでの変更を強調表示し、未保存の変更だけを自動で強調する仕組みではない
before-save-hookとafter-save-hookを使えば、保存前に強調表示を切り、保存後に再び有効にする形で、保存前の変更だけを強調するフローを作れる- 例のコードでは、
text-mode-hookでファイルバッファにhighlight-changes-modeを有効にし、保存前後のフックで強調状態を調整する - 独立した
highlight-unsaved-modeの形にすれば、保存するまでのすべての変更を強調表示するマイナーモードになる highlight-changes-next-changeとhighlight-changes-previous-changeで次・前の変更箇所へ移動できるhighlight-changes-remove-highlightで視覚的な強調表示を取り除き、変更追跡にもとづく移動だけを使うこともできる
バックアップファイルを実際に役立てる: vc-diff 系
-
Emacs バックアップの問題
- Emacs はデフォルトで、編集して保存するファイルのバックアップを定期的に作成する
- このバックアップシステムは、通常
make-backup-filesで無効にすべき面倒な機能として言及される - 機密ファイルがディスク上の別の場所にコピーされることへのセキュリティ上の懸念がありうる
- それ以外では、問題は主に作業ディレクトリにバックアップが散らばることと、バックアップファイルを調べたり扱ったりしやすい UI が不足している点にある
backup-directory-alist,kept-old-versions,kept-new-versionsなどのユーザーオプションで、バックアップの場所と保持数を調整できる- 外部パッケージ
backup-walkerは、バックアップをタイムトラベルのようにたどるインターフェースを提供する
-
VC インターフェース拡張
- Emacs 組み込みの VC パッケージは、バージョン管理されたファイルの過去バージョンを見るためのインターフェースを提供する
vc-diffはファイルを直前のバージョンまたは指定したバージョンと diff するvc-ediffはファイルの直前のバージョンまたは指定したバージョンに対して Ediff を実行するvc-revision-other-windowは、直前または指定した過去バージョンを現在のファイルの横に表示する- このインターフェースは Git 限定ではないが、バージョン管理されていないファイルでは動作しない
- 3 つの VC コマンドをオーバーロードすれば、未保存バッファ、バージョン管理ファイル、バージョン管理されていないファイルのバックアップをすべて「以前のバージョンと比較する」というモデルにまとめられる
- 未保存ファイルでは
vc-diffとvc-ediffがバッファとファイルを比較する - バージョン管理ファイルでは、元の
vc-diff,vc-ediff,vc-revision-other-windowがそのまま実行される - バージョン管理されていないファイルでは、最新番号のバックアップ、または接頭引数で選んだ番号のバックアップと比較または表示する
apropos 系
describe-keyであるC-h kは、キー入力が呼び出す関数を直接確認できるため、非常に便利なヘルプキーである- 2 番目に学ぶヘルプ機能としては
aproposが強力で、何を探せばよいかわからないときに Emacs の機能配置を把握する入口になる aproposは単一のコマンドではなく、apropos-library,apropos-function,apropos-command,apropos-variable,apropos-user-option,apropos-documentation,info-aproposなど、複数の専門検索コマンドのファミリーである- 例の設定では、これらのコマンドを
C-h a配下のキーマップに束ねてaproposを置き換えている which-keyのようなプロンプターがなくても、接頭キーC-h aの後にC-hを押せば使用可能なコマンド一覧を見られるcustomize-aproposは、検索語に一致するオプション、フェイス、グループを集めて、専用の customize バッファを作ってくれる
find-func ツール: M-x find-function-on-key, M-x find-function
- キーバインディングが気に入らない、または動作を知りたいとき、そのキーが呼び出すコマンドの定義へ移動すれば、その動作を読んだり修正したりできる
- 一般的な流れは、
describe-keyまたはC-h kでキーが呼び出すコマンドを確認したあと、sを押してソースへ移動するというものだ find-function-on-keyはこの 2 番目のステップを省き、キーバインディングから関数ソースへ直接移動する- 例の設定では、
help-mapのC-h M-kをfind-function-on-keyにバインドしている
copy-from-above-command と duplicate-dwim
- Emacs には最近、複数のユーザーがずっと以前から使っていたテキスト複製コマンドが追加された
copy-from-above-commandは、現在の行の上にある最初の空でない行からテキストをコピーし、Vim のC-yに近いduplicate-dwimは、現在の行またはアクティブリージョンを現在の行の下にコピーし、Vim のyy<N>pに近いcopy-from-above-commandは接頭引数の分だけ上の行から文字をコピーするが、例の advice ではC-u接頭引数を「上の行全体をコピーしてコメントアウトする」動作に変えている- 数値接頭引数
C-<N>を使えば、従来どおり上から指定した数の文字をコピーできる duplicate-dwimは複製後にカーソルを元の位置に置くか複製先に置くかを選ぶ必要があり、ユーザーオプションでこれを決められる- 例の設定では、
duplicate-region-final-positionとduplicate-line-final-positionを-1にして、カーソルとリージョンが複製されたテキストへ移動するようにしている
キー入力履歴をマクロにする: M-x kmacro-edit-lossage
- Emacs のキーボードマクロは、テキスト変換だけでなく、マウスクリックを含む Emacs のあらゆる操作シーケンスをキャプチャして再生できる
- キーボードマクロは強力だが、記録開始前に反復可能性を見込む必要があり、エラーのない一般化された操作を行わなければならないため、認知負荷が高い
- Vim の
.コマンドや Emacs のdot-modeパッケージは、編集の繰り返しという問題を和らげるが、完全なキーボードマクロとは守備範囲が異なる view-lossage(C-h l) は最近およそ 300 個のキー入力履歴を表示するkmacro-edit-lossageは、このキー入力履歴からいつでもマクロを作れるようにする- lossage は実際に編集可能なので、マクロ作成時に新しいコマンドを記録の中へ入れられる
- すでに定義したマクロは
edit-kbd-macro(C-x C-k e) でより頻繁に編集できるが、kmacro-edit-lossageは、まれな状況で今しがた行った複雑な作業を繰り返し可能にするのに役立つ - 一般化可能なマクロを作るには、
kbd-macro-query呼び出しを lossage に入れる必要があることが多い
subword-mode, superword-mode, 単語文法
- Emacs の単語ベースの移動・編集コマンドは、major mode ごとの syntax table を使っており、何を単語と見なすかはユーザーが調整できる
subword-modeでは CamelCase 記号の各構成要素が単語として扱われる- 例として
GtkWindowはGtkとWindow、EmacsFrameClassはEmacs,Frame,Class、NSGraphicsContextはNS,Graphics,Contextに分かれる superword-modeではthis_is_a_symbolのような snake_case 記号が 1 つの単語として扱われる- 実際の利用では
*-sexpコマンドによるシンボル操作がすでによくサポートされているため、superword-modeはsubword-modeより有用性が低い - major mode の syntax table を数分いじるだけでも、構造的移動で感じる不便を減らせる
- Lisp 系の文脈では、
:を単語構成文字にすると、:fooのようなキーワードをbackward-kill-wordで扱いやすくなる - Org mode では
=と~の区切り文字を単語構成文字として扱うように変更できる - 文字文法の指定方法は
describe-syntax(C-h s) とmodify-syntax-entryで確認できる
画像表示の操作
- Emacs が画像を表示するほぼすべての場所で、画像の上にカーソルを置いて
iを押すと表示を操作できる - Org mode の画像リンクプレビューや Elfeed の項目バッファ内の画像でも同じ操作を使える
i +とi -は拡大・縮小に便利で、i rは画像を 90 度回転するi cで画像を切り抜くこともでき、詳しいキーはM-x describe-keymap RET image-mapで見られる- ブラウザーや他のアプリケーションで慣れた
C-<wheel>ショートカットも使える repeat-modeを使えば、最初の呼び出しの後はi接頭なしで+,-,rだけを繰り返せる- この機能は画像上に置かれたキーマップとして提供され、別途有効化は不要である
- 操作されるのはディスク上の画像ファイルそのものではなく、表示状態 だけである
- ウェブページとレンダリング済み HTML バッファでは、
z(shr-zoom-image) が画像を複数行の横方向スライスに分け、サイズを順に切り替えることで、大きな画像表示の限界を和らげる
すべてのテキストを表示: M-x visible-mode
- Emacs はバッファ内のテキストを選択的に非表示にでき、この機能が Magit section、Outline mode、Org mode のような折りたたみ動作の基盤になっている
- 折りたたみ機能を提供するモードは通常、折りたたみ状態を切り替えるキーバインドを用意しており、
TABがたいてい機能する - モードごとのキーバインドを覚えるのが難しい、あるいは使う頻度が十分高くない場合は、
visible-modeですべての隠されたテキストを表示できる visible-modeはバッファ全体のテキスト不可視化を無効にし、再度実行すると以前の不可視状態を復元する- 動的な折りたたみ UI があるバッファでは、
visible-modeが有効な間は画面表示が崩れて見えることがある - この機能は一時的な対処やデバッグツールに近いが、1つのコマンドでバッファ内のすべてのテキストを一様に表示できる
見えないテキストを無視: isearch-toggle-invisible
- Isearch のような一部の Emacs コマンドは、デフォルトでテキスト不可視性を無視するため、実際の文書全体を簡単に検索できる
- 表示されているバッファ状態がナビゲーションの手がかりとして機能している場合、折りたたまれたテキストを自動で露出する検索は期待どおりに動かないことがある
- Isearch を検索よりもナビゲーションツールとして使うとき、折りたたまれた領域の一致箇所へ移動してしまうと問題になる
- Isearch 中に
M-s iにバインドされたisearch-toggle-invisibleで、見えないテキストを検索するかどうかを切り替えられる - 例では Org 文書の最後の見出しへ移動しようとして
zeroを検索したが、折りたたまれた領域の一致へ飛んでしまい、再検索しながらM-s iを押して表示されているテキスト内の一致だけをたどる - Isearch の動作切り替えキーは、
C-sの基本バインディングに対応するM-sキーマップの下にある
ルーラー: M-x ruler-mode
- Emacs には過去の WYSIWYG ワードプロセッシング機能の名残として、
center-*コマンドのような機能が残っている center-*コマンドは行、段落、リージョンをfill-column基準で中央揃えし、コードの装飾コメントのような用途に使える- 表示 margin と fringe の幅は多くの機能を詰め込める画面領域だが、表示 margin の幅を直接変える作業は簡単ではない
set-left-marginとset-right-marginは表示 margin の幅を変えるコマンドではなく、実際のバッファテキストを字下げするという点でcenter系コマンドのように動作する- 表示 margin の設定には直接的なコマンドがなく、ウィンドウが再表示されるまで効果が反映されないという問題もある
ruler-modeを有効にすると、header-line 上のツールチップで使い方を確認できるS-<mouse-1>とS-<mouse-3>でバッファの左・右 margin を設定できる<mouse-2>のドラッグでfill-columnも設定できる- プリセット幅を切り替えるのではなく、その場で margin を変えたいなら、
visual-fill-columnやolivettiのようなパッケージよりruler-modeのほうが使いやすいかもしれない
テキストを再充填: M-x refill-mode
- Emacs はテキストを整形するためのさまざまな
fill-*コマンドと、入力中の改行を処理するauto-fill-modeを提供している auto-fill-modeは Emacs チュートリアルの早い段階で扱われるほど、テキスト整形を重要な編集機能として位置づけているauto-fill-modeは実際には完全自動ではなく、現在の行だけを折り返し、貼り付けなどで生じた前の段落の乱れは手動で直す必要があるrefill-modeは文書がfill-columnに合うよう維持する、Emacs の実質的な自動テキスト整形機能であるM-x refill-modeを実行するとその動作を使える
すべてのウィンドウを一緒にスクロール: M-x scroll-all-mode
scroll-other-windowは選択されていない別ウィンドウを切り替えずにスクロールでき、現在のウィンドウで作業しながら次のウィンドウの参考資料を見るときに便利であるfollow-modeは 1 つのバッファを複数のウィンドウにまたがって連続表示する機能であるscroll-all-modeはあまり知られていないが、フレーム内のすべてのウィンドウを同時にスクロールする- 同期させて見比べたいバッファを確認するときに便利で、例では Ediff セッションに入らずにファイルの 2 つの版を目視で比較するのに使われている
- 例の流れは、現在のファイルの特定の過去バックアップを
vc-revision-other-windowで開き、scroll-all-modeを有効にしたあと、普段どおりスクロールするとすべてのウィンドウが同時に動くというものだ -
他ウィンドウのスクロールと
master-mode- 画面にウィンドウが 2 つより多くあり、スクロールしたいウィンドウが Emacs の選ぶ
next-windowでない場合、問題が起きることがある - 組み込みの
master-modeは、別バッファからスクロールできるバッファをあらかじめ指定したり、その場で指定したりできるようにする - より即効性のある方法は、スクロール対象ウィンドウを見つける戦略を設定することだ
(setq other-window-scroll-default #'get-lru-window)は常に最も長く使われていないウィンドウをスクロールする- 参考資料が入っていて、ほとんど選択しないウィンドウをスクロールしたいときにこの方法は有効である
- 頻繁に編集する 2 つのウィンドウが複数ウィンドウの中にあるなら、最も最近使ったウィンドウを他ウィンドウスクロールの対象にするラムダ関数を設定できる
- こうした設定の組み合わせは、
scroll-other-windowが意図したウィンドウをスクロールする助けになる
- 画面にウィンドウが 2 つより多くあり、スクロールしたいウィンドウが Emacs の選ぶ
終了拒否: M-x emacs-lock-mode
- 未保存のファイルがあると、Emacs は各ファイルをどう処理するかに答えるまで終了を拒否する
emacs-lock-modeはこの考え方を拡張し、ユーザーが任意のバッファをロックできるようにする- ロックが解除されるまで、そのバッファは kill を拒否し、
Buffer "*scratch*" is locked and cannot be killedのようなメッセージを出す - ロックされたバッファがあると Emacs も終了を拒否し、
Emacs cannot exit because buffer "*scratch*" is lockedのようなメッセージを出す - ファイルを訪問していないバッファに入っている情報を誤って失わないようにしたり、そのバッファに作業が残っていることを思い出させたりするのに役立つ
- Org-capture 以後、前者の問題はまれになったが、shell・compilation バッファ、Web サイト、その他の特殊アプリケーションの出力や状態を失わないための用途としては依然有用である
フレームを復元: M-x undelete-frame-mode, M-x undelete-frame
- 丹念に構成した Emacs フレームを誤って閉じたとき、
undelete-frameで復元できる - この機能を使うには
undelete-frame-modeを有効にしておく必要がある - 組み込みの
winnerやtab-bar-historyがウィンドウに対して提供する機能を、フレームを対象に行う undelete-frame-modeを Emacs と一緒に有効にしておけば、フレームを閉じることをそれほど心配しなくて済む- 削除されたフレームは最大 16 個まで復元できる
残った機能と除外された機能
- 過去 6 年間で出会った機能のうち、2026 年の Emacs 利用の現実の中で生き残った機能は 20 個である
- 偶然見つけた多くの Emacs ライブラリは、一般ユーザーの要求に対する安定した解決策というより、考古学的な興味のほうが大きかった
allout-modeは Org mode に似た平行世界の outline 管理機能で、Org の speed-key やサブツリー単位の暗号化のような機能を備えているshadowfileは Emacs 内でunisonを実装するが、その有用性には疑問があるdouble-modeはquailに先行する、キー変換ベースの非キーボード文字入力方式であるbsライブラリは、より賢いlist-buffersコマンドを作ろうとした試みだったが、ibufferのほうが優れているため使う理由がなくなったelectric-pair-modeによるリージョンを区切り文字で囲む機能のように、表面的には有用でも扱いの難しさに見合う価値が低い機能は除外された- この種の用途には
wrap-region、smartparens、embraceのような外部パッケージのほうが優れている apptのような Org および Org 周辺の組み込みライブラリは興味深いが、別記事で扱うに値するほど範囲が広いthunkのように主に Elisp 開発者に役立つライブラリも、別途整理が必要である- Emacs に同梱される
lispディレクトリはそれほど大きくないが、有用な標準機能は今後も発見の余地がある
1件のコメント
Lobste.rsの意見
find-file(C-x C-f)で*foo*.txtのように ワイルドカードで複数ファイル を開くのはたいていミスなので、ワイルドカードを使ったらfind-fileがすぐdiredを開くようにfind-file-noselectにadvice-addを仕込んでいるfile-expand-wildcardsの結果が2件以上のときはdired-noselectに渡し、そうでなければ元のfind-file-noselectを呼ぶ方式ruler-modeは本当に面白い。Emacs にこんな WYSIWYG機能 があるとはまったく知らなかったし、Emacs は本当に変わっていて楽しいソフトウェアだ普通の Emacs だけを使いながら、ほとんど見尽くしたと思っていたのに、まだ発見できるものがずっと多かった。
ruler-modeは文章を書く用途としてかなり良い以前は Magit をずっと多用していたが、今は組み込みの
vc-modeとdiffツールに移行しており、どちらもとてもよく動くので満足しているこういう記事は好きだ。Emacs や Neovim のような複雑でカスタマイズ可能なエディタを使うとき、標準のエディタが何をできるのか理解する前に、肥大化したディストリビューション を先に入れてしまい、あまりにも早く走り出してしまうことが多い
時間があるなら、マニュアルを読んで最初から自分で設定を積み上げていく過程はかなりやりがいがある。あまり知られていない Emacs の関数に
finder-list-keywordsがあり、実行すると見つけにくい Emacs の機能を探せるメニューが出てくる。たとえば、組み込みゲームが 24個 もあるのを知っていただろうか?