Environment variables on Emacs
Maybe you need an env var for something you're doing in lisp or for some library. How can you set it?
I usually export my env vars from .bashrc
, especially if they don't require extra caution, for example, any token you use for running a bot. So, we go in .bashrc
and write:
#~/.bashrc
export VARNAME="VAR STRING"
To get the value in Emacs, you should be able to launch getenv
like this
(getenv "VARNAME")
But it's not so simple. Are you surprised? I don't think so, it's never so simple.
Why your getenv
function is giving you a nil
, instead of your craved string?
Maybe you aren't running Emacs from within the shell. That's my case because I run the Emacs daemon from systemd. I think my option could be to launch the daemon from the shell, but I would like to maintain my current approach to the daemon.
I found that xahlee covered this topic in a post of his and he basically said that you could actually launch envvars from within emacs itself as a solution. It feels hacky to me. The other solutions are specifically for Windows or MacOS, so I moved over and thought about exposing the env vars from systemd.
A member of the Arch community "found a good way to export environment variables using systemctl so that they are available to systemd spawned processes". This could be exactly what I was looking for, but I don't like to mess with systemd, because I found .bashrc
more comfortable, so I kept looking for a solution with the actual approach. I keep this here as plan B.
So I found this interesting answer on unix.stackexchange which linked a gist which presents a
nice piece of Emacs lisp that uses diff to compare outputs of export command before and after sourcing, and then calls setenv function accordingly.
let's see it:
(defun source (filename)
"Update environment variables from a shell source file."
(interactive "fSource file: ")
(message "Sourcing environment from `%s'..." filename)
(with-temp-buffer
(shell-command (format "diff -u <(true; export) <(source %s; export)" filename) '(4))
(let ((envvar-re "declare -x \\([^=]+\\)=\\(.*\\)$"))
;; Remove environment variables
(while (search-forward-regexp (concat "^-" envvar-re) nil t)
(let ((var (match-string 1)))
(message "%s" (prin1-to-string `(setenv ,var nil)))
(setenv var nil)))
;; Update environment variables
(goto-char (point-min))
(while (search-forward-regexp (concat "^+" envvar-re) nil t)
(let ((var (match-string 1))
(value (read (match-string 2))))
(message "%s" (prin1-to-string `(setenv ,var ,value)))
(setenv var value)))))
(message "Sourcing environment from `%s'... done." filename))
It looks like a good solution: one could add this to the config file followed by a
(source ".bashrc")
and getting your exports now and forever without problems. Right? Well, it doesn't work for me.
Now I must do other things in my life, but I promise that I will update this post soon, hopefully with a reasonable and elegant solution. Better: with a working solution. A working solution would be just fine.
Did you find this post useful?
Remember that this website doesn’t make use of any trackers or analytics or adv so it doesn’t earn from your visits (moreover, it has a minimal environmental impact).
If you like this blog, refill my caffeine supplies by