Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set environment variables to a buffer-local scope in emacs

Tags:

emacs

elisp

In Emacs, I want to vary the values of my environment variables in different buffers.

My emacs environment depends on environment variables (flymake, compile etc), however I want to be able to be able to have multiple projects open at once in one emacs session but these projects might have conflicting environments.

For example something like different INCLUDE_PATH environment variables for flymake.

like image 472
Marius Olsthoorn Avatar asked May 28 '13 08:05

Marius Olsthoorn


3 Answers

You can do this by making 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)

A more elaborate example is this code that imports the Guile environment setup created by an external script. The script is designed to be "sourced" in the shell, but here its result gets imported into a single Emacs buffer:

(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)
like image 156
user4815162342 Avatar answered Oct 22 '22 11:10

user4815162342


I put the following in .dir-locals.el at the root of the tree where I want to define some environment vars:

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

This will warn the first time you open a file in that directory tree. After you accept, the given environment var will be defined for each buffer you open there.

like image 30
Joost Diepenmaat Avatar answered Oct 22 '22 12:10

Joost Diepenmaat


One solution would be to temporary change the environment when you spawn an external command. The command will inherit the current environment. Remember that Emacs is a single-treaded application, so we don't have to worry about race conditions etc.

You can pick one of two ways of doing this:

1) Write you own functions like my-compile that changes the environment temporarily and calls the normal compile command.

2) Modify the low-level process functions and ensure that they modify the environment accordingly. Typically, you can do this with defadvice.

like image 40
Lindydancer Avatar answered Oct 22 '22 11:10

Lindydancer