Search code examples
emacselisp

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


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.


Solution

  • 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)