Recharger les variables d'environnement

10

Cette question a été posée au superutilisateur is-there-a-way-to-recharge-environment-variables-in-emacs , mais aucune bonne solution n'a été donnée.

J'utilise EmacsClient avec souvent plus de 30 tampons ouverts, si je change une variable d'environnement dans le shell, je dois quitter EmacsClient (et rouvrir tous les tampons) ou je dois définir manuellement la variable d'environnement également dans Emacs. Je trouve ennuyeux de ne pas pouvoir mettre à jour facilement les variables d'environnement dans Emacs. Aucune suggestion?

Håkon Hægland
la source
Il n'existe aucun moyen simple de le faire, car la modification d'une variable d'environnement dans le processus parent ne mettra pas à jour sa valeur telle qu'elle est exportée vers un enfant.
Erik Hetzner

Réponses:

7

exec-path-from-shell fournit la exec-path-from-shell-copy-envcommande, qui vous permet de copier la valeur des variables d'environnement dans les sessions Emacs. Par exemple, M-x exec-path-from-shell-copy-env RET FOOdéfinit également la valeur de $FOOdans Emacs.

Notez que exec-path-from-shell-copy-envgénère un nouveau shell pour extraire la valeur de la variable d'environnement. Par conséquent, cela ne fonctionnera que pour les variables que vous définissez dans vos fichiers de configuration shell (par exemple .bashrc), mais pas pour les variables définies uniquement dans une session shell en cours d'exécution avec export. L'extraction de ces variables est généralement impossible sans des piratages alambiqués qui inspectent /proc/ou une API similaire pour l'exécution des processus.

lunaryorn
la source
En ce qui concerne ces dernières valeurs / transitoires, si Emacs s'exécute en tant que serveur, le transfert des valeurs mises à jour à emacsclient directement à partir de ce shell serait assez facile.
phils
@phils Merci, voir ma réponse mise à jour ..
Håkon Hægland
5

Comme solution de contournement, les éléments suivants peuvent être utilisés (Linux, Bash):

  • Exécutez d'abord à printenv -0 > env.txtpartir de la fenêtre du terminal Bash,
  • Ensuite, depuis Emacs, exécutez
(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)))))

Mise à jour

Il s'avère que cela peut être fait de manière plus élégante en utilisant l' --evaloption de la emacsclientcommande: Définir un script Bash update_emacs_env:

#! /bin/bash

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

server_nameest le nom de votre serveur Emacs et my-update-envest une fonction définie par votre ~/.emacsfichier:

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

Vous pouvez maintenant simplement taper à update_emacs_envpartir de la ligne de commande du shell pour mettre à jour les variables d'environnement Emacs.

Håkon Hægland
la source
Et vous pouvez également exécuter le "printenv" depuis l'intérieur de la fonction ...
mankoff
@mankoff En fait, je pense que vous ne pourriez pas .. :) (Il imprimerait alors les anciennes valeurs)
Håkon Hægland
Vous ne pouvez pas générer un shell avec un drapeau de connexion? Ou sourcele .bashrc, .bash_profile, etc.?
mankoff
Oui .. mais cela n'aiderait pas pour le cas spécial si j'exporte dans le shell directement depuis la ligne de commande, en utilisantexport VAR=value
Håkon Hægland
Oui, je n'ai pas pensé à ce cas. Solution élégante avec le client!
mankoff
3

J'avais l'habitude d'utiliser ceci:

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
}

Vous permet d'exporter une variable nommée, EG:

export EDITOR=vim
export-emacs EDITOR
Phil Jackson
la source