在Emacs中,我想在不同的缓冲区中改变环境变量的值。
我的emacs环境依赖于环境变量(flymake,编译等),但我希望能够在一个emacs会话中同时打开多个项目,但这些项目可能存在冲突的环境。
例如类似于flymake的不同INCLUDE_PATH环境变量。
答案 0 :(得分:15)
您可以通过process-environment
buffer-local:
(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)
答案 1 :(得分:1)
一种解决方案是在生成外部命令时临时更改环境。该命令将继承当前环境。请记住,Emacs是一个单线程应用程序,因此我们不必担心竞争条件等。
您可以选择以下两种方法之一:
1)编写自己的函数,如my-compile
,暂时更改环境并调用正常的编译命令。
2)修改低级流程函数并确保它们相应地修改环境。通常,您可以使用defadvice
执行此操作。
答案 2 :(得分:0)
可以对这些变量使用动态绑定。
动态绑定和动态范围有点难以解释,有关解释,请参阅http://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding和 http://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scoping
答案 3 :(得分:0)
以下是我创建本地process-environment
而不必将其设为buffer-local
的示例。优点是设置仅影响正在运行的进程,并且一旦进程结束它们就会消失。在这个例子中,我设置了timzezone环境变量,并使用(funcall my-start-process ....)
调用该函数,其他所有内容就像参数一样start-process
,等等。
(let* ((my-start-process
(lambda (name buffer program &rest program-args)
(unless (fboundp 'make-process)
(error "Emacs was compiled without subprocess support"))
(let* (
(temp (mapcar 'concat process-environment))
(newenv
(cond
((equal (car (cdr (current-time-zone))) "PDT")
(setenv-internal temp "TZ" "UTC+7" t))
((equal (car (cdr (current-time-zone))) "PST")
(setenv-internal temp "TZ" "UTC+8" t))))
(process-environment (or newenv temp)))
(apply #'make-process
(append (list :name name :buffer buffer)
(when program
(list :command (cons program program-args))))))))
(proc (funcall my-start-process ...))))
答案 4 :(得分:-1)
我将.dir-locals.el
中的以下内容放在我想要定义一些环境变量的树的根目录中:
;; variables local to this directory and its children
((nil . ((eval . (setenv "SOME_VARIABLE" "TRUE")))))
这将在您第一次打开该目录树中的文件时发出警告。接受后,将为您在那里打开的每个缓冲区定义给定的环境var。