精简版的exec-path-from-shell(13loc)

MacOS上的Emacs除非从终端启动,否则不读在shell里设置的环境变量。我看了一下一般的解决方案似乎是使用purcell的exec-path-from-shell或者像doom一样在终端bootstrap时把环境变量写到一个文件里再每次读取,或者手动设置。

因为我不希望为了拿到一个环境变量多装一个包,也不希望在我的配置目录里留一个env文件,更不希望在我的配置里硬编码一堆PATH,所以就写了一个非常简短的函数。

(defun environment-update ()
  (interactive)
  (let* ((shell (or (getenv "SHELL") "/bin/sh"))
         (command (format "%s -l -c 'env'" shell)))
    (with-temp-buffer
      (call-process-shell-command command nil t)
      (goto-char (point-min))
      (while (re-search-forward "^\\([^=]+\\)=\\(.*\\)$" nil t)
        (let ((key (match-string 1))
              (val (match-string 2)))
          (when (string-equal key "PATH")
            (setenv key val)
            (setq exec-path (split-string val path-separator))))))))

如果你安装的没有启用延迟加载的包不会调用那些不在标准PATH(一般是/usr/bin/usr/local/bin)里的可执行文件,为了加快你的Emacs的GUI弹出的速度,你还可以:

(add-hook 'after-init-hook #'environment-update)
6 个赞

好用吗?有没有什么缺点

我的解决方案:不关终端,就从终端启动

1 个赞

我只用 7 行,首先我只利用 macOS path helper 特性管理 PATH 变量,而不是靠乱七八糟的改 shell profile。byte compile 后持久化完全没有需要启动外部进程的性能损失。

1 个赞

不用「乱七八糟」地改shell profile吧。比如我的~/.zprofile长这样:

export LANG="en_US.UTF-8"

alias emacs=/Applications/Emacs.app/Contents/MacOS/emacs
alias mpv=/Applications/Mpv.app/Contents/MacOS/mpv

source ~/.zsh/zsh-autosuggestions/hint.sh

然后也能拿到比如说/etc/paths.d/10-pkgsrc下面的PATH。

(而且PATH增加之后也不需要重新byte compile)

如果你用的是正常的shell,比如zsh这些,我感觉是没有。

因为 zsh 和其他 POSIX shell 一样都会 source /etc/profile,macOS 上默认已经配置好了调用 path_helper,而 path_helper 也无非就是把 path 配置变成能用 shell eval 的格式。知道这些原理,本身不用 HOME 里的 shell profile 配置 PATH 变量,就根本没必要用启动 shell 这种弯路。

我自己配置文件的总体思路是尽可能利用 byte compile,同样的代码,没有经过 byte compile 会有宏展开之类的因素导致额外的 gc 调用。

有道理。

就是有些聪明的包管理器(点名opam)会在~/.zshrc里添加PATH,需要自己写对应的/etc/paths.d

我倒是没想到过byte compile配置文件,我试试。

直接raycast一类的启动器,配置个脚本,open emacs就好了,更省事。。。