そもそもOS XでEmacs.appをインストールしているのにMewを~配下にインストールしないといけない理由がわからないという人もいるかもしれませんが、Emacs.appにmewを混ぜたくないがあまり適当なディレクトリがない、というわけで、私はHomebrewでインストールしたEmacs.appと~配下に野良ビルドしたMewという組み合わせでメールを読み書きしています(2013年11月10日訂正・現在ではMewを使っていません)。
ところで、何も考えずにこの組み合わせでMewを使うと、~/bin配下にインストールしたバイナリを呼び出す必要があるときに「mewl: command not found」などのエラーに遭遇してしまうことがあります。これは、launchdから引き継いだPATH
をEmacs.appが(事実上)そのまま使ってしまうためです。
(Emacs.appはbash等を経由して起動されるわけではないため、PATH
を変更できるよいタイミングがありません。/etc/launchd.confを修正しても目的は達成できるのですが、/etc/launchd.confのsetenv PATH
行に~配下のパスを書き加えるのは抵抗がありますので、私はこの方法を採用しませんでした。なお、launchdは~/.launchd.confを読みません)
つまり問題は「Emacsにコマンドサーチパスを追加するにはどうしたらよいか」なのですが、
この問題を解決するには、~/.emacs.d/init.el等に以下のコードを入れるのがよいようです。
(if (file-directory-p (expand-file-name "~/bin"))
(progn
(add-to-list 'exec-path (expand-file-name "~/bin"))
(let ((exec-path (reverse (cdr-safe (reverse exec-path)))))
(setenv "PATH" (mapconcat 'identity exec-path path-separator)))))
関数add-to-list
は第1引数(ここではexec-path
。関数実行前に展開されないようquote
し、シンボルとしておく)の要素に第2引数(ここでは~/binをexpand-file-name
したもの)がない場合に限り第1引数のリストに第2引数を追加するという挙動を示します。
exec-path
に~/binが追加されたら、Emacs.Appの子プロセスからも使えるように環境変数PATH
をexec-path
に合わせます(exec-path
はもともとPATH
の値をもとに設定されます)。それがsetenv
行で、setenv
の第2引数に対しexec-path
を「:」でmapconcat
した結果を返しますが、mapconcat
それ自体は関数に対して引数を渡す関数なので、引数をそのまま返すだけの関数であるidentify
を介すことでsetenv
を成立させています。
(2012年11月6日修正)exec-pathをそのまま使うとEmacsのlibexecディレクトリ(HomebrewでEmacs 24.1を入れたOS X 10.8の場合は/usr/local/Cellar/emacs/24.1/libexec/emacs/24.1/x86_64-apple-darwin12.2.0)もPATHに含まれてしまうため、let
で束縛したexec-path
をreverse
で一旦逆さにしてから最初の要素だけを排除(cdr
)し、再度reverse
することで順序をもとに戻したものを設定し、PATH
の生成に利用しています。また、path-separator
を使いました。