В относительно текущих версиях Emacs (например, в моей копии Emacs 24.2, но не в дистрибутиве emacs 22.1 для OS X) вы можете написать код 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)