Em versões relativamente atuais do Emacs (por exemplo, na minha cópia do Emacs 24.2, mas não na distribuição do emacs 22.1 do OS X), você pode escrever código Elisp que enviará um comando para o emacsclient dizendo para sair com uma saída de erro status.
Isso é mais fácil do que parece.
Existe uma variável local do buffer, server-buffer-clients
, com os clientes que estão conectados ao buffer. E a função server-send-string
pode ser usada para comunicar comandos seguindo o protocolo server-process-filter
.
Por exemplo:
(server-send-string (car server-buffer-clients) "-error die")
faz com que (um dos) emacsclient (s) associados ao buffer publiquem imediatamente o texto
*ERROR*: die
e saia com o código de saída 1.
Portanto, é muito fácil definir uma função interativa que você poderia chamar do próprio emacs para eliminar os 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")))
Com o acima em seu arquivo .emacs
(e uma versão suficientemente atual do Emacs), você pode invocar M-x tell-emacsclients-for-buffer-to-die
para fazer o emacsclients sair com o status de erro. (E, claro, você poderia vincular essa função a uma sequência de teclas alternativa apropriada.)
Nota de rodapé
O ideal seria, então, acoplar a função acima com um gancho na função server-kill-buffer
para atingir o número da meta (2.) na pergunta original. (Isto é, matar o buffer sem salvá-lo via C-x #
deve disparar o mesmo erro que sai do emacsclient.)
No entanto, minhas tentativas de adicionar isso ao kill-buffer-hook
falharam, porque a função server-kill-buffer
é colocada na frente da lista kill-buffer-hook
depois que os ganchos server-visit-hook
foram executados e, portanto, a% padrão A funçãoserver-kill-buffer
será executada primeiro. (Pode-se consertar o kill-buffer-hook
depois, mas ainda não estou certo de onde colocar o código para fazer isso no fluxo de controle Elisp.)
Atualização: Ok, aqui está uma maneira realmente hacky de realizar o acima:
(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)
Atualização 2: variante ligeiramente mais robusta:
(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)