Recargar variables de entorno

10

Esta pregunta se ha hecho en superuser is-there-a-way-to-reload-environment-variables-in-emacs , pero no se dio una buena solución.

Estoy usando EmacsClient con a menudo más de 30 buffers abiertos, si cambio una variable de entorno en el shell, necesito salir de EmacsClient (y volver a abrir todos los buffers) o tengo que configurar manualmente la variable de entorno también en Emacs. Me resulta molesto que no pueda actualizar las variables de entorno fácilmente en Emacs. ¿Alguna sugerencia?

Håkon Hægland
fuente
No hay una forma directa de hacer esto, porque cambiar una variable de entorno en el proceso padre no actualizará su valor como se exporta a un hijo.
Erik Hetzner

Respuestas:

7

exec-path-from-shell proporciona el exec-path-from-shell-copy-envcomando, que le permite copiar el valor de las variables de entorno a las sesiones de Emacs. Por ejemplo, M-x exec-path-from-shell-copy-env RET FOOestablece el valor de $FOOen Emacs también.

Tenga en cuenta que exec-path-from-shell-copy-envgenera un nuevo shell para extraer el valor de la variable de entorno. Por lo tanto, solo funcionará para las variables que establezca en sus archivos de configuración de shell (por ejemplo .bashrc), pero no para las variables que solo se configuran en una sesión de shell en ejecución export. La extracción de estas variables es generalmente imposible sin hacks enrevesados ​​que inspeccionan /proc/o API similar para ejecutar procesos.

Lunaryorn
fuente
Con respecto a los últimos valores transitorios, si Emacs se ejecuta como un servidor, pasar los valores actualizados a emacsclient directamente desde ese shell sería bastante fácil.
phils
@phils Gracias, mira mi respuesta actualizada ..
Håkon Hægland
5

Como solución alternativa, se puede usar lo siguiente (Linux, Bash):

  • Primero ejecute printenv -0 > env.txtdesde la ventana de terminal Bash,
  • Luego, desde Emacs, ejecuta
(defun my-update-env ()
  (interactive)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents "env.txt")
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Actualizar

Resulta que esto se puede hacer de manera más elegante usando la --evalopción del emacsclientcomando: Definir un script Bash update_emacs_env:

#! /bin/bash

fn=tempfile
printenv -0 > "$fn" 
emacsclient -s server_name -e '(my-update-env "'"$fn"'")' >/dev/null

donde server_nameestá el nombre de su servidor Emacs, y my-update-enves una función definida por su ~/.emacsarchivo:

(defun my-update-env (fn)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents fn)
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Ahora puede simplemente escribir update_emacs_envdesde la línea de comandos del shell para actualizar las variables de entorno de Emacs.

Håkon Hægland
fuente
Y se podría ejecutar el "printenv" de dentro de la función también ...
Mankoff
@mankoff En realidad, creo que no podrías ... :) (Imprimiría los valores antiguos entonces)
Håkon Hægland
¿No puedes generar un shell con la bandera de inicio de sesión? ¿O sourceel .bashrc, .bash_profile, etc.?
mankoff
Sí ... pero no ayudaría para el caso especial si exporto directamente en la shell desde la línea de comando, usandoexport VAR=value
Håkon Hægland
Sí, no pensé en ese caso. ¡Solución elegante con el cliente!
mankoff
3

Solía ​​usar esto:

function export-emacs {
    if [ "$(emacsclient -e t)" != 't' ]; then
        return 1
    fi

    for name in "${@}"; do
        value=$(eval echo \"\$${name}\")
        emacsclient -e "(setenv \"${name}\" \"${value}\")" >/dev/null
    done
}

Le permite exportar una variable con nombre, por ejemplo:

export EDITOR=vim
export-emacs EDITOR
Phil Jackson
fuente