macOSのEmacsでmigemoやagが動かなかった話

Page content

実行環境

  • macOS Big Sur 11.1
  • Emacs 27.1

起こった問題: migemoやagが動かない

Emacsの C-s (i-search) で migemo が動作する様に普段設定していますが、気がついたらこれが動かなくなっていました (勝手に壊れた…) 。具体的には cmigemo not found というエラーが出てしまいます。あるいは以下のEmacs Lispを実行してもエラーが出ます。

(setq migemo-command "cmigemo")
(migemo-init)

さらに、not foundというエラーで動かないのは migemo だけではなく、 M-x ag でも ag not found のエラーが出ます。なお、 cmigemoag 自体は Homebrew/usr/local/bin 以下に導入済です。

原因

理由は良くわかりませんが、デスクトップからEmacsを起動した際に、 /usr/local/bin が環境変数 PATH に入っていませんでした。 ag や cmigemo を Homebrewでインストールする場合には /usr/local/bin 以下にインストールされるため、これを PATH に追加する必要があります。以前は正常に動作していたので、macOSをBig Surに更新した前後で設定がおかしくなったのかもしれません。

なお、Emacsからは (getenv "PATH") で環境変数 PATH の値を取得したり、 変数 exec-path を評価することでEmacsが実行ファイルを探してくれるディレクトリのリストを確認したりすることができます。

解決法

解決策は、要するに /usr/local/bin が 環境変数 PATHexec-path に入っていない場合に追加すれば良いです。何も考えずに追加しても良いですが、既に /usr/local/bin がこれらに入っている場合に追加するのはあまり綺麗ではないので、一応 /usr/local/bin が含まれているかどうかを事前に確認しています。

以下が全体のコードになります。

(if (not (string-match "\\(^\\|:\\)/usr/local/bin\\($\\|\\:\\)" (getenv "PATH")))
    (setenv "PATH" (concat '"/usr/local/bin:" (getenv "PATH"))))
(if (not (member "/usr/local/bin" exec-path))
    (setq exec-path (cons "/usr/local/bin" exec-path)))

環境変数 PATH について

環境変数 PATH について、まず始めに getenv で取得できる PATH の値に /usr/local/bin が含まれているかどうかを string-match で調べます。ここで微妙に複雑な正規表現を使っていますが、これは例えば /usr/local/bin/foo//bar/usr/local/bin/ の様な似て非なるディレクトリとマッチするのを防ぐためです (あんまりそういうこともないかと思いますが念のため)。

(string-match "\\(^\\|:\\)/usr/local/bin\\($\\|\\:\\)" (getenv "PATH"))

環境変数 PATH/usr/local/bin を含んでいない場合、以下の様に setenv で環境変数 PATH の値を更新します。

(setenv "PATH" (concat '"/usr/local/bin:" (getenv "PATH")))

Emacsの変数 exec-path について

Emacsの変数 exec-path についても環境変数 PATH の場合と同様に /usr/local/bin が含まれているかどうかを調べて、含まれていない場合には追加します。 exec-path の場合は文字列ではなくリストなので単に member を使って /usr/local/bin が含まれているかどうかを判定できます。

(member "/usr/local/bin" exec-path)

exec-path/usr/local/bin を含んでいない場合、以下の様に setq で値を更新します。

(setq exec-path (cons "/usr/local/bin" exec-path))

結果

Emacsが無事 /usr/local/bin 以下にあるプログラムを見つけてくれる様になったので、ちゃんと動く様になりました!

参考

4.3 Creating Strings
https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Creating-Strings.html
5.7 Using Lists as Sets
https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Sets-And-Lists.html
34.4 Regular Expression Searching
https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Regexp-Search.html