Redémarrez emacs depuis emacs

44

Je redémarre beaucoup mon emacs. Tout ce que je veux faire est de créer une fonction qui tue les emacs actuels, pour en créer une nouvelle à sa place. Idéalement, cela fonctionnerait également dans un ATS.

PythonNut
la source
8
Par curiosité, pourquoi tuez-vous et redémarrez-vous immédiatement si souvent?
Dan
2
Je développe très activement mon logiciel .emacs.d, ce qui signifie que je redémarre emacs pour supprimer les déchets que j'ai envoyés dans mon environnement. C'est ce que je fais dans quelques autres cas d'utilisation, mais c'est le plus important.
PythonNut
1
@ PythonNut, je pense que vous devez reformuler votre question un peu. Pouvez-vous dire bashde redémarrer après avoir terminé? Ou vi? Ou tout autre processus, en règle générale? Non, car cela ne fait pas partie de leurs préoccupations et est traité correctement à l’extérieur. Quoi qu'il en soit, ce que vous voulez vraiment, c'est un moyen de réinitialiser emacs, en effaçant sa VM et en réexécutant votre code init ( sans tuer son processus). Ce serait utile et approprié à Emacs. Je ne sais pas s'il existe, cependant :)
harpo
4
@harpo oui, je peux commencer bashà redémarrer avec exec bash. Je n'ai aucune idée de Vim.
PythonNut
11
FWIW, je suis plus enclin à démarrer une nouvelle instance d’Emacs pour tester les modifications de configuration, plutôt que de quitter et de redémarrer. Pourquoi? Parce que si mon code contient une erreur, Emacs pourrait ne pas être en mesure de charger ma configuration lorsque je la redémarre. À ce stade, je ne peux pas obtenir une instance en cours d'exécution avec mes paramètres normaux. Je dois donc utiliser une édition moins familière. environnement pour corriger le bogue. Cela n'arrivera pas souvent, mais c'est agaçant quand cela se produit. emacs -qBien sûr, je peux exécuter et résoudre le problème, mais je préfère garder une "bonne" instance en fonctionnement tout le temps lors du piratage de ma configuration, pour des raisons de sécurité.
phils

Réponses:

25

Remarque: J'ai emballé les éléments suivants dans un package restart-emacsdisponible ici .


Voici un autre moyen d’atteindre ce que vous voulez en utilisant du pur elisp (pas vraiment puisque vous comptez sur un shell). Le truc consiste à engendrer un autre processus emacs juste avant que les emacs actuels soient tués.

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

Le code pour démarrer une version graphique d’emacs est simple. Le code pour démarrer emacs dans un terminal est un peu délicat. Il utilise le fait que vous pouvez passer une chaîne suspend-emacsqui serait transmise en tant qu'entrée de terminal au processus parent (le shell). De la documentation

(suspend-emacs & STUFFSTRING en option)

Arrêtez Emacs et retournez au processus supérieur. Vous pouvez reprendre plus tard. Si `ne peut pas suspendre 'est non nul, ou si le système ne prend pas en charge le contrôle des travaux, exécutez un sous-shell à la place.

Si arg optionnel STUFFSTRING est non-nil, ses caractères sont farcis pour être lus en tant qu'entrée terminale par le parent d'Emacs, après suspension.

Donc, en principe, nous suspendons emacs juste avant de le tuer, disons au shell parent de reprendre les emacs actuellement suspendus (qui vont bientôt disparaître), puis de lancer un autre processus emacs. Notez que cela ne fonctionne pas sur les plates-formes sur lesquelles le terminal emacs peut / ne peut pas réellement suspendre mais démarre un sous-shell, par exemple sur Windows.

Iqbal Ansari
la source
Cela ne fonctionne pas pour moi: quand je cours à sh -c "emacs &"partir du shell, il s'arrête avec " emacs: standard input is not a tty". (Quand je le fais M-x restart-emacsje ne vois même pas ce message d'erreur, Emacs se termine juste.)
Constantine
Fonctionne pour moi sous X. Ne fonctionnera pas dans un terminal car il redirige stdin et stdout vers / dev / null; passer le tty parent au sous-processus est probablement faisable mais plus compliqué.
Beni Cherniavsky-Paskin
1
Cela fonctionne parfaitement et me fait un peu peur. Pourquoi diable Emacs est-il autorisé à passer des commandes à son shell?
Radon Rosborough
quelle combinaison de touches utilisez-vous pour cela?
slk500 le
32

Autant que je sache, vous ne pouvez pas dire à Emacs de redémarrer après la fin, mais vous pouvez définir le code de sortie de sorte que le processus qui a démarré Emacs puisse détecter que vous voulez redémarrer.

Par exemple, ce script shell redémarre Emacs s'il s'est arrêté avec le code 123.

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

Ensuite, nous définissons ce kill-emacs-and-restartqui oblige Emacs à se terminer avec un code de sortie égal au nombre magique reconnu par le script:

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

Maintenant, si vous exécutez Emacs via ce script, vous pouvez recommencer par M-x kill-emacs-and-restart(ou le lier à une séquence de clés).

Constantine
la source
Belle façon de contourner le problème! Je l'accepterai si vous pouvez me dire pourquoi you cannot tell Emacs to re-start after terminating. Est-ce une limitation technique?
PythonNut
3
@PythonNut: Autant que je sache, le seul moyen de relancer un processus consiste à utiliser l'une des fonctions de la exec...famille (sur les systèmes POSIX, de toute façon). Les fonctions de contrôle de processus Emacs Lisp n'exposent pas de tels appels de bas niveau. Je ne suis pas un expert, alors j'espère que quelqu'un de plus expérimenté interviendra.
Constantine
2

Volé de manière flagrante sur https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmatically

En supposant que j'ai la syntaxe correcte pour incorporer "dans une chaîne, cela devrait le faire."

(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\")'"))
Josué
la source
11
S'il vous plaît ne pas. Cela contourne tout le nettoyage interne d'Emacs et ignore tout état actuel (par exemple, les tampons modifiés) sans confirmation .
lunaryorn
l'avertissement de lunaryorn est correct.
Josué