Starten Sie den Emacs von Emacs aus neu


44

Ich starte meinen Emacs viel neu. Ich möchte nur eine Funktion erstellen, die die aktuellen Emacs abschaltet und stattdessen eine neue erzeugt. Idealerweise würde dies auch in einem TTY funktionieren.


8
Warum tötest du aus Neugier so oft und startest sofort wieder?
Dan

2
Ich entwickle meine sehr aktiv .emacs.d, was bedeutet, dass ich Emacs neu starte, um den Müll zu entfernen, den ich in meine Umgebung gesprengt habe. Es gibt einige andere Anwendungsfälle, in denen ich das mache, aber das ist der größte.
PythonNut

1
@PythonNut, ich denke, Sie müssen Ihre Frage ein wenig umformulieren. Kannst du sagen bash, nach dem Beenden neu zu starten? Oder vi? Oder irgendein anderer Prozess in der Regel? Nein, da dies außerhalb ihres Anliegenbereichs liegt und von außen ordnungsgemäß gehandhabt wird. Was Sie auf jeden Fall wirklich wollen, ist eine Möglichkeit, Emacs neu zu initialisieren , indem Sie die VM löschen und Ihren Init-Code erneut ausführen ( ohne den Prozess zu beenden ). Das wäre nützlich und angemessen für Emacs. Ich weiß allerdings nicht, ob es das gibt :)
harpo

4
@harpo ja, ich kann bashmit neu starten exec bash. Ich habe keine Ahnung von vim.
PythonNut

11
FWIW, ich bin eher geneigt, eine neue Emacs-Instanz zu starten , um Konfigurationsänderungen zu testen, als zu beenden und neu zu starten. Warum? Denn wenn mein Code einen Fehler aufweist, kann Emacs meine Konfiguration möglicherweise nicht laden, wenn ich ihn neu starte, und zu diesem Zeitpunkt kann ich keine laufende Instanz mit meinen normalen Einstellungen erhalten, sodass ich eine weniger vertraute Bearbeitung verwenden muss Umgebung, um den Fehler zu beheben. Es kommt nicht oft vor, aber es ist ärgerlich, wenn es passiert. Ich kann emacs -qdas Problem natürlich ausführen und beheben, aber ich bevorzuge es, immer eine "gute" Instanz auszuführen , wenn ich meine Konfiguration hacke, nur um sicherzugehen.
Phils

Antworten:


25

Hinweis: Ich habe Folgendes in ein Paket eingepackt, das hierrestart-emacs erhältlich ist .


Hier ist eine alternative Methode, um mit purem Elisp das zu erreichen, was Sie wollen (nicht wirklich, da Sie sich auf eine Shell verlassen). Der Trick besteht darin, einen anderen Emacs-Prozess auszulösen, kurz bevor der aktuelle Emacs getötet wird.

(defun launch-separate-emacs-in-terminal ()
  (suspend-emacs "fg ; emacs -nw"))

(defun launch-separate-emacs-under-x ()
  (call-process "sh" nil nil nil "-c" "emacs &"))

(defun restart-emacs ()
  (interactive)
  ;; We need the new emacs to be spawned after all kill-emacs-hooks
  ;; have been processed and there is nothing interesting left
  (let ((kill-emacs-hook (append kill-emacs-hook (list (if (display-graphic-p)
                                                           #'launch-separate-emacs-under-x
                                                         #'launch-separate-emacs-in-terminal)))))
    (save-buffers-kill-emacs)))

Der Code zum Starten einer GUI-Version von Emacs ist unkompliziert. Der Code zum Starten von Emacs in einem Terminal ist etwas knifflig. Es wird die Tatsache ausgenutzt, dass Sie eine Zeichenfolge übergeben können, suspend-emacsdie als Terminal-Eingabe an den übergeordneten Prozess (die Shell) übergeben wird. Aus der Dokumentation

(Suspend-Emacs & optionaler STUFFSTRING)

Stoppen Sie Emacs und kehren Sie zum übergeordneten Prozess zurück. Sie können später fortfahren. Wenn `nicht aussetzen 'nicht null ist oder wenn das System die Auftragssteuerung nicht unterstützt, führen Sie stattdessen eine Subshell aus.

Wenn das optionale Argument STUFFSTRING nicht null ist, werden seine Zeichen so gefüllt, dass sie nach dem Suspendieren von Emacs 'Eltern als Terminal-Eingabe gelesen werden.

Wir unterbrechen Emacs also im Grunde, kurz bevor es beendet wird. Fordern Sie die übergeordnete Shell auf, die momentan unterdrückten Emacs (die bald beendet werden) wieder aufzunehmen und dann einen weiteren Emacs-Prozess zu starten. Beachten Sie, dass dies nicht auf Plattformen funktioniert, auf denen Terminal-Emacs tatsächlich anhalten können oder nicht, sondern eine Subshell starten, z. B. unter Windows.


Das funktioniert bei mir nicht: Wenn ich sh -c "emacs &"von der Shell aus laufe , hört es mit " emacs: standard input is not a tty" auf. (Wenn ich diese M-x restart-emacsFehlermeldung nicht sehe,
Constantine

Funktioniert für mich unter X. Funktioniert nicht in einem Terminal, da stdin und stdout nach / dev / null umgeleitet werden. Das übergeordnete tty an den Unterprozess zu übergeben, ist wahrscheinlich machbar, aber schwieriger.
Beni Cherniavsky-Paskin

1
Das funktioniert perfekt und macht mir ein bisschen Angst. Warum um alles in der Welt darf Emacs Befehle an die zugehörige Shell übergeben?
Radon Rosborough

Welche Tastenkombination verwenden Sie dafür?
slk500

32

Soweit ich weiß, können Sie Emacs nicht anweisen, nach dem Beenden neu zu starten, aber Sie können den Beendigungscode so einstellen, dass der Prozess, der Emacs überhaupt gestartet hat, erkennen kann, dass Sie neu starten möchten.

Beispielsweise startet dieses Shell-Skript Emacs neu, wenn es mit dem Code 123 beendet wurde.

#!/bin/sh
while emacs -nw "$@"; [ $? = 123 ]; do :; done

Als nächstes definieren wir, kill-emacs-and-restartdass Emacs mit dem Exit-Code endet, der der magischen Zahl entspricht, die vom Skript erkannt wird:

(defun kill-emacs-and-restart ()
  (interactive)
  (kill-emacs 123))

Wenn Sie Emacs jetzt über dieses Skript ausführen, können Sie es neu starten M-x kill-emacs-and-restart(oder an eine Tastenfolge binden).


Schöne Art, das Problem zu umgehen! Ich werde das akzeptieren, wenn Sie mir sagen können, warum you cannot tell Emacs to re-start after terminating. Ist das eine technische Einschränkung?
PythonNut

3
@PythonNut: Soweit ich weiß, ist der einzige Weg, einen Prozess neu zu starten, die Verwendung einer der Funktionen aus der exec...Familie (auf POSIX-Systemen jedenfalls). Mit den Prozesssteuerungsfunktionen von Emacs Lisp werden keine Anrufe auf niedriger Ebene angezeigt. Ich bin jedoch kein Experte, also hoffentlich meldet sich jemand, der sich besser auskennt.
Constantine

2

Offensichtlich gestohlen von https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmatically

Angenommen, ich habe die richtige Syntax zum Einbetten von "" in eine Zeichenfolge, dann sollte dies der Fall sein.

(defun restart-emacs ()
  (call-process "sh" nil nil nil "-c" "gdb -p $(ps h -o ppid -p $$) -ex 'call execl(\"/bin/sh\", \"/bin/sh\", \"-c\", \"exec emacs\")'"))

11
Bitte nicht Dies umgeht alle von Emacs internen cleanup und verwirft alle aktuellen Zustand (zB modifizierte Puffer) ohne Bestätigung .
Lunaryorn

Die Warnung des Monddorns ist richtig.
Joshua
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.