J'essaie d'obtenir shell-command
et async-shell-command
d'intégrer de manière transparente avec quelques programmes dans mon .bashrc
fichier, en particulier direnv dans cet exemple.
J'ai trouvé que si je personnalisais shell-command-switch
, je pouvais obtenir des processus shell pour charger mon profil comme s'il s'agissait d'un shell de connexion interactif normal:
(setq shell-command-switch (purecopy "-ic")) (setq explicit-bash-args '("-ic" "export EMACS =; stty echo; bash"))
J'utilise également exec-path-from-shell .
Disons que j'ai un ~/.bashrc
fichier avec:
... eval "$ (crochet direnv $ 0)" écho "foo"
A l'intérieur ~/code/foo
j'ai un .envrc
dossier avec:
export PATH = $ PWD / bin: $ PATH écho "bar"
Si je lance M-x shell
avec default-directory
set to ~/code/foo
, un shell bash chargera correctement mon profil et exécutera le hook direnv pour l'ajouter à mon chemin:
direnv: chargement .envrc bar direnv: export ~ PATH ~ / code / foo $ echo $ PATH / Utilisateurs / nom d'utilisateur / code / foo / bin: / usr / local / bin: ... # reste de $ PATH
Cependant si default-directory
est toujours ~/code/foo
et que je cours M-! echo $PATH
, il charge correctement mon .bashrc mais n'exécute pas le hook direnv du répertoire courant:
foo / usr / local / bin: ... # reste de $ PATH sans ./bin
J'obtiens le même résultat si je cours M-! cd ~/code/foo && echo $PATH
.
Existe-t-il un moyen de conseiller ou de connecter shell-command
ou start-process
de le faire se comporter comme s'il était envoyé à partir d'un tampon shell interactif?
la source
(setq shell-command-switch "-ic")
il doit être évalué avec toutes les autres commandes dans ~ / .bashrc.eval "$(direnv hook $0)"
. Cela s'exécute, mais le mécanisme qui devrait être déclenché lorsque vous êtes dans un répertoire spécifique avec un.envrc
fichier ne l'est pas..envrc
fichier n'est-il évalué? Ou s'agit-il uniquement de variables d'environnement qui ne sont pas exportées? Pourriez-vous s'il vous plaît fournir un exemple complet afin que je puisse essayer de le reproduire?Réponses:
Cela ne semble pas être un problème avec Emacs mais avec bash.
shell-command
s'exécute simplementcall-process
sur le shell et passe des arguments. J'ai essayé cela sur un shell régulier:~/.bashrc
est originaire, mais le hook direnv n'est pas exécuté. Quanddirenv hook bash
est exécuté, une fonction_direnv_hook
est sortie et ajoutée au débutPROMPT_COMMAND
.Je soupçonne que
PROMPT_COMMAND
cela ne fonctionnera tout simplement pas. Ce n'est pas un problème, cependant, car_direnv_hook
c'est vraiment simple. Nous pouvons simplement ajoutereval $(direnv export bash)
à la commande shell et cela fonctionnera:Cela affichera le chemin augmenté vers le tampon des messages. Vous pouvez également exécuter avec
M-!
:Vous n'en avez pas besoin pour
(setq shell-command-switch "-ic")
que cela fonctionne.la source
eval "$(direnv export bash)"
in elisp, mais cela a été extrêmement utile et m'a mis sur la bonne voie.L'exécution
eval "$(direnv hook $0)"
définit une fonction qui se connecte$PROMPT_COMMAND
, qui n'est jamais appelée lorsque bash est exécutébash -ic
car il n'y a pas d'invite. Vous pouvez changer la ligne:eval "$(direnv hook $0)"
à:
eval "$(direnv hook $0)" && _direnv_hook
pour appeler explicitement la fonction hook.
Edit: Je viens de réaliser que rekado a donné une réponse très similaire.
la source
$PROMPT_COMMAND
.Merci à Rekado et Erik d'avoir souligné le fonctionnement du hook direnv en utilisant
$PROMPT_COMMAND
. Puisqueshell-command
n'utilise pas d'invite, cela n'a pas été exécuté.Bien que la réponse d'Erik fonctionne dans mon exemple d'appeler une commande shell avec
M-!
avecdefault-directory
set, cela ne fonctionnerait pas dans l'exemple suivant:Après quelques recherches sur Google, j'ai trouvé un moyen de créer un hook preexec dans bash pour exécuter quelque chose avant l'exécution d'une commande. J'ai pris cette idée et modifié pour répondre à mon besoin de direnv. Voici à quoi ressemble la partie pertinente de mon ~ / .bashrc:
la source
de nos jours, vous voudrez probablement utiliser https://github.com/wbolster/emacs-direnv
cela fonctionne de manière similaire au hook que direnv installe dans votre shell. l'environnement emacs est mis à jour sur demande (ou automatiquement lors du changement de tampons) pour correspondre à ce que direnv indique est l'environnement correct pour le répertoire en cours.
en modifiant
exec-path
etprocess-environment
emacs se comportera comme le ferait votre shell: exécutez les programmes à partir des bons chemins et avec le bon environnement.la source