exec-path和$ PATH


28

我在网上看到了一些示例,其中人们使用以下命令将路径添加到Emacs中的默认路径:

(add-to-list 'exec-path "/usr/local/bin/")

我是Elisp的新手,我想我了解上述声明的功能,但是我有几个问题:

  • Emacs 以什么顺序搜索执行路径?例如,它是否完全考虑$PATH(env。variable)的值(如果是,则在它之前或之后exec-path?)

  • 如何设置多个此类路径?我可以继续串联它们吗?例如

    (add-to-list 'exec-path "PATH1", "PATH2")
    

    还是我应该做:

    (add-to-list 'exec-path "PATH1:PATH2:PATH3") 
    

我还在GitHub上找到了这个有趣的包:exec-path-from-shell。为什么需要为此包装?

动机

有没有发现命令在您的Shell中有效,但在Emacs中无效?

这在OS X上经常发生,在OS X上,从GUI启动的Emacs实例继承了一组默认的环境变量。

这个库的工作原理是通过从用户的shell复制重要的环境变量来解决此问题的:它通过要求shell打印出感兴趣的变量,然后将其复制到Emacs环境中来工作。


3
欢迎来到Emacs和Elisp!我自己对这个话题仍然很新鲜,不知道您的问题的答案,但是我想我要提到的是使生活变得简单得多的东西:describe函数。例如(describe-function 'add-to-list)C-h f)将为您提供该add-to-list功能的文档以及到源的链接。还有(describe-variable 'exec-path)C-h v)。这并不是要成为RTFM评论-这些文档并不能回答您列出的所有问题,只是有用的东西。
jtmoulia 2014年

谢谢@jtmoulia!对于以后的问题,我一定会牢记在心。
Amelio Vazquez-Reina

除之外C-h v exec-path,请使用手册(Emacs和Elisp)。在手册中,i exec-path可为您提供有用的解释。首先询问Emacs-您不会后悔的。
德鲁

Answers:


23

1)PATHexec-path

Emacs确实exec-pathPATH启动时的值开始设置,但以后将不再查看。但是,如果您运行命令,它将继承PATH而不是exec-path,因此子进程可以找到与Emacs不同的命令。

正如Francesco所说,这可能会特别令人困惑shell-command,因为它不会直接运行进程,而是调用Shell运行它,它将使用PATH而不是exec-path

2)添加多个路径 exec-path

只需add-to-list反复致电:

(add-to-list 'exec-path "PATH1")
(add-to-list 'exec-path "PATH2")

请注意,这add-to-list会添加到列表的开头,因此最终会出现"PATH2"exec-pathbefore之前"PATH1"

您还可以对列表使用更多的“低级”访问权限:

(setq exec-path (append '("PATH1" "PATH2")
                        exec-path))

这将增加"PATH1""PATH2"你的exec-path,按照这个顺序。

3)Mac OS的路径

Mac OS X上的问题是,当您从全局UI或从外壳程序调用程序时,Mac OS不会将环境设置为相同。这意味着从外壳程序运行Emacs会导致设置与从finder中运行环境变量不同的环境变量。如果将环境变量设置为in .bashrc或类似值,这会特别烦人,因为这不会影响“全局” Emacs。

该软件包显然启动了一个shell并从那里导入环境变量,从而模拟了您在全局启动的Emacs中从shell获得的环境。


谢谢乔根。关于问题3:您是否偶然知道PATH从全局UI(桌面环境)启动的程序的默认定义在哪里?我PYTHONPATHelpy:)中遇到了同样的问题。当我从桌面启动Emacs时,Emacs并不知道我PYTHONPATH.zshenv文件(用于的初始化文件zsh)中的定义,这非常令人沮丧,因为elpy不知道在哪里可以找到我的Python包。我很高兴将这些PYTHONPATH定义移到另一个Shell init文件中(尽管理想情况下,我希望Emacs使用我的定义.zshenv
Amelio Vazquez-Reina

恐怕我对Mac OS X并不太了解。一个快速的Google引导我前往stackoverflow.com/questions/135688/…,这似乎表明launchd.conf是正确的地方。如果您需要的只是Emacs,则当然可以同时在exec-pathPATH中进行设置.emacs。您可以PATH使用设置(setenv "PATH" (format "%s:%s" "/new/path/element" (getenv "PATH")))
JorgenSchäfer2014年

谢谢。我知道以下是问答发散从OP了一点,但有什么办法在Emacs到指定PYTHONPATHelpy应该使用?
阿梅利奥·瓦兹克斯·雷纳

您可以修改process-environment,例如使用setenv。您可以在中进行此操作elpy-mode-hook,但这是一个globsl变量,将其设置为局部缓冲区很容易导致混乱的行为。
约尔根·舍费尔

9

当emacs使用诸如call-process或的原始函数启动新的外部过程时start-process,将在exec-path(而不是$PATH)中搜索可执行文件。

但是,诸如shell-command将外壳作为子进程启动并将其传递给您要运行的命令的功能。为了执行此命令,shell将尝试在中$PATH(而不是中exec-path)查找可执行文件。

因此,exec-path最重要的是由emacs本身启动的外部进程,最重要的$PATH是您使用更高级别的功能运行自己的命令(M-!例如,使用)


如果要将多个目录添加到中exec-path,则应使用 add-to-list多次。

您可以手动完成

(add-to-list 'exec-path "dir1")
(add-to-list 'exec-path "dir2")

或使用循环

(dolist (dir '("dir1" "dir2"))
  (add-to-list 'exec-path dir))

关于您的第三个问题,如果emacs是从桌面环境启动的,它会从中继承环境,这可能不如完整外壳程序那么完整。

这意味着有时可能需要$PATH使用常规shell 来完成Emacs的价值。这就是exec-path-from-shell您提到的库的目的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.