Перезавантажте emacs зсередини emacs


44

Я багато перезапускаю свої emacs. Все, що я хочу зробити, - це створити функцію, яка вбиває поточні emacs, тільки щоб породити новий замість нього. В ідеалі це також би працювало в TTY.


8
З цікавості, чому ви вбиваєте та негайно так часто запускаєте?
Дан

2
Я дуже активно розвиваю своє .emacs.d, а це означає, що я перезапускаю emacs, щоб видалити будь-яке сміття, яке я потрапив у своє оточення. Є кілька інших випадків використання, коли я це роблю, але це найбільше.
PythonNut

1
@PythonNut, я думаю, вам потрібно трохи переробити своє запитання. Чи можете ви сказати bashперезавантажити після закінчення? Або vi? Або будь-який інший процес, як правило? Ні, тому що це виходить за межі їх проблем, і належним чином застосовується зовні. У будь-якому випадку те, що ви насправді хочете, - це спосіб повторно реалізувати emacs, очистивши його VM та повторно запустивши свій код init ( не вбиваючи його процес). Це було б корисно та належно emacs. Я не знаю, чи існує, але :)
harpo

4
@harpo так, я можу bashперезапустити exec bash. Я не маю уявлення про vim.
PythonNut

11
FWIW, я більше схильний запустити новий екземпляр Emacs для тестування змін конфігурації, а не виходу та перезавантаження. Чому? Тому що якщо в моєму коді є помилка, то Emacs не зможе завантажити мою конфігурацію, коли я перезавантажую її, і в цей момент я фактично не можу отримати запущений екземпляр зі своїми нормальними налаштуваннями, тому мені доведеться використовувати менш знайоме редагування середовище, щоб виправити помилку. Це трапляється не часто, але це дратує, коли це станеться. Я, emacs -qзвичайно, можу запустити та виправити проблему, але я вважаю за краще тримати «добрий» екземпляр під час злому моєї конфігурації у будь-який час.
філ

Відповіді:


25

Примітка. Я переклав наступне в пакет, restart-emacsдоступний тут .


Ось альтернативний спосіб досягти того, що ви хочете, використовуючи чистий елісп (не дуже, оскільки ви покладаєтесь на оболонку). Трюк полягає в тому, щоб створити ще один процес emacs перед вбивством поточних emacs.

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

Код для запуску GUI-версії emacs простий. Код для запуску emacs у терміналі трохи складний. Він використовує той факт, що ви можете передати рядок, suspend-emacsякий буде переданий як термінальний вхід до батьківського процесу (оболонки). З документації

(призупинити-emacs та необов'язково ПОВЕРНЕННЯ)

Зупиніть Emacs та поверніться до вищого процесу. Ви можете відновити пізніше. Якщо опція `не може призупинити дію ', або якщо система не підтримує контроль за роботою, замість неї запустіть підзарядку.

Якщо необов'язковий аргумент STUFFSTRING не має нульових значень, його символи заповнюються, щоб зчитуватись як термінальний вхід батьком Emacs після призупинення.

Таким чином, ми в основному призупиняємо emacs перед тим, як він буде вбитий, скажемо батьківській оболонці відновити поточно призупинені emacs (які незабаром завершаться), а потім запустити інший процес emacs. Зауважте, що це не працює на платформах, на яких термінал emacs може / насправді не призупиняється, але запускає підзарядку, наприклад у Windows.


Це не працює для мене: коли я біжу sh -c "emacs &"від оболонки, вона зупиняється на " emacs: standard input is not a tty". (Коли я це робити, M-x restart-emacsя навіть не бачу цього повідомлення про помилку, Emacs просто припиняється.)
Костянтин

Працює для мене під X. Не працює в терміналі, оскільки він перенаправляє stdin і stdout на / dev / null; передача батьківського tty до підпроцесу, ймовірно, доцільна, але складніше.
Бені Чернявський-Паскін

1
Це прекрасно працює, і насправді це мене трохи лякає. Чому на Emacs дозволено передавати команди його оболонці?
Радон Росборо

яке клавішне використання ви використовуєте для цього?
slk500

32

Наскільки я знаю, ви не можете сказати Emacs перезапуститись після закінчення, але ви можете встановити код виходу, щоб процес, який запустив Emacs, в першу чергу міг виявити, що ви хочете перезапустити.

Наприклад, цей скрипт оболонки перезапускає Emacs, якщо він вийшов із кодом 123.

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

Далі ми визначаємо, kill-emacs-and-restartщо змушує Emacs закінчувати код виходу рівним магічному номеру, розпізнаваному сценарієм:

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

Тепер, якщо ви запускаєте Emacs за допомогою цього сценарію, ви можете перезапустити його M-x kill-emacs-and-restart(або прив’язати його до послідовності ключів).


Гарний спосіб прокрутки навколо проблеми! Я прийму це, якщо ви можете мені сказати, чому you cannot tell Emacs to re-start after terminating. Це технічне обмеження?
PythonNut

3
@PythonNut: Наскільки я знаю, єдиний спосіб відновити процес - це використовувати одну з функцій exec...родини (у будь-якому випадку на системах POSIX). Функції управління процесами Emacs Lisp не піддають таких дзвінків низького рівня. Я, однак, не експерт, тому сподіваюся, хтось більш обізнаний задзвенить.
Костянтин

2

Відверто вкрадено з https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmatic

Якщо припустити, що я маю право на синтаксис для вбудовування "в рядок, це повинно це робити.

(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
Будь ласка, не варто. Це обходить всі внутрішні очищення Emacs та відкидає весь поточний стан (наприклад, модифіковані буфери) без підтвердження .
місячник

Попередження місячних є правильним.
Джошуа
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.