Dans les versions relativement actuelles d’Emacs (par exemple, dans ma copie d’Emacs 24.2, mais pas dans la distribution d’Emacs 22.1 sous OS X), vous pouvez écrire du code Elisp qui enverra une commande à emacsclient lui indiquant de quitter avec un statut d’exit d’erreur.
C'est plus facile que ça en a l'air.
Il existe une variable locale du tampon server-buffer-clients, avec les clients attachés au tampon. Et la fonction server-send-stringpeut être utilisée pour communiquer des commandes suivant le server-process-filterprotocole.
Par exemple:
(server-send-string (car server-buffer-clients) "-error die")
provoque (un des) emacsclient (s) associé (s) au tampon à émettre immédiatement le texte
*ERROR*: die
puis quittez avec le code de sortie 1.
Donc, il est assez facile de définir une fonction interactive que vous pourriez appeler depuis emacs pour tuer les clients emacs:
(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")))
Avec ce qui précède dans votre .emacsfichier (et une version suffisamment récente d’Emacs), vous pouvez M-x tell-emacsclients-for-buffer-to-diefaire appel pour que les clients emacs soient fermés avec le statut d’erreur. (Et bien sûr, vous pouvez lier cette fonction à une autre séquence de touches appropriée.)
note de bas de page
Idéalement, on couplerait ensuite la fonction ci-dessus avec un crochet server-kill-bufferpour atteindre le nombre d'objectifs (2.) de la question d'origine. (Autrement dit, tuer le tampon sans l'enregistrer via C-x #devrait déclencher les mêmes erreurs que emacsclient.)
Cependant, mes tentatives pour l'ajouter à kill-buffer-hookont échoué, car la server-kill-bufferfonction est placée au premier plan de la kill-buffer-hookliste une fois les server-visit-hookpoints d'ancrage exécutés. La server-kill-bufferfonction par défaut est donc exécutée en premier. (On pourrait réparer la kill-buffer-hooksuite, mais je ne sais pas encore où mettre le code pour le faire dans le flux de contrôle Elisp.)
Mise à jour: d'accord, voici un moyen vraiment déconcertant d'accomplir ce qui précède:
(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)
Mise à jour 2: variante légèrement plus robuste:
(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)