ivy/swiperをmigemo化した際に遭遇したエラーの解決と新たなminor-modeの提案

はじめに

avy-migemoを使わずにswiperやswiper-isearchをmigemo化することに成功した偉大な先人がいる:

これらの記事では、ivyに食わせるmigemo的な正規表現を生成する関数を独自に定義している。
そして、これらの設定を適用したのち、swiper-isearchを実行したところ、以下のエラーに遭遇した。

Error in post-command-hook (ivy--queue-exhibit): (invalid-regexp "Unmatched ) or \\)")

この原因は以下の設定をしていたことにあった:

 (setq search-default-mode #'char-fold-to-regexp)

そこで以下のように修正することで、エラーは解消され、件のmigemo化が実現できた。

 (setq search-default-mode nil)

毎回、search-default-modeを評価しなおすのも手間なので、オリジナルのminor-modeを作ることにした。
このminor-modeの紹介が本記事の主旨である。

作成したminor-modeおよび使い方

以下のivy-with-migemo-modeである。

コードを表示する

本minor-modeを有効化することで、swiperやswiper-isearchでmigemoが使えるようになる。すなわち、有効化されている間はsearch-default-modenilに設定される。

(require 'ivy-with-migemo)
(setq ivy-with-migemo-enable-command
      '(swiper swiper-isearch))
(global-ivy-with-migemo-mode 1)

上記、ivy-with-migemo-enable-commandという変数が、migemoを使う対象となるコマンドを格納するリストである。counsel-recentfを対象に追加する場合は、以下の設定にする。

(setq ivy-with-migemo-enable-command
      '(swiper
        swiper-isearch
        counsel-recentf))

無効化する場合は、C-u -1 M-x global-ivy-with-migemo-modeとすればよい。もしくは

(global-ivy-with-migemo-mode -1)

を評価する。

バッファローカルで有効・無効を切り替える場合は、global-ivy-with-migemo-modeによる有効化を使わず各バッファごとにM-x ivy-with-migemo-modeとする

もしcounsel-agやcounsel-rgも併せて使う場合は以下の設定を試してみるとよい。ただしripgrepは最新版のソースコードをダウンロードしてコンパイル/インストールしておくこと。複数ファイルの串刺し検索がmigemoで実現できるので、とても快適である。

(require 'ivy-with-migemo)
(setq ivy-with-migemo-enable-command
      '(swiper swiper-isearch counsel-rg counsel-ag))
(setq migemo-options '("--quiet" "--nonewline" "--emacs"))
(migemo-kill)
(migemo-init)
(global-ivy-with-migemo-mode 1)

補足

ivyインターフェイスを持つコマンドに対してmigemoを有効化するためのパッケージとしては、すでにivy-migemoが存在する。

このパッケージも同様の機能を提供するが、search-default-modeの設定には踏み込んでいない。さらにmigemo化のON/OFFには専用のtoggleコマンドを用意しており、minor-modeは用意されていない点も異なる。もっとも、toggleコマンド自体は良いインターフェイスであると思う。またivy-migemoではfuzzyマッチングも利用でき、ユーザによっては嬉しい点である。以上がivy-migemoivy-with-migemo-modeとの違いである。

追記 4/23

最近の変更により、ivy-migemoにもsearch-default-modeへの対応が入ったようである。かなり使いやすく整備されており、おすすめできる。

追記

ivy-with-migemo-modeをきれいに整形し、githubリポジトリを登録した。
名前はswiper-migemoに改めた。