補完機能によるEmacs体験の向上

マーティン・ファウラー:2024年1月25日

私は長年Emacsを使用しており、ウェブサイトへの記事執筆、書籍執筆、そしてプログラミングの大部分をEmacsで行っています。(JavaにはIntelliJ IDEA、RにはRStudioを使用しているのは例外です。)そのため、ここ数年でEmacsの機能を向上させる多くの活動が見られ、進化の袋小路という印象が薄れてきたことは喜ばしいです。私のEmacs体験を最も向上させた改善点の1つは、補完リストに正規表現を使用することです。

多くのEmacsコマンドは、選択できるアイテムのリストを生成します。ファイルを訪問(開く)する場合、ファイルを探すためのキーコンビネーションを入力すると、Emacsはミニバッファ(コマンドと対話するための特別な領域)に候補ファイルのリストを表示します。これらのファイルリストは、特に現在のプロジェクト内のすべてのファイルのリストを要求した場合、非常に長くなる可能性があります。

目的のファイルを指定するには、リストをフィルタリングするためのテキストを入力できます。例えば、articles/simple/2024-emacs-completion.mdというファイルを開きたい場合、emacsと入力できます。そのファイルだけを絞り込む必要はなく、リストを十分に絞り込めれば十分です。

特に役立つ正規表現ビルダーのスタイルがあり、それはスペースで正規表現を区切ります。これにより、ファイルパスに「articles」と「emacs」が含まれるファイルパスのリストを取得するために、articles emacsと入力できます。これは基本的に文字列「articles emacs」を正規表現\\(articles\\).*\\(emacs\\)に変換します。さらに良いことに、このようなマッチング方式では、正規表現の順番を任意に変更できます。そのため、「emacs articles」もマッチします。このように、最初の正規表現がフィルタリングされたリストを表示すると、2番目の正規表現を使用して目的のものを選択できます。区別する正規表現が最初の検索よりも前であってもです。

このような補完マッチングをインストールすることで、コマンドと対話する際に大きなリストをフィルタリングすることが非常に簡単になり、Emacsの使用に大きな影響を与えました。その最も重要な影響の1つは、すべての対話型Emacs関数のリストを表示するキーコンビネーションであるM-xの使用方法が変化したことでしょう。正規表現マッチャを使用してリストをフィルタリングすることで、数回のキーストロークだけで、その名前を使用してEmacsコマンドを呼び出すことができます。これにより、キーボードショートカットを覚える必要がなくなります。これにより、あまり使用しないコマンドをM-xを使用して呼び出します。開いているバッファのリストを頻繁に表示するわけではないので、そのためのキーコンビネーションを覚える代わりに、M-x ibと入力すると、ibufferがすぐに表示されます。私がM-xに使用しているコマンド(counsel-M-x)は、正規表現の先頭に「^」を挿入し、最初の正規表現を行頭に固定します。自作の関数はすべてmf-で始まるようにしているので、名前が長くても自分の関数を簡単に検索できます。URLからドメインを削除するコマンドを作成しましたが、mf-url-remove-domainと呼び、M-x mf urlで呼び出すことができます。

Emacsには、この種のマッチングを行うパッケージがいくつかあり、やや混乱するほどです。私が現在使用しているのはIvyです。デフォルトでは、スペース区切りの正規表現マッチャを使用しますが、順序をサポートしていません。自分の好みに合わせて設定するには、以下を使用します。

(setq ivy-re-builders-alist '((t . ivy--regex-ignore-order)))

Ivyは、この種の選択を強化するさまざまなコマンドを含むcounselというパッケージの一部です。

Ivyはこの種の処理を行う唯一のツールではありません。実際、Emacsの補完ツールの世界は、重複と相互作用が多く、私にはよく理解できないため、非常に混乱しています。この分野のツールには、HelmcompanyVerticoConsultなどがあります。Understanding Minibuffer Completionという記事がMastering Emacsにありますが、そこで説明されているメカニズムがIvyの機能とどのように適合するかは説明されておらず、まだそれを理解する時間を取っていません。

そして、一般的な注意として、この素晴らしいツールの使い方を学ぶために、Mastering Emacsという本を強くお勧めします。Emacsには非常に多くの機能があるため、私のような数十年のベテランユーザーでも、「こんなこともできるなんて知らなかった」という瞬間がありました。

興味のある方のために、私のEmacs設定の関連部分を以下に示します。

(use-package ivy
  :demand t
  :diminish ivy-mode
  :config
  (ivy-mode 1)
  (counsel-mode 1)
  (setq ivy-use-virtual-buffers t)
  (setq ivy-use-selectable-prompt t)
  (setq ivy-ignore-buffers '(\\` " "\\`\\*magit"))
  (setq ivy-re-builders-alist '(
                                (t . ivy--regex-ignore-order)
                                ))
  (setq ivy-height 10)
  (setq counsel-find-file-at-point t)
  (setq ivy-count-format "(%d/%d) "))

(use-package counsel
  :bind (
         ("C-x C-b" . ivy-switch-buffer)
         ("C-x b" . ivy-switch-buffer)
         ("M-r" . counsel-ag)
         ("C-x C-d" . counsel-dired)
         ("C-x d" . counsel-dired)
         )
  :diminish
  :config
  (global-set-key [remap org-set-tags-command] #'counsel-org-tag))

(use-package swiper
  :bind(("M-C-s" . swiper)))

(use-package ivy-hydra)