Help us understand the problem. What is going on with this article?

NTEmacs + cygwin or msys2 で exec-path-from-shell

More than 3 years have passed since last update.

exec-path-from-shell

exec-path-from-shell (https://github.com/purcell/exec-path-from-shell) は、GUI での起動時に、指定した環境変数をシェルから引き継いでくれます。楽チンです。
詳細は以下のリンクを参照
http://qiita.com/catatsuy/items/3dda714f4c60c435bb25
http://syohex.hatenablog.com/entry/20130718/1374154709

ただし、windows はサポートしてないし、そのままでは動きません。ですが、NTEmacs と cygwin/msys2 を楽して連携したいので、それを何とかしてみます。

以下の環境で検証

  • Windows 7、msys2、NTEmacs 24.5.1、exec-path-from-shell melpa の最新版

パスの形式の問題

cygwin/msys2 のシェルで扱うパスは unix 形式であり、cygwin or msys2 の環境変数もそうなっています。一方、NTEmacs は WIN32 アプリケーションのため unix 形式のパスは読み込めません。exec-path-from-shell がうまく動かない問題はこれが原因です。よって、 unix 形式のパス → windows 形式のパスのように変換できればいいわけです。

cygpath

cygwin/msys2 には unix 形式のパス と windows 形式のパスを相互に変換する cygpath コマンドがあります(詳細は以下のリンク参照)。
http://takuya-1st.hatenablog.jp/entry/20110910/1315644196

このリンク先には紹介されていませんが、-p オプションを使うと、環境変数で使われるパスのリストを一気に変換してくれます。

$ cygpath -amp "/bin:/usr/bin" # unix 形式のパスリスト
D:/msys64/usr/bin;D:/msys64/usr/bin # windows 形式のパスリスト

$ cygpath -aup "D:/msys64/usr/bin;D:/msys64/usr/bin" # windows 形式のパスリスト
/usr/bin:/usr/bin # unix 形式のパスリスト

よって cygpath を NTemacs から実行すればうまくいきそうです。

NTEmacs の設定

以上を踏まえて、init.el あたりに以下を設定すればいいようです。
注1) bash と cygpath のフルパスは各自の環境にあわせて変更してください
注2) cygwin でもおそらく動きますが、msys2 の設定部分はコメントアウトなりしてください
注3) NTEmacs 24.3 以前を使用している場合 新 advice は動作しないので 旧 advice に書き直しが必要。

init.el
(setq shell-command-switch "-c")

;; シェルからの起動では exec-path-from-shell を実行しない
(let ((shell-level (getenv "SHLVL")))
  (when (or (not shell-level) (string= "0" shell-level))
    (when (eq system-type 'windows-nt)
      ;; bash のフルパスを指定
      (setq shell-file-name "d:/msys64/usr/bin/bash")
      (defvar explicit-shell-file-name)
      (setq explicit-shell-file-name shell-file-name)
      (setenv "SHELL" shell-file-name)

      ;; msys2 のみの設定 mingw64 とパスを共有
      (setenv "MSYSTEM" "MINGW64")

      ;; 環境変数 PATH のときのみパスの変換を実行
      (defun ad-exec-path-from-shell-setenv (orig-fun &rest args)
        (when (string=  (car args) "PATH")
          (setf (nth 1 args)
                (with-temp-buffer
                  (call-process "d:/msys64/usr/bin/cygpath" nil '(t nil) nil "-amp" (nth 1 args))
                  (unless (bobp)
                    (goto-char (point-min))
                    (buffer-substring-no-properties (point) (line-end-position))))))
        (apply orig-fun args))
      (advice-add 'exec-path-from-shell-setenv :around 'ad-exec-path-from-shell-setenv))

    ;; 引き継ぎたい環境変数を列挙
    (exec-path-from-shell-copy-envs '("PATH" "MANPATH" "PKG_CONFIG_PATH"))))
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away