From 7b2563acc064586b674f68abd4eebd11b568e76b Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sun, 9 Oct 2022 14:50:06 -0700 Subject: [PATCH 2/2] [WIP] Add hooks before/after deleting Emacs clients * lisp/server.el (server-before-delete-client-functions) (server-after-delete-client-functions): New defcustoms. (server-delete-client): New argument ARG. Handle 'nowait' value for PROC. Run the above hooks. (server-save-buffers-kill-terminal): Extract buffer-saving code from here... (server-save-some-buffers): ... to this new function. --- lisp/server.el | 78 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/lisp/server.el b/lisp/server.el index 5034a8e8c6..c1a64d6f32 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -191,6 +191,18 @@ server-done-hook "Hook run when done editing a buffer for the Emacs server." :type 'hook) +;;;###autoload +(defcustom server-before-delete-client-functions '(server-save-some-buffers) + "Functions to run before deleting an Emacs client. +The functions are run with two arguments: the client process +being deleted and an arg indicating whether to silently save." + :type 'hook) + +(defcustom server-after-delete-client-functions nil + "Functions to run after deleting an Emacs client. +Functions are run with one argument: the client process just deleted." + :type 'hook) + (defvar server-process nil "The current server process.") @@ -318,13 +330,25 @@ server-with-environment process-environment))) (progn ,@body)))) -(defun server-delete-client (proc &optional noframe) +(defun server-delete-client (proc &optional noframe arg) "Delete PROC, including its buffers, terminals and frames. If NOFRAME is non-nil, let the frames live. Updates `server-clients'." (server-log (concat "server-delete-client" (if noframe " noframe")) proc) - ;; Force a new lookup of client (prevents infinite recursion). - (when (memq proc server-clients) + (cond + ((eq proc 'nowait) + (run-hook-with-args-until-success + 'server-before-delete-client-functions proc arg) + (if (cdr (frame-list)) + (delete-frame) + ;; If we're the last frame standing, kill Emacs. + (kill-emacs arg)) + (run-hook-with-args 'server-after-delete-client-functions proc)) + + ;; Force a new lookup of client (prevents infinite recursion). + ((memq proc server-clients) + (run-hook-with-args-until-success + 'server-before-delete-client-functions proc arg) (let ((buffers (process-get proc 'buffers))) ;; Kill the client's buffers. @@ -373,7 +397,8 @@ server-delete-client (if (eq (process-status proc) 'open) (delete-process proc)) - (server-log "Deleted" proc)))) + (server-log "Deleted" proc) + (run-hook-with-args 'server-after-delete-client-functions proc))))) (defvar server-log-time-function #'current-time-string "Function to generate timestamps for `server-buffer'.") @@ -1738,29 +1763,28 @@ server-save-buffers-kill-terminal If emacsclient was started with a list of filenames to edit, then only these files will be asked to be saved." - (if server-stop-automatically - (server-stop-automatically--handle-delete-frame (selected-frame)) - (let ((proc (frame-parameter nil 'client))) - (cond ((eq proc 'nowait) - ;; Nowait frames have no client buffer list. - (if (cdr (frame-list)) - (progn (save-some-buffers arg) - (delete-frame)) - ;; If we're the last frame standing, kill Emacs. - (save-buffers-kill-emacs arg))) - ((processp proc) - (let ((buffers (process-get proc 'buffers))) - (save-some-buffers - arg (if buffers - ;; Only files from emacsclient file list. - (lambda () (memq (current-buffer) buffers)) - ;; No emacsclient file list: don't override - ;; `save-some-buffers-default-predicate' (unless - ;; ARG is non-nil), since we're not killing - ;; Emacs (unlike `save-buffers-kill-emacs'). - (and arg t))) - (server-delete-client proc))) - (t (error "Invalid client frame")))))) + (let ((proc (frame-parameter nil 'client))) + (unless (or (eq proc 'nowait) + (processp proc)) + (error "Invalid client frame")) + (server-delete-client proc nil arg))) + +(defun server-save-some-buffers (proc arg) + "Save buffers associated with PROC. +A non-nil ARG means save all without questions (see +`save-some-buffers')." + (if (eq proc 'nowait) + (save-some-buffers arg) + (let ((buffers (process-get proc 'buffers))) + (save-some-buffers + arg (if buffers + ;; Only files from emacsclient file list. + (lambda () (memq (current-buffer) buffers)) + ;; No emacsclient file list: don't override + ;; `save-some-buffers-default-predicate' (unless ARG is + ;; non-nil), since we're not killing Emacs (unlike + ;; `save-buffers-kill-emacs'). + (and arg t)))))) (defun server-stop-automatically--handle-delete-frame (frame) "Handle deletion of FRAME when `server-stop-automatically' is used." -- 2.25.1