Ich versuche , zu erhalten shell-command
und async-shell-command
mit ein paar Programme in meiner nahtlos zu integrieren .bashrc
Datei, speziell direnv in diesem Beispiel.
Ich stellte fest, dass ich beim Anpassen shell-command-switch
Shell-Prozesse dazu bringen könnte, mein Profil so zu laden, als wäre es eine reguläre interaktive Login-Shell:
(setq shell-command-switch (purecopy "-ic")) (setq explizit-bash-args '("-ic" "export EMACS =; stty echo; bash"))
Ich benutze auch exec-path-from-shell .
Angenommen, ich habe eine ~/.bashrc
Datei mit:
... eval "$ (direnv hook $ 0)" Echo "foo"
Im Inneren habe ~/code/foo
ich eine .envrc
Datei mit:
export PATH = $ PWD / bin: $ PATH Echo "Bar"
Wenn ich M-x shell
mit default-directory
set to ~/code/foo
ausführe, lädt eine Bash-Shell mein Profil korrekt und führt den direnv-Hook aus, um dies meinem Pfad hinzuzufügen:
direnv: Laden von .envrc Bar direnv: export ~ PATH ~ / code / foo $ echo $ PATH / Benutzer / Benutzername / Code / foo / bin: / usr / local / bin: ... # Rest von $ PATH
Wenn dies default-directory
jedoch immer noch der Fall ist ~/code/foo
und ich ausgeführt werde M-! echo $PATH
, wird meine .bashrc-Datei korrekt geladen, der direnv-Hook des aktuellen Verzeichnisses wird jedoch nicht ausgeführt:
foo / usr / local / bin: ... # Rest von $ PATH ohne ./bin
Ich bekomme das gleiche Ergebnis, wenn ich renne M-! cd ~/code/foo && echo $PATH
.
Gibt es eine Weise , die ich beraten oder Haken in shell-command
oder start-process
um es sich verhalten , als ob es aus einem interaktiven Shell - Puffer gesendet wurden?
quelle
(setq shell-command-switch "-ic")
es ausgewertet haben, sollte es zusammen mit jedem anderen Befehl in ~ / .bashrc ausgewertet werden.eval "$(direnv hook $0)"
. Dies wird ausgeführt, aber der Mechanismus, der ausgelöst werden soll, wenn Sie sich in einem bestimmten Verzeichnis mit einer.envrc
Datei befinden, ist dies nicht..envrc
Datei ausgewertet? Oder werden nur Umgebungsvariablen nicht exportiert? Könnten Sie bitte ein vollständiges Beispiel angeben, damit ich versuchen kann, dies zu reproduzieren?Antworten:
Dies scheint kein Problem mit Emacs zu sein, sondern mit Bash.
shell-command
wird nurcall-process
auf der Shell ausgeführt und übergibt Argumente. Ich habe das auf einer normalen Shell versucht:~/.bashrc
wird bezogen, aber der direnv-Hook wird nicht ausgeführt. Wenndirenv hook bash
ausgeführt, wird eine Funktion_direnv_hook
ausgegeben und vorangestelltPROMPT_COMMAND
.Ich vermute, das wird
PROMPT_COMMAND
einfach nicht funktionieren. Das ist aber kein Problem, denn das_direnv_hook
ist wirklich einfach. Wir können einfacheval $(direnv export bash)
den Shell-Befehl voranstellen und es wird funktionieren:Dadurch wird der erweiterte Pfad zum Nachrichtenpuffer gedruckt. Alternativ können Sie Folgendes ausführen
M-!
:Sie müssen nicht,
(setq shell-command-switch "-ic")
damit dies funktioniert.quelle
eval "$(direnv export bash)"
Elisp nicht hinzugefügt werden muss, aber dies war äußerst hilfreich und brachte mich auf den richtigen Weg.Running
eval "$(direnv hook $0)"
definiert eine Funktion, die sich einhakt$PROMPT_COMMAND
und die beim Ausführen von bash niemals aufgerufen wird,bash -ic
da keine Eingabeaufforderung vorhanden ist. Sie können die Zeile ändern:eval "$(direnv hook $0)"
zu:
eval "$(direnv hook $0)" && _direnv_hook
die Hook-Funktion explizit aufrufen.
Bearbeiten: Gerade realisiert, gab rekado eine sehr ähnliche Antwort.
quelle
$PROMPT_COMMAND
.Vielen Dank an Rekado und Erik für den Hinweis, wie der Direnv-Hook mit funktioniert
$PROMPT_COMMAND
. Dashell-command
keine Eingabeaufforderung verwendet wird, wurde diese nicht ausgeführt.Während Eriks Antwort in meinem Beispiel funktioniert, in dem ein Shell-Befehl
M-!
mitdefault-directory
set aufgerufen wird, funktioniert sie im folgenden Beispiel nicht:Nach einigem googeln habe ich einen Weg gefunden, einen preexec-Hook in bash zu erstellen , um etwas auszuführen, bevor ein Befehl ausgeführt wird. Ich nahm diese Idee und modifizierte sie, um meinem Bedürfnis nach Direnv gerecht zu werden. So sieht der relevante Teil meines ~ / .bashrc jetzt aus:
quelle
Heutzutage möchten Sie wahrscheinlich https://github.com/wbolster/emacs-direnv verwenden
Es funktioniert ähnlich wie der Hook, den direnv in Ihrer Shell installiert. Die Emacs-Umgebung wird auf Anfrage (oder automatisch beim Wechseln der Puffer) aktualisiert, um den direkten Umgebungen für das aktuelle Verzeichnis zu entsprechen.
Durch Ändern
exec-path
undprocess-environment
Emacs wird sich so verhalten, wie es Ihre Shell tun würde: Führen Sie Programme von den richtigen Pfaden und mit der richtigen Umgebung aus.quelle