如何在emacs中将环境变量设置为缓冲区局部范围

如何在emacs中将环境变量设置为缓冲区局部范围,emacs,elisp,Emacs,Elisp,在Emacs中,我希望在不同的缓冲区中改变环境变量的值 我的emacs环境取决于环境变量(flymake、compile等),但是我希望能够在一个emacs会话中同时打开多个项目,但是这些项目可能有冲突的环境 例如,flymake的不同INCLUDE_PATH环境变量。一种解决方案是在生成外部命令时临时更改环境。该命令将继承当前环境。请记住,Emacs是一个单踏板应用程序,因此我们不必担心比赛条件等 您可以从以下两种方法中选择一种: 1) 编写自己的函数,如my compile,临时更改环境并调

在Emacs中,我希望在不同的缓冲区中改变环境变量的值

我的emacs环境取决于环境变量(flymake、compile等),但是我希望能够在一个emacs会话中同时打开多个项目,但是这些项目可能有冲突的环境


例如,flymake的不同INCLUDE_PATH环境变量。

一种解决方案是在生成外部命令时临时更改环境。该命令将继承当前环境。请记住,Emacs是一个单踏板应用程序,因此我们不必担心比赛条件等

您可以从以下两种方法中选择一种:

1) 编写自己的函数,如
my compile
,临时更改环境并调用普通的compile命令


2) 修改低级流程功能,并确保它们相应地修改环境。通常,您可以使用
defadvice

执行此操作。我将以下内容放在
.dir locals.el
树的根目录中,我希望在其中定义一些环境变量:

;; variables local to this directory and its children
((nil . ((eval . (setenv "SOME_VARIABLE" "TRUE")))))

这将在您第一次打开该目录树中的文件时发出警告。接受后,将为您在其中打开的每个缓冲区定义给定的环境变量。

您可以通过将
流程环境设置为本地缓冲区来实现这一点:

(defun setup-some-mode-env ()
  (make-local-variable 'process-environment)
  ;; inspect buffer-file-name and add stuff to process-environment as necessary
  ...)
(add-hook 'some-major-mode 'setup-some-mode-env)
一个更详细的示例是导入由外部脚本创建的Guile环境设置的代码。脚本被设计为在shell中“源代码”,但在这里它的结果被导入到单个Emacs缓冲区中:

(defun my-guile-setup ()
  (make-local-variable 'process-environment)
  (with-temp-buffer
    (call-process "bash" nil t nil "-c"
          "source ~/work/guileenv; env | egrep 'GUILE|LD_LIBRARY_PATH'")
    (goto-char (point-min))
    (while (not (eobp))
      (setq process-environment
        (cons (buffer-substring (point) (line-end-position))
          process-environment))
      (forward-line 1))))

(add-hook 'guile-hook 'my-guile-setup)
可以对这些变量使用动态绑定

动态绑定和动态范围有点难以解释,有关解释请参见和
。优点是这些设置只影响正在运行的进程,一旦进程结束,它们就会消失。在本例中,我设置了timzezone环境变量,并使用
(funcall my start process…)
调用函数,其他一切在参数等方面都与
start process类似

(让*((我的启动过程
(lambda(名称缓冲程序和rest程序参数)
(除非(fboundp’make流程)
(错误“编译Emacs时没有子流程支持”))
(让我们*(
(温度(mapcar的concat工艺环境))
(新环境
(续)
((相等(car(cdr(当前时区)))“PDT”)
(设置环境内部温度“TZ”“UTC+7”t))
((相等(car(cdr(当前时区)))“PST”)
(setenv内部温度“TZ”“UTC+8”t)))
(过程环境(或新环境温度)))
(应用#制作流程)
(追加(列表:名称:缓冲区)
(当节目
(列表:命令(cons程序args(()())())))
(proc(funcall my start process…))

您正在设置全局值。显然,@user4815162342的答案比这更好,因为Emacs似乎已经有了一种机制来处理子流程的环境……这个“流程环境”变量正是我所要寻找的。对于那些只想影响
M-x编译
环境的人,您只需使用
编译环境
变量即可。详情见最后一段。你也可以让这个缓冲区变得有价值-local@Felipe很好的一点,尽管OP确实特别提到了flymake,它不是
编译模式的一部分。关于动态绑定没有什么本质上难以解释的,事实上它仍然是Emacs Lisp中的默认值。但是动态范围界定很难向不习惯的人解释——它是Elisp中的默认设置,这并不会使它更容易理解。动态范围界定有很多问题,但难以理解不是其中之一。事实上,理解它并不重要,这就是为什么它是BASIC、各种shell、Perl、各种lisp等语言中的默认值。