Riavvia emacs dall'interno di emacs


44

Riavvio molto i miei emacs. Tutto quello che voglio fare è creare una funzione che uccida gli attuali emacs, solo per generarne uno nuovo al suo posto. Idealmente, questo funzionerebbe anche in un TTY.


8
Per curiosità, perché uccidi e riavvii così spesso?
Dan

2
Sviluppo molto attivamente my .emacs.d, il che significa che riavvio emacs per rimuovere qualsiasi immondizia che ho fatto esplodere nel mio ambiente. Ci sono alcuni altri casi d'uso in cui lo faccio, ma questo è il più grande.
PythonNut

1
@PythonNut, penso che devi riformulare un po 'la tua domanda. Puoi dire bashdi riavviare dopo aver terminato? Oppure vi? O qualsiasi altro processo, di regola? No, perché è al di fuori del loro ambito di preoccupazione ed è adeguatamente gestito esternamente. In ogni caso, quello che vuoi davvero è un modo per reinizializzare emacs, cancellando la sua VM e rieseguendo il tuo codice di init ( senza uccidere il suo processo). Sarebbe utile e corretto per emacs. Non so se esiste, però :)
Harpo,

4
@harpo sì, posso bashricominciare exec bash. Non ho idea di Vim.
PythonNut

11
FWIW, sono più propenso ad avviare una nuova istanza di Emacs per testare le modifiche alla configurazione, piuttosto che uscire e riavviare. Perché? Perché se il mio codice presenta un errore, Emacs potrebbe non essere in grado di caricare la mia configurazione al riavvio, ea quel punto in realtà non riesco a ottenere un'istanza in esecuzione con le mie impostazioni normali, quindi devo usare una modifica meno familiare ambiente per correggere il bug. Non succederà spesso, ma è fastidioso quando lo fa. Sono in grado di eseguire emacs -qe risolvere il problema ovviamente, ma preferisco mantenere sempre un'istanza "valida" durante l'hacking sulla mia configurazione, solo per sicurezza.
phils,

Risposte:


25

Nota: ho racchiuso quanto segue in un pacchetto restart-emacsdisponibile qui .


Ecco un modo alternativo per ottenere quello che vuoi usando pure elisp (non proprio da quando ti affidi a una shell). Il trucco è generare un altro processo di emacs appena prima che l'attuale emacs venga ucciso.

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

Il codice per avviare una versione GUI di emacs è semplice. Il codice per avviare emacs in un terminale è un po 'complicato. Usa il fatto che puoi passare una stringa a suspend-emacscui verrebbe passato come input terminale al processo genitore (la shell). Dalla documentazione

(suspend-emacs e STUFFSTRING opzionale)

Arresta Emacs e ritorna al processo superiore. Puoi riprendere più tardi. Se "Impossibile-sospendere" è diverso da zero, o se il sistema non supporta il controllo dei processi, eseguire invece una subshell.

Se arg opzionale STUFFSTRING è diverso da zero, i suoi caratteri vengono riempiti per essere letti come input terminale dal genitore di Emacs, dopo la sospensione.

Quindi sostanzialmente sospendiamo emacs appena prima che venga ucciso, diciamo alla shell madre di riprendere emacs attualmente sospesi (che uscirà presto) e quindi lanciamo un altro processo emacs. Si noti che ciò non funziona su piattaforme su cui emacs terminali possono / non sospendono effettivamente, ma avvia una subshell, ad esempio su Windows.


Questo non funziona per me: quando corro sh -c "emacs &"dalla shell si ferma con " emacs: standard input is not a tty". (Quando lo faccio M-x restart-emacsnon vedo nemmeno quel messaggio di errore, Emacs termina.)
Costantino,

Funziona con me sotto X. Non funzionerà in un terminale perché reindirizza stdin e stdout a / dev / null; passare il genitore tty al sottoprocesso è probabilmente fattibile ma più complicato.
Beni Cherniavsky-Paskin,

1
Funziona perfettamente e mi spaventa un po '. Perché mai a Emacs è permesso passare comandi alla sua shell contenente?
Radon Rosborough,

quale keybinding usi per questo?
slk500,

32

Per quanto ne so, non puoi dire a Emacs di riavviare dopo aver terminato, ma puoi impostare il codice di uscita in modo che il processo che ha avviato Emacs in primo luogo possa rilevare che vuoi riavviare.

Ad esempio, questo script di shell riavvia Emacs se è uscito con il codice 123.

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

Successivamente, definiamo kill-emacs-and-restartche fa terminare Emacs con il codice di uscita uguale al numero magico riconosciuto dallo script:

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

Ora se esegui Emacs tramite questo script puoi ricominciare M-x kill-emacs-and-restart(o associarlo a una sequenza di tasti).


Bel modo di aggirare il problema! Accetterò questo se puoi dirmi perché you cannot tell Emacs to re-start after terminating. È una limitazione tecnica?
PythonNut

3
@PythonNut: Per quanto ne so, l'unico modo per riavviare un processo è utilizzare una delle funzioni della exec...famiglia (su sistemi POSIX, comunque). Le funzioni di controllo di processo di Emacs Lisp non espongono tali chiamate di basso livello. Non sono un esperto, però, quindi spero che qualcuno più esperto entrerà in campo.
Costantino,

2

Evidentemente rubato da https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmmatic

Supponendo che ho la sintassi giusta per incorporare "in una stringa, questo dovrebbe farlo.

(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
Per favore, no. Ciò ignora tutta la pulizia interna di Emacs e scarta tutti gli stati correnti (ad es. Buffer modificati) senza conferma .
lunaryorn,

l'avvertimento di lunaryorn è corretto.
Joshua,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.