Вопрос Как установить статус выхода для emacsclient


Я решил использовать мою основную сессию Emacs (CocoaEmacs в OSX) для редактирования моей командной строки bash. Для этого у меня установлен мой EDITOR emacsclient, Затем я редактирую строку в Emacs и сохраняю и закрываю этот буфер - обычно используя "C-x #" который выполняет (server-edit),

Проблема в том, что иногда Я занимаюсь редактированием строки, и я понимаю, что я не хочу, чтобы на самом деле выполнял эту строку (в ней вызывают сожаление). Проблема заключается в том, что bash определяет, следует ли выполнять строку или нет на основе статуса возврата.

Я бы хотел, чтобы у меня было два варианта.

  1. Если я ударил "C-x #" сохранить буфер и вернуть код выхода 0 (т. е. я сделал свое редактирование, и я готов к bash, чтобы с ним справиться).

  2. Если я убью буфер, не сохраняю буфер, убейте его и верните ненулевой код выхода. Я даже не возражал бы, если бы мне пришлось напасть на альтернативную привязку.

Один частичный решение просто для того, чтобы прокомментировать эту строку. Я не рассматриваю это как вариант для меня, как обычно, потому что я редактирую командную строку в Emacs, так это то, что я работаю над многострочной штукой.


4
2018-06-09 18:31


происхождения


Будете ли вы заглушать буфер, сохраняете и выходите за работу? Должно быть легко связать это с чем-то. - user314253
вероятно, не потому, что я не хочу, чтобы история была протерта, и я думаю, что есть проблема с этим. хотя мне нужно освоить историю истории bash немного лучше. - milkypostman


ответы:


В относительно текущих версиях Emacs (например, в моей копии Emacs 24.2, но не в дистрибуции OSA от OS X версии 22.1), вы можете написать код Elisp, который отправит команду emacsclient, которая сообщит ему выйти с статусом выхода ошибки.

Это проще, чем кажется.

Существует буфер-локальная переменная, server-buffer-clients, с клиентами, которые прикреплены к буферу. И функция server-send-string может использоваться для передачи команд после server-process-filter протокол.

Например:

(server-send-string (car server-buffer-clients) "-error die")

вызывает (один из) emacsclient (s), связанных с буфером, для немедленной выдачи текста

*ERROR*: die

и затем выйдите с кодом выхода 1.


Таким образом, довольно легко определить интерактивную функцию, которую вы могли бы вызвать из emacs, чтобы убить emacsclients:

(defun tell-emacsclients-for-buffer-to-die ()
  "Sends error exit command to every client for the current buffer."
  (interactive)
  (dolist (proc server-buffer-clients)
    (server-send-string proc "-error die")))

С приведенным выше в вашем .emacs файла (и достаточно текущей версии Emacs), вы можете вызывать M-x tell-emacsclients-for-buffer-to-die для выхода emacsclients с статусом ошибки. (И, конечно, вы можете привязать эту функцию к соответствующей чередующейся последовательности клавиш.)


сноска

В идеале, тогда можно было бы связать функцию выше с крючком на server-kill-buffer чтобы выполнить номер цели (2.) в исходном вопросе. (То есть, убивая буфер, не сохраняя его C-x # должен погасить те же ошибки, что и выходы emacsclient.)

Однако мои попытки добавить это к kill-buffer-hook потерпели неудачу, поскольку server-kill-buffer функция помещается на передней панели kill-buffer-hook после server-visit-hook перехватчики были запущены, и поэтому по умолчанию server-kill-buffer функция будет работать в первую очередь. (Можно было исправить kill-buffer-hook после этого, но я еще не уверен, куда поместить код для этого в поток управления Elisp.)

Обновление: Хорошо, вот очень хакерский способ выполнить вышеизложенное:

(defun kill-buffer-with-special-emacsclient-handling ()
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

(global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling)

Обновление 2: Немного более надежный вариант:

(defun kill-buffer-with-special-emacsclient-handling ()
  "Wrapper around kill-buffer that ensures tell-emacsclients-for-buffer-to-die is on the hooks"
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

;; (global-set-key (kbd "C-x k") 'kill-buffer)

(defun install-emacsclient-wrapped-kill-buffer ()
  "Installs wrapped kill-buffer with special emacsclient handling.
Best not to install it unconditionally because the server is not
necessarily running."
  (interactive)
  (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling))

(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer)

3
2018-01-28 15:04



Хорошо, позвольте мне попробовать это и посмотреть, как хорошо это работает. Это то, что я искал. - milkypostman
milkypostman: это сработало для вас? - pnkfelix
tbh Я не помню сейчас. но у меня возникают подобные проблемы, поэтому я попробую еще раз. - milkypostman


Просто нажмите Ctrl+C в терминале, где вы используете bash. Это отменяет издание и подталкивает исходную строку к истории. Если вы не можете сделать это напрямую, потому что Emacs работает в том же терминале, убейте emacsclientпроцесс по вашему выбору.


1
2018-06-10 23:39



это хорошо. есть ли простой способ убить клиентский процесс изнутри emacs? это было бы еще лучше, не так ли? выглядит сложно server.el - milkypostman