* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom @ 2022-11-29 4:23 Jim Porter 2022-12-01 17:08 ` Eli Zaretskii 0 siblings, 1 reply; 10+ messages in thread From: Jim Porter @ 2022-11-29 4:23 UTC (permalink / raw) To: 59668 [-- Attachment #1: Type: text/plain, Size: 1318 bytes --] The manual says: The Emacs server can optionally be stopped automatically when certain conditions are met. To do this, call the function @code{server-stop-automatically} in your init file (@pxref{Init File}), with one of the following arguments... It'd be nice if this were a defcustom so that people who prefer the Customize interface could use that instead of editing their init files. Here's a patch for that. I've tried to make sure this is as robust as possible, so that everything is always properly set, especially when adjusting the value in the Customize UI. It should even work correctly if a user stopped the server temporarily and restarted it (you might do this to clear out old clients, do some work, and then make the server available again). Maybe this last bit is a little paranoid, but it was minimal extra work compared to getting the Customize part working. One question though: should this only go on the master branch, or should it go into the 29 branch? To me, it seems like it could go either way, though I think it'd be nice to make this easier for users in 29. I'll do whatever the maintainers think is best though. If it goes on the master branch only, I'll add back the function form of 'server-stop-automatically' for compatibility, and then mark it obsolete. [-- Attachment #2: 0001-Make-server-stop-automatically-into-a-defcustom.patch --] [-- Type: text/plain, Size: 9042 bytes --] From d1273ad3170514bc28460b32886a6b4d7615742b Mon Sep 17 00:00:00 2001 From: Jim Porter <jporterbugs@gmail.com> Date: Sun, 27 Nov 2022 22:21:10 -0800 Subject: [PATCH] Make 'server-stop-automatically' into a defcustom * lisp/server.el (server-stop-automatically): Convert the variable to a defcustom. Remove the function. (server-stop-automatically--timer): New variable. (server-apply-stop-automatically): New function. (server-stop, server-start): Call 'server-apply-stop-automatically'. (server-save-buffers-kill-terminal): Adjust 'server-stop-automatically' conditional. (server-stop-automatically--handle-delete-frame) (server-stop-automatically--maybe-kill-emacs): Update docstrings. * doc/emacs/misc.texi (Emacs Server): Update documentation. --- doc/emacs/misc.texi | 13 +++---- lisp/server.el | 89 +++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 29c0bed19c..e3c013acb1 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1808,26 +1808,25 @@ Emacs Server emacs --daemon=foo @end example -@findex server-stop-automatically +@vindex server-stop-automatically The Emacs server can optionally be stopped automatically when -certain conditions are met. To do this, call the function -@code{server-stop-automatically} in your init file (@pxref{Init -File}), with one of the following arguments: +certain conditions are met. To do this, set the option +@code{server-stop-automatically} to one of the following values: @itemize @item -With the argument @code{empty}, the server is stopped when it has no +With the value @code{empty}, the server is stopped when it has no clients, no unsaved file-visiting buffers and no running processes anymore. @item -With the argument @code{delete-frame}, when the last client frame is +With the value @code{delete-frame}, when the last client frame is being closed, you are asked whether each unsaved file-visiting buffer must be saved and each unfinished process can be stopped, and if so, the server is stopped. @item -With the argument @code{kill-terminal}, when the last client frame is +With the value @code{kill-terminal}, when the last client frame is being closed with @kbd{C-x C-c} (@code{save-buffers-kill-terminal}), you are asked whether each unsaved file-visiting buffer must be saved and each unfinished process can be stopped, and if so, the server is diff --git a/lisp/server.el b/lisp/server.el index 1b027f88ce..dac07dfa35 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -273,6 +273,11 @@ server-client-instructions :version "28.1" :type 'boolean) +(defvar server-stop-automatically) ; Defined below to avoid recursive load. + +(defvar server-stop-automatically--timer nil + "The timer object for `server-stop-automatically--maybe-kill-emacs'.") + ;; We do not use `temporary-file-directory' here, because emacsclient ;; does not read the init file. (defvar server-socket-dir @@ -636,7 +641,8 @@ server-stop (setq stopped-p t server-process nil server-mode nil - global-minor-modes (delq 'server-mode global-minor-modes))) + global-minor-modes (delq 'server-mode global-minor-modes)) + (server-apply-stop-automatically)) (unwind-protect ;; Delete the socket files made by previous server ;; invocations. @@ -757,6 +763,7 @@ server-start (list :family 'local :service server-file :plist '(:authenticated t))))) + (server-apply-stop-automatically) (unless server-process (error "Could not start server process")) (server-log "Started server") (process-put server-process :server-file server-file) @@ -1769,9 +1776,6 @@ server-switch-buffer (when server-raise-frame (select-frame-set-input-focus (window-frame))))) -(defvar server-stop-automatically nil - "Internal status variable for `server-stop-automatically'.") - ;;;###autoload (defun server-save-buffers-kill-terminal (arg) ;; Called from save-buffers-kill-terminal in files.el. @@ -1780,7 +1784,8 @@ 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 + (if (and (daemonp) + (memq server-stop-automatically '(kill-terminal delete-frame)) (server-stop-automatically--handle-delete-frame (selected-frame)) (let ((proc (frame-parameter nil 'client))) (cond ((eq proc 'nowait) @@ -1805,7 +1810,7 @@ server-save-buffers-kill-terminal (t (error "Invalid client frame")))))) (defun server-stop-automatically--handle-delete-frame (frame) - "Handle deletion of FRAME when `server-stop-automatically' is used." + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." (when server-stop-automatically (if (if (and (processp (frame-parameter frame 'client)) (eq this-command 'save-buffers-kill-terminal)) @@ -1828,7 +1833,7 @@ server-stop-automatically--handle-delete-frame (delete-frame frame))))) (defun server-stop-automatically--maybe-kill-emacs () - "Handle closing of Emacs daemon when `server-stop-automatically' is used." + "Handle closing of Emacs daemon when `server-stop-automatically' is `empty'." (unless (cdr (frame-list)) (when (and (not (memq t (mapcar (lambda (b) @@ -1842,41 +1847,61 @@ server-stop-automatically--maybe-kill-emacs (process-list))))) (kill-emacs)))) -;;;###autoload -(defun server-stop-automatically (arg) - "Automatically stop server as specified by ARG. - -If ARG is the symbol `empty', stop the server when it has no +(defun server-apply-stop-automatically () + "Apply the current value of `server-stop-automatically'. +This function adds or removes the necessary helpers to manage +stopping the Emacs server automatically, depending on the whether +the server is running or not. This function only applies when +running Emacs as a daemon." + (when (daemonp) + (let (empty-timer-p delete-frame-p) + (when server-process + (pcase server-stop-automatically + ('empty (setq empty-timer-p t)) + ('delete-frame (setq delete-frame-p t)))) + ;; Start or stop the timer. + (if empty-timer-p + (unless server-stop-automatically--timer + (setq server-stop-automatically--timer + (run-with-timer + 10 2 + #'server-stop-automatically--maybe-kill-emacs))) + (when server-stop-automatically--timer + (cancel-timer server-stop-automatically--timer) + (setq server-stop-automatically--timer nil))) + ;; Add or remove the delete-frame hook. + (if delete-frame-p + (add-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame) + (remove-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame))))) + +(defcustom server-stop-automatically nil + "If non-nil, stop the server under the requested conditions. + +If this is the symbol `empty', stop the server when it has no remaining clients, no remaining unsaved file-visiting buffers, and no running processes with a `query-on-exit' flag. -If ARG is the symbol `delete-frame', ask the user when the last +If this is the symbol `delete-frame', ask the user when the last frame is deleted whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' flag can be stopped, and if so, stop the server itself. -If ARG is the symbol `kill-terminal', ask the user when the +If this is the symbol `kill-terminal', ask the user when the terminal is killed with \\[save-buffers-kill-terminal] \ whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' -flag can be stopped, and if so, stop the server itself. - -Any other value of ARG will cause this function to signal an error. - -This function is meant to be called from the user init file." - (when (daemonp) - (setq server-stop-automatically arg) - (cond - ((eq arg 'empty) - (setq server-stop-automatically nil) - (run-with-timer 10 2 - #'server-stop-automatically--maybe-kill-emacs)) - ((eq arg 'delete-frame) - (add-hook 'delete-frame-functions - #'server-stop-automatically--handle-delete-frame)) - ((eq arg 'kill-terminal)) - (t - (error "Unexpected argument"))))) +flag can be stopped, and if so, stop the server itself." + :type '(choice + (const :tag "Never" nil) + (const :tag "When empty" empty) + (const :tag "When killing last terminal" kill-terminal) + (const :tag "When killing last terminal or frame" delete-frame)) + :set (lambda (symbol value) + (set-default symbol value) + (server-apply-stop-automatically)) + :version "29.1") (define-key ctl-x-map "#" 'server-edit) -- 2.25.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-11-29 4:23 bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom Jim Porter @ 2022-12-01 17:08 ` Eli Zaretskii 2022-12-01 18:33 ` Jim Porter 2022-12-02 3:30 ` Jim Porter 0 siblings, 2 replies; 10+ messages in thread From: Eli Zaretskii @ 2022-12-01 17:08 UTC (permalink / raw) To: Jim Porter; +Cc: 59668 > Date: Mon, 28 Nov 2022 20:23:17 -0800 > From: Jim Porter <jporterbugs@gmail.com> > > The Emacs server can optionally be stopped automatically when > certain conditions are met. To do this, call the function > @code{server-stop-automatically} in your init file (@pxref{Init > File}), with one of the following arguments... > > It'd be nice if this were a defcustom so that people who prefer the > Customize interface could use that instead of editing their init files. > Here's a patch for that. Thanks. > One question though: should this only go on the master branch, or should > it go into the 29 branch? To me, it seems like it could go either way, > though I think it'd be nice to make this easier for users in 29. I'll do > whatever the maintainers think is best though. Let's not start installing new features on the release branch. We have enough new stuff there already. Besides, the changes you suggest are hardly trivial, and saying just "make a function into a defcustom" doesn't come close to describing it, IMO. So please install on master, once you take care of the comments below. > If it goes on the master branch only, I'll add back the function form of > 'server-stop-automatically' for compatibility, and then mark it obsolete. I see no reason to make the function obsolete. It does not harm to have both a variable and a function by the same name. > -@findex server-stop-automatically > +@vindex server-stop-automatically > The Emacs server can optionally be stopped automatically when > -certain conditions are met. To do this, call the function > -@code{server-stop-automatically} in your init file (@pxref{Init > -File}), with one of the following arguments: > +certain conditions are met. To do this, set the option > +@code{server-stop-automatically} to one of the following values: > > @itemize > @item > -With the argument @code{empty}, the server is stopped when it has no > +With the value @code{empty}, the server is stopped when it has no > clients, no unsaved file-visiting buffers and no running processes > anymore. > > @item > -With the argument @code{delete-frame}, when the last client frame is > +With the value @code{delete-frame}, when the last client frame is > being closed, you are asked whether each unsaved file-visiting buffer > must be saved and each unfinished process can be stopped, and if so, > the server is stopped. This @itemize list should be converted to a @table, formatted like this: @item empty This value caused the server to be stopped when... @item delete-frame This value means that when the last client frame is deleted... etc., I guess you get the idea. > @@ -1780,7 +1784,8 @@ 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 > + (if (and (daemonp) > + (memq server-stop-automatically '(kill-terminal delete-frame)) Why is this needed? I guess I don't understand why non-trivial code changes are in a patch that was supposed to just add a defcustom? > +(defun server-apply-stop-automatically () > + "Apply the current value of `server-stop-automatically'. > +This function adds or removes the necessary helpers to manage > +stopping the Emacs server automatically, depending on the whether > +the server is running or not. This function only applies when > +running Emacs as a daemon." And why this significant refactoring of the original function? was there something wrong with it? ^ permalink raw reply [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-01 17:08 ` Eli Zaretskii @ 2022-12-01 18:33 ` Jim Porter 2022-12-01 18:41 ` Jim Porter 2022-12-02 3:30 ` Jim Porter 1 sibling, 1 reply; 10+ messages in thread From: Jim Porter @ 2022-12-01 18:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668 On 12/1/2022 9:08 AM, Eli Zaretskii wrote: >> Date: Mon, 28 Nov 2022 20:23:17 -0800 >> From: Jim Porter <jporterbugs@gmail.com> >> >> One question though: should this only go on the master branch, or should >> it go into the 29 branch? To me, it seems like it could go either way, >> though I think it'd be nice to make this easier for users in 29. I'll do >> whatever the maintainers think is best though. > > Let's not start installing new features on the release branch. ... Sounds good to me. >> If it goes on the master branch only, I'll add back the function form of >> 'server-stop-automatically' for compatibility, and then mark it obsolete. > > I see no reason to make the function obsolete. It does not harm to have > both a variable and a function by the same name. Fine by me. The function will just be a one-liner anyway: (setopt server-stop-automatically arg). > This @itemize list should be converted to a @table, formatted like this: > > @item empty > This value caused the server to be stopped when... > > @item delete-frame > This value means that when the last client frame is deleted... > > etc., I guess you get the idea. Will do. I made the minimal set of changes to the manual, but while I'm here, I agree that it would be good to improve things further. >> @@ -1780,7 +1784,8 @@ 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 >> + (if (and (daemonp) >> + (memq server-stop-automatically '(kill-terminal delete-frame)) > > Why is this needed? I guess I don't understand why non-trivial code changes > are in a patch that was supposed to just add a defcustom? It's due to a change in the meaning of the 'server-stop-automatically' value. Previously, it was an internal variable that was set to nil after calling "(server-stop-automatically 'empty)", or when calling 'server-stop-automatically' in a non-daemon session. Since 'server-stop-automatically' is now a defcustom, that means that a) it can really be set to 'empty', and b) it can be non-nil in non-daemon sessions. So this extra code is just to account for the change in meaning. I could make a helper function that returns the same value as the *old* version of the 'server-stop-automatically' variable; either way has the same meaning. I could also keep the old variable around, possibly renamed to something like 'server-stop-automatically--kill-terminal', but I think a helper function would be cleaner. >> +(defun server-apply-stop-automatically () >> + "Apply the current value of `server-stop-automatically'. >> +This function adds or removes the necessary helpers to manage >> +stopping the Emacs server automatically, depending on the whether >> +the server is running or not. This function only applies when >> +running Emacs as a daemon." > > And why this significant refactoring of the original function? was there > something wrong with it? The previous implementation was limited in that you could call it once, but you couldn't necessarily call it a second time to change the setting. For example, this would put you in an inconsistent state: (server-stop-automatically 'delete-frame) (server-stop-automatically 'empty) After this, the 'empty' setting would be enabled, and the 'delete-frame' setting would still be partially-enabled too. That wasn't so much of a problem when you'd just call this function only once in your init file, but for the Customize interface, I think it's important to make sure that users can set the defcustom multiple times, e.g. if they change their minds while customizing it. The changes for 'server-apply-stop-automatically' are to support that. As you said, these changes are more extensive than "just" adding a defcustom, but all the other changes are there to support the Customize interface. ^ permalink raw reply [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-01 18:33 ` Jim Porter @ 2022-12-01 18:41 ` Jim Porter 0 siblings, 0 replies; 10+ messages in thread From: Jim Porter @ 2022-12-01 18:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668 On 12/1/2022 10:33 AM, Jim Porter wrote: > I could make a helper function that returns the same value as the *old* > version of the 'server-stop-automatically' variable; either way has the > same meaning. Oops, the bit after the semicolon should be "this would do the same thing as the current conditional." ^ permalink raw reply [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-01 17:08 ` Eli Zaretskii 2022-12-01 18:33 ` Jim Porter @ 2022-12-02 3:30 ` Jim Porter 2022-12-02 14:42 ` Eli Zaretskii 1 sibling, 1 reply; 10+ messages in thread From: Jim Porter @ 2022-12-02 3:30 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668 [-- Attachment #1: Type: text/plain, Size: 1077 bytes --] On 12/1/2022 9:08 AM, Eli Zaretskii wrote: > I see no reason to make the function obsolete. It does not harm to have > both a variable and a function by the same name. Ok, fixed. I've added back a 'server-stop-automatically' function that just sets the variable. > This @itemize list should be converted to a @table, formatted like this: > > @item empty > This value caused the server to be stopped when... > > @item delete-frame > This value means that when the last client frame is deleted... Done. >> @@ -1780,7 +1784,8 @@ 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 >> + (if (and (daemonp) >> + (memq server-stop-automatically '(kill-terminal delete-frame)) > > Why is this needed? I guess I don't understand why non-trivial code changes > are in a patch that was supposed to just add a defcustom? Addressed in my other message, but I've added a defsubst to make this clearer (I hope). [-- Attachment #2: 0001-Make-server-stop-automatically-into-a-defcustom.patch --] [-- Type: text/plain, Size: 10111 bytes --] From c0f245bffa7243ad14118e1b6145c7b0e0b3cd3f Mon Sep 17 00:00:00 2001 From: Jim Porter <jporterbugs@gmail.com> Date: Sun, 27 Nov 2022 22:21:10 -0800 Subject: [PATCH] Make 'server-stop-automatically' into a defcustom * lisp/server.el (server-stop-automatically): Convert the variable to a defcustom, and make the function simply set the defcustom. (server-stop-automatically--timer): New variable. (server-stop-automatically--when-killing-terminal): (server-apply-stop-automatically): New functions. (server-stop, server-start): Call 'server-apply-stop-automatically'. (server-save-buffers-kill-terminal): Adjust 'server-stop-automatically' conditional. (server-stop-automatically--handle-delete-frame) (server-stop-automatically--maybe-kill-emacs): Update docstrings. * doc/emacs/misc.texi (Emacs Server): Update documentation. --- doc/emacs/misc.texi | 41 +++++++++---------- lisp/server.el | 96 ++++++++++++++++++++++++++++++--------------- 2 files changed, 84 insertions(+), 53 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 29c0bed19c..702c72bac2 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1808,31 +1808,28 @@ Emacs Server emacs --daemon=foo @end example -@findex server-stop-automatically +@vindex server-stop-automatically The Emacs server can optionally be stopped automatically when -certain conditions are met. To do this, call the function -@code{server-stop-automatically} in your init file (@pxref{Init -File}), with one of the following arguments: +certain conditions are met. To do this, set the option +@code{server-stop-automatically} to one of the following values: -@itemize -@item -With the argument @code{empty}, the server is stopped when it has no -clients, no unsaved file-visiting buffers and no running processes -anymore. - -@item -With the argument @code{delete-frame}, when the last client frame is -being closed, you are asked whether each unsaved file-visiting buffer -must be saved and each unfinished process can be stopped, and if so, -the server is stopped. - -@item -With the argument @code{kill-terminal}, when the last client frame is -being closed with @kbd{C-x C-c} (@code{save-buffers-kill-terminal}), -you are asked whether each unsaved file-visiting buffer must be saved -and each unfinished process can be stopped, and if so, the server is +@table @code +@item empty +This value causes the server to be stopped when it has no clients, no +unsaved file-visiting buffers and no running processes anymore. + +@item delete-frame +This value means that when the last client frame is being closed, you +are asked whether each unsaved file-visiting buffer must be saved and +each unfinished process can be stopped, and if so, the server is stopped. -@end itemize + +@item kill-terminal +This value means that when the last client frame is being closed with +@kbd{C-x C-c} (@code{save-buffers-kill-terminal}), you are asked +whether each unsaved file-visiting buffer must be saved and each +unfinished process can be stopped, and if so, the server is stopped. +@end table @findex server-eval-at If you have defined a server by a unique server name, it is possible diff --git a/lisp/server.el b/lisp/server.el index 1b027f88ce..e16a9e464e 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -273,6 +273,11 @@ server-client-instructions :version "28.1" :type 'boolean) +(defvar server-stop-automatically) ; Defined below to avoid recursive load. + +(defvar server-stop-automatically--timer nil + "The timer object for `server-stop-automatically--maybe-kill-emacs'.") + ;; We do not use `temporary-file-directory' here, because emacsclient ;; does not read the init file. (defvar server-socket-dir @@ -636,7 +641,8 @@ server-stop (setq stopped-p t server-process nil server-mode nil - global-minor-modes (delq 'server-mode global-minor-modes))) + global-minor-modes (delq 'server-mode global-minor-modes)) + (server-apply-stop-automatically)) (unwind-protect ;; Delete the socket files made by previous server ;; invocations. @@ -757,6 +763,7 @@ server-start (list :family 'local :service server-file :plist '(:authenticated t))))) + (server-apply-stop-automatically) (unless server-process (error "Could not start server process")) (server-log "Started server") (process-put server-process :server-file server-file) @@ -1769,8 +1776,10 @@ server-switch-buffer (when server-raise-frame (select-frame-set-input-focus (window-frame))))) -(defvar server-stop-automatically nil - "Internal status variable for `server-stop-automatically'.") +(defsubst server-stop-automatically--when-killing-terminal () + "Return non-nil if we should potentially stop Emacs when killing a terminal." + (and (daemonp) + (memq server-stop-automatically '(kill-terminal delete-frame)))) ;;;###autoload (defun server-save-buffers-kill-terminal (arg) @@ -1780,7 +1789,7 @@ 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 + (if (server-stop-automatically--when-killing-terminal) (server-stop-automatically--handle-delete-frame (selected-frame)) (let ((proc (frame-parameter nil 'client))) (cond ((eq proc 'nowait) @@ -1805,7 +1814,7 @@ server-save-buffers-kill-terminal (t (error "Invalid client frame")))))) (defun server-stop-automatically--handle-delete-frame (frame) - "Handle deletion of FRAME when `server-stop-automatically' is used." + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." (when server-stop-automatically (if (if (and (processp (frame-parameter frame 'client)) (eq this-command 'save-buffers-kill-terminal)) @@ -1828,7 +1837,7 @@ server-stop-automatically--handle-delete-frame (delete-frame frame))))) (defun server-stop-automatically--maybe-kill-emacs () - "Handle closing of Emacs daemon when `server-stop-automatically' is used." + "Handle closing of Emacs daemon when `server-stop-automatically' is `empty'." (unless (cdr (frame-list)) (when (and (not (memq t (mapcar (lambda (b) @@ -1842,41 +1851,66 @@ server-stop-automatically--maybe-kill-emacs (process-list))))) (kill-emacs)))) -;;;###autoload -(defun server-stop-automatically (arg) - "Automatically stop server as specified by ARG. - -If ARG is the symbol `empty', stop the server when it has no +(defun server-apply-stop-automatically () + "Apply the current value of `server-stop-automatically'. +This function adds or removes the necessary helpers to manage +stopping the Emacs server automatically, depending on the whether +the server is running or not. This function only applies when +running Emacs as a daemon." + (when (daemonp) + (let (empty-timer-p delete-frame-p) + (when server-process + (pcase server-stop-automatically + ('empty (setq empty-timer-p t)) + ('delete-frame (setq delete-frame-p t)))) + ;; Start or stop the timer. + (if empty-timer-p + (unless server-stop-automatically--timer + (setq server-stop-automatically--timer + (run-with-timer + 10 2 + #'server-stop-automatically--maybe-kill-emacs))) + (when server-stop-automatically--timer + (cancel-timer server-stop-automatically--timer) + (setq server-stop-automatically--timer nil))) + ;; Add or remove the delete-frame hook. + (if delete-frame-p + (add-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame) + (remove-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame))))) + +(defcustom server-stop-automatically nil + "If non-nil, stop the server under the requested conditions. + +If this is the symbol `empty', stop the server when it has no remaining clients, no remaining unsaved file-visiting buffers, and no running processes with a `query-on-exit' flag. -If ARG is the symbol `delete-frame', ask the user when the last +If this is the symbol `delete-frame', ask the user when the last frame is deleted whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' flag can be stopped, and if so, stop the server itself. -If ARG is the symbol `kill-terminal', ask the user when the +If this is the symbol `kill-terminal', ask the user when the terminal is killed with \\[save-buffers-kill-terminal] \ whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' -flag can be stopped, and if so, stop the server itself. - -Any other value of ARG will cause this function to signal an error. - -This function is meant to be called from the user init file." - (when (daemonp) - (setq server-stop-automatically arg) - (cond - ((eq arg 'empty) - (setq server-stop-automatically nil) - (run-with-timer 10 2 - #'server-stop-automatically--maybe-kill-emacs)) - ((eq arg 'delete-frame) - (add-hook 'delete-frame-functions - #'server-stop-automatically--handle-delete-frame)) - ((eq arg 'kill-terminal)) - (t - (error "Unexpected argument"))))) +flag can be stopped, and if so, stop the server itself." + :type '(choice + (const :tag "Never" nil) + (const :tag "When empty" empty) + (const :tag "When killing last terminal" kill-terminal) + (const :tag "When killing last terminal or frame" delete-frame)) + :set (lambda (symbol value) + (set-default symbol value) + (server-apply-stop-automatically)) + :version "29.1") + +(defun server-stop-automatically (value) + "Automatically stop the Emacs server as specified by VALUE. +This sets the variable `server-stop-automatically' (which see)." + (setopt server-stop-automatically value)) (define-key ctl-x-map "#" 'server-edit) -- 2.25.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-02 3:30 ` Jim Porter @ 2022-12-02 14:42 ` Eli Zaretskii 2022-12-07 1:39 ` Jim Porter 0 siblings, 1 reply; 10+ messages in thread From: Eli Zaretskii @ 2022-12-02 14:42 UTC (permalink / raw) To: Jim Porter; +Cc: 59668 > Date: Thu, 1 Dec 2022 19:30:03 -0800 > Cc: 59668@debbugs.gnu.org > From: Jim Porter <jporterbugs@gmail.com> > > @@ -1805,7 +1814,7 @@ server-save-buffers-kill-terminal > (t (error "Invalid client frame")))))) > > (defun server-stop-automatically--handle-delete-frame (frame) > - "Handle deletion of FRAME when `server-stop-automatically' is used." > + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." > (when server-stop-automatically > (if (if (and (processp (frame-parameter frame 'client)) > (eq this-command 'save-buffers-kill-terminal)) > @@ -1828,7 +1837,7 @@ server-stop-automatically--handle-delete-frame > (delete-frame frame))))) AFAIU, this delete-frame is called after save-buffers-kill-emacs, which is strange: there will be no Emacs to perform this call after that. What am I missing? > + (const :tag "When empty" empty) "When empty" doesn't explain itself well enough. Can we come up with a better description? Otherwise LGTM, thanks. ^ permalink raw reply [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-02 14:42 ` Eli Zaretskii @ 2022-12-07 1:39 ` Jim Porter 2022-12-07 1:49 ` Jim Porter 2022-12-07 12:48 ` Eli Zaretskii 0 siblings, 2 replies; 10+ messages in thread From: Jim Porter @ 2022-12-07 1:39 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668 [-- Attachment #1: Type: text/plain, Size: 1498 bytes --] On 12/2/2022 6:42 AM, Eli Zaretskii wrote: >> Date: Thu, 1 Dec 2022 19:30:03 -0800 >> Cc: 59668@debbugs.gnu.org >> From: Jim Porter <jporterbugs@gmail.com> >> >> @@ -1805,7 +1814,7 @@ server-save-buffers-kill-terminal >> (t (error "Invalid client frame")))))) >> >> (defun server-stop-automatically--handle-delete-frame (frame) >> - "Handle deletion of FRAME when `server-stop-automatically' is used." >> + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." >> (when server-stop-automatically >> (if (if (and (processp (frame-parameter frame 'client)) >> (eq this-command 'save-buffers-kill-terminal)) >> @@ -1828,7 +1837,7 @@ server-stop-automatically--handle-delete-frame >> (delete-frame frame))))) > > AFAIU, this delete-frame is called after save-buffers-kill-emacs, which is > strange: there will be no Emacs to perform this call after that. What am I > missing? Thanks. I think that's just an oversight. I removed it in my patch for bug#51993, since this seems more closely-related to that bug. >> + (const :tag "When empty" empty) > > "When empty" doesn't explain itself well enough. Can we come up with a > better description? How about "When empty (no clients, unsaved files, or processes)"? That seems a bit clumsy to me, but I wanted to keep the word "empty" in there somehow, since that's the name of the option value. Attached is an updated patch (rebased on top of my previous patches for bug#51993). [-- Attachment #2: 0001-Make-server-stop-automatically-into-a-defcustom.patch --] [-- Type: text/plain, Size: 11341 bytes --] From 7d9c9bbccf8fdf6851ac3cf5425c564d91919438 Mon Sep 17 00:00:00 2001 From: Jim Porter <jporterbugs@gmail.com> Date: Sun, 27 Nov 2022 22:21:10 -0800 Subject: [PATCH] Make 'server-stop-automatically' into a defcustom This changes the meaning of the (formerly internal) variable 'server-stop-automatically': it now always holds the requested configuration, even when Emacs was not started as a daemon (bug#59668). * lisp/server.el (server-stop-automatically): Convert the variable to a defcustom, and make the function simply set the defcustom. (server-stop-automatically--timer): New variable. (server-apply-stop-automatically): New function... (server-stop, server-start): ... call it. (server-save-buffers-kill-terminal): Adjust the conditions for stopping automatically to account for the change of meaning for 'server-stop-automatically'. (server-stop-automatically--handle-delete-frame): Remove unnecessary test of the 'server-stop-automatically' option; this hook is only set when it should do its job. (server-stop-automatically--maybe-kill-emacs): Update docstring. * doc/emacs/misc.texi (Emacs Server): Update documentation. --- doc/emacs/misc.texi | 41 ++++++++-------- lisp/server.el | 111 +++++++++++++++++++++++++++++--------------- 2 files changed, 93 insertions(+), 59 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 29c0bed19c0..702c72bac25 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1808,31 +1808,28 @@ Emacs Server emacs --daemon=foo @end example -@findex server-stop-automatically +@vindex server-stop-automatically The Emacs server can optionally be stopped automatically when -certain conditions are met. To do this, call the function -@code{server-stop-automatically} in your init file (@pxref{Init -File}), with one of the following arguments: +certain conditions are met. To do this, set the option +@code{server-stop-automatically} to one of the following values: -@itemize -@item -With the argument @code{empty}, the server is stopped when it has no -clients, no unsaved file-visiting buffers and no running processes -anymore. - -@item -With the argument @code{delete-frame}, when the last client frame is -being closed, you are asked whether each unsaved file-visiting buffer -must be saved and each unfinished process can be stopped, and if so, -the server is stopped. - -@item -With the argument @code{kill-terminal}, when the last client frame is -being closed with @kbd{C-x C-c} (@code{save-buffers-kill-terminal}), -you are asked whether each unsaved file-visiting buffer must be saved -and each unfinished process can be stopped, and if so, the server is +@table @code +@item empty +This value causes the server to be stopped when it has no clients, no +unsaved file-visiting buffers and no running processes anymore. + +@item delete-frame +This value means that when the last client frame is being closed, you +are asked whether each unsaved file-visiting buffer must be saved and +each unfinished process can be stopped, and if so, the server is stopped. -@end itemize + +@item kill-terminal +This value means that when the last client frame is being closed with +@kbd{C-x C-c} (@code{save-buffers-kill-terminal}), you are asked +whether each unsaved file-visiting buffer must be saved and each +unfinished process can be stopped, and if so, the server is stopped. +@end table @findex server-eval-at If you have defined a server by a unique server name, it is possible diff --git a/lisp/server.el b/lisp/server.el index aa62b25a891..97265c1a68c 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -273,6 +273,11 @@ server-client-instructions :version "28.1" :type 'boolean) +(defvar server-stop-automatically) ; Defined below to avoid recursive load. + +(defvar server-stop-automatically--timer nil + "The timer object for `server-stop-automatically--maybe-kill-emacs'.") + ;; We do not use `temporary-file-directory' here, because emacsclient ;; does not read the init file. (defvar server-socket-dir @@ -636,7 +641,8 @@ server-stop (setq stopped-p t server-process nil server-mode nil - global-minor-modes (delq 'server-mode global-minor-modes))) + global-minor-modes (delq 'server-mode global-minor-modes)) + (server-apply-stop-automatically)) (unwind-protect ;; Delete the socket files made by previous server ;; invocations. @@ -757,6 +763,7 @@ server-start (list :family 'local :service server-file :plist '(:authenticated t))))) + (server-apply-stop-automatically) (unless server-process (error "Could not start server process")) (server-log "Started server") (process-put server-process :server-file server-file) @@ -1769,9 +1776,6 @@ server-switch-buffer (when server-raise-frame (select-frame-set-input-focus (window-frame))))) -(defvar server-stop-automatically nil - "Internal status variable for `server-stop-automatically'.") - ;;;###autoload (defun server-save-buffers-kill-terminal (arg) ;; Called from save-buffers-kill-terminal in files.el. @@ -1779,11 +1783,19 @@ server-save-buffers-kill-terminal With ARG non-nil, silently save all file-visiting buffers, then kill. If emacsclient was started with a list of filenames to edit, then -only these files will be asked to be saved." - (let ((proc (frame-parameter nil 'client))) +only these files will be asked to be saved. + +When running Emacs as a daemon and with +`server-stop-automatically' (which see) set to `kill-terminal' or +`delete-frame', this function may call `save-buffers-kill-emacs' +if there are no other active clients." + (let ((stop-automatically + (and (daemonp) + (memq server-stop-automatically '(kill-terminal delete-frame)))) + (proc (frame-parameter nil 'client))) (cond ((eq proc 'nowait) ;; Nowait frames have no client buffer list. - (if (length> (frame-list) (if server-stop-automatically 2 1)) + (if (length> (frame-list) (if stop-automatically 2 1)) ;; If there are any other frames, only delete this one. ;; When `server-stop-automatically' is set, don't count ;; the daemon frame. @@ -1792,7 +1804,7 @@ server-save-buffers-kill-terminal ;; If we're the last frame standing, kill Emacs. (save-buffers-kill-emacs arg))) ((processp proc) - (if (or (not server-stop-automatically) + (if (or (not stop-automatically) (length> server-clients 1) (seq-some (lambda (frame) @@ -1819,14 +1831,13 @@ server-save-buffers-kill-terminal (t (error "Invalid client frame"))))) (defun server-stop-automatically--handle-delete-frame (frame) - "Handle deletion of FRAME when `server-stop-automatically' is used." - (when (and server-stop-automatically - (null (cddr (frame-list)))) + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." + (when (null (cddr (frame-list))) (let ((server-stop-automatically nil)) (save-buffers-kill-emacs)))) (defun server-stop-automatically--maybe-kill-emacs () - "Handle closing of Emacs daemon when `server-stop-automatically' is used." + "Handle closing of Emacs daemon when `server-stop-automatically' is `empty'." (unless (cdr (frame-list)) (when (and (not (memq t (mapcar (lambda (b) @@ -1840,41 +1851,67 @@ server-stop-automatically--maybe-kill-emacs (process-list))))) (kill-emacs)))) -;;;###autoload -(defun server-stop-automatically (arg) - "Automatically stop server as specified by ARG. - -If ARG is the symbol `empty', stop the server when it has no +(defun server-apply-stop-automatically () + "Apply the current value of `server-stop-automatically'. +This function adds or removes the necessary helpers to manage +stopping the Emacs server automatically, depending on the whether +the server is running or not. This function only applies when +running Emacs as a daemon." + (when (daemonp) + (let (empty-timer-p delete-frame-p) + (when server-process + (pcase server-stop-automatically + ('empty (setq empty-timer-p t)) + ('delete-frame (setq delete-frame-p t)))) + ;; Start or stop the timer. + (if empty-timer-p + (unless server-stop-automatically--timer + (setq server-stop-automatically--timer + (run-with-timer + 10 2 + #'server-stop-automatically--maybe-kill-emacs))) + (when server-stop-automatically--timer + (cancel-timer server-stop-automatically--timer) + (setq server-stop-automatically--timer nil))) + ;; Add or remove the delete-frame hook. + (if delete-frame-p + (add-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame) + (remove-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame))))) + +(defcustom server-stop-automatically nil + "If non-nil, stop the server under the requested conditions. + +If this is the symbol `empty', stop the server when it has no remaining clients, no remaining unsaved file-visiting buffers, and no running processes with a `query-on-exit' flag. -If ARG is the symbol `delete-frame', ask the user when the last +If this is the symbol `delete-frame', ask the user when the last frame is deleted whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' flag can be stopped, and if so, stop the server itself. -If ARG is the symbol `kill-terminal', ask the user when the +If this is the symbol `kill-terminal', ask the user when the terminal is killed with \\[save-buffers-kill-terminal] \ whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' -flag can be stopped, and if so, stop the server itself. - -Any other value of ARG will cause this function to signal an error. - -This function is meant to be called from the user init file." - (when (daemonp) - (setq server-stop-automatically arg) - (cond - ((eq arg 'empty) - (setq server-stop-automatically nil) - (run-with-timer 10 2 - #'server-stop-automatically--maybe-kill-emacs)) - ((eq arg 'delete-frame) - (add-hook 'delete-frame-functions - #'server-stop-automatically--handle-delete-frame)) - ((eq arg 'kill-terminal)) - (t - (error "Unexpected argument"))))) +flag can be stopped, and if so, stop the server itself." + :type '(choice + (const :tag "Never" nil) + (const :tag "When empty (no clients, unsaved files, or processes)" + empty) + (const :tag "When killing last terminal" kill-terminal) + (const :tag "When killing last terminal or frame" delete-frame)) + :set (lambda (symbol value) + (set-default symbol value) + (server-apply-stop-automatically)) + :version "29.1") + +(defun server-stop-automatically (value) + "Automatically stop the Emacs server as specified by VALUE. +This sets the variable `server-stop-automatically' (which see)." + (setopt server-stop-automatically value)) (define-key ctl-x-map "#" 'server-edit) -- 2.25.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-07 1:39 ` Jim Porter @ 2022-12-07 1:49 ` Jim Porter 2022-12-07 12:48 ` Eli Zaretskii 1 sibling, 0 replies; 10+ messages in thread From: Jim Porter @ 2022-12-07 1:49 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668 [-- Attachment #1: Type: text/plain, Size: 181 bytes --] On 12/6/2022 5:39 PM, Jim Porter wrote: > Attached is an updated patch (rebased on top of my previous patches for > bug#51993). Oops. Forgot to save the file after my last change. [-- Attachment #2: 0001-Make-server-stop-automatically-into-a-defcustom.patch --] [-- Type: text/plain, Size: 11433 bytes --] From 68946abc9cd6bec43f04ae85357e701861983b07 Mon Sep 17 00:00:00 2001 From: Jim Porter <jporterbugs@gmail.com> Date: Sun, 27 Nov 2022 22:21:10 -0800 Subject: [PATCH] Make 'server-stop-automatically' into a defcustom This changes the meaning of the (formerly internal) variable 'server-stop-automatically': it now always holds the requested configuration, even when Emacs was not started as a daemon (bug#59668). * lisp/server.el (server-stop-automatically): Convert the variable to a defcustom, and make the function simply set the defcustom. (server-stop-automatically--timer): New variable. (server-apply-stop-automatically): New function... (server-stop, server-start): ... call it. (server-save-buffers-kill-terminal): Adjust the conditions for stopping automatically to account for the change of meaning for 'server-stop-automatically'. (server-stop-automatically--handle-delete-frame): Remove unnecessary test of the 'server-stop-automatically' option; this hook is only set when it should do its job. (server-stop-automatically--maybe-kill-emacs): Update docstring. * doc/emacs/misc.texi (Emacs Server): Update documentation. --- doc/emacs/misc.texi | 41 ++++++++-------- lisp/server.el | 113 +++++++++++++++++++++++++++++--------------- 2 files changed, 95 insertions(+), 59 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 29c0bed19c0..702c72bac25 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1808,31 +1808,28 @@ Emacs Server emacs --daemon=foo @end example -@findex server-stop-automatically +@vindex server-stop-automatically The Emacs server can optionally be stopped automatically when -certain conditions are met. To do this, call the function -@code{server-stop-automatically} in your init file (@pxref{Init -File}), with one of the following arguments: +certain conditions are met. To do this, set the option +@code{server-stop-automatically} to one of the following values: -@itemize -@item -With the argument @code{empty}, the server is stopped when it has no -clients, no unsaved file-visiting buffers and no running processes -anymore. - -@item -With the argument @code{delete-frame}, when the last client frame is -being closed, you are asked whether each unsaved file-visiting buffer -must be saved and each unfinished process can be stopped, and if so, -the server is stopped. - -@item -With the argument @code{kill-terminal}, when the last client frame is -being closed with @kbd{C-x C-c} (@code{save-buffers-kill-terminal}), -you are asked whether each unsaved file-visiting buffer must be saved -and each unfinished process can be stopped, and if so, the server is +@table @code +@item empty +This value causes the server to be stopped when it has no clients, no +unsaved file-visiting buffers and no running processes anymore. + +@item delete-frame +This value means that when the last client frame is being closed, you +are asked whether each unsaved file-visiting buffer must be saved and +each unfinished process can be stopped, and if so, the server is stopped. -@end itemize + +@item kill-terminal +This value means that when the last client frame is being closed with +@kbd{C-x C-c} (@code{save-buffers-kill-terminal}), you are asked +whether each unsaved file-visiting buffer must be saved and each +unfinished process can be stopped, and if so, the server is stopped. +@end table @findex server-eval-at If you have defined a server by a unique server name, it is possible diff --git a/lisp/server.el b/lisp/server.el index aa62b25a891..f6d9a439e32 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -273,6 +273,11 @@ server-client-instructions :version "28.1" :type 'boolean) +(defvar server-stop-automatically) ; Defined below to avoid recursive load. + +(defvar server-stop-automatically--timer nil + "The timer object for `server-stop-automatically--maybe-kill-emacs'.") + ;; We do not use `temporary-file-directory' here, because emacsclient ;; does not read the init file. (defvar server-socket-dir @@ -636,7 +641,8 @@ server-stop (setq stopped-p t server-process nil server-mode nil - global-minor-modes (delq 'server-mode global-minor-modes))) + global-minor-modes (delq 'server-mode global-minor-modes)) + (server-apply-stop-automatically)) (unwind-protect ;; Delete the socket files made by previous server ;; invocations. @@ -757,6 +763,7 @@ server-start (list :family 'local :service server-file :plist '(:authenticated t))))) + (server-apply-stop-automatically) (unless server-process (error "Could not start server process")) (server-log "Started server") (process-put server-process :server-file server-file) @@ -1769,9 +1776,6 @@ server-switch-buffer (when server-raise-frame (select-frame-set-input-focus (window-frame))))) -(defvar server-stop-automatically nil - "Internal status variable for `server-stop-automatically'.") - ;;;###autoload (defun server-save-buffers-kill-terminal (arg) ;; Called from save-buffers-kill-terminal in files.el. @@ -1779,11 +1783,19 @@ server-save-buffers-kill-terminal With ARG non-nil, silently save all file-visiting buffers, then kill. If emacsclient was started with a list of filenames to edit, then -only these files will be asked to be saved." - (let ((proc (frame-parameter nil 'client))) +only these files will be asked to be saved. + +When running Emacs as a daemon and with +`server-stop-automatically' (which see) set to `kill-terminal' or +`delete-frame', this function may call `save-buffers-kill-emacs' +if there are no other active clients." + (let ((stop-automatically + (and (daemonp) + (memq server-stop-automatically '(kill-terminal delete-frame)))) + (proc (frame-parameter nil 'client))) (cond ((eq proc 'nowait) ;; Nowait frames have no client buffer list. - (if (length> (frame-list) (if server-stop-automatically 2 1)) + (if (length> (frame-list) (if stop-automatically 2 1)) ;; If there are any other frames, only delete this one. ;; When `server-stop-automatically' is set, don't count ;; the daemon frame. @@ -1792,7 +1804,7 @@ server-save-buffers-kill-terminal ;; If we're the last frame standing, kill Emacs. (save-buffers-kill-emacs arg))) ((processp proc) - (if (or (not server-stop-automatically) + (if (or (not stop-automatically) (length> server-clients 1) (seq-some (lambda (frame) @@ -1819,14 +1831,13 @@ server-save-buffers-kill-terminal (t (error "Invalid client frame"))))) (defun server-stop-automatically--handle-delete-frame (frame) - "Handle deletion of FRAME when `server-stop-automatically' is used." - (when (and server-stop-automatically - (null (cddr (frame-list)))) + "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'." + (when (null (cddr (frame-list))) (let ((server-stop-automatically nil)) (save-buffers-kill-emacs)))) (defun server-stop-automatically--maybe-kill-emacs () - "Handle closing of Emacs daemon when `server-stop-automatically' is used." + "Handle closing of Emacs daemon when `server-stop-automatically' is `empty'." (unless (cdr (frame-list)) (when (and (not (memq t (mapcar (lambda (b) @@ -1840,41 +1851,69 @@ server-stop-automatically--maybe-kill-emacs (process-list))))) (kill-emacs)))) -;;;###autoload -(defun server-stop-automatically (arg) - "Automatically stop server as specified by ARG. - -If ARG is the symbol `empty', stop the server when it has no +(defun server-apply-stop-automatically () + "Apply the current value of `server-stop-automatically'. +This function adds or removes the necessary helpers to manage +stopping the Emacs server automatically, depending on the whether +the server is running or not. This function only applies when +running Emacs as a daemon." + (when (daemonp) + (let (empty-timer-p delete-frame-p) + (when server-process + (pcase server-stop-automatically + ('empty (setq empty-timer-p t)) + ('delete-frame (setq delete-frame-p t)))) + ;; Start or stop the timer. + (if empty-timer-p + (unless server-stop-automatically--timer + (setq server-stop-automatically--timer + (run-with-timer + 10 2 + #'server-stop-automatically--maybe-kill-emacs))) + (when server-stop-automatically--timer + (cancel-timer server-stop-automatically--timer) + (setq server-stop-automatically--timer nil))) + ;; Add or remove the delete-frame hook. + (if delete-frame-p + (add-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame) + (remove-hook 'delete-frame-functions + #'server-stop-automatically--handle-delete-frame)))) + ;; Return the current value of `server-stop-automatically'. + server-stop-automatically) + +(defcustom server-stop-automatically nil + "If non-nil, stop the server under the requested conditions. + +If this is the symbol `empty', stop the server when it has no remaining clients, no remaining unsaved file-visiting buffers, and no running processes with a `query-on-exit' flag. -If ARG is the symbol `delete-frame', ask the user when the last +If this is the symbol `delete-frame', ask the user when the last frame is deleted whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' flag can be stopped, and if so, stop the server itself. -If ARG is the symbol `kill-terminal', ask the user when the +If this is the symbol `kill-terminal', ask the user when the terminal is killed with \\[save-buffers-kill-terminal] \ whether each unsaved file-visiting buffer must be saved and each running process with a `query-on-exit' -flag can be stopped, and if so, stop the server itself. - -Any other value of ARG will cause this function to signal an error. - -This function is meant to be called from the user init file." - (when (daemonp) - (setq server-stop-automatically arg) - (cond - ((eq arg 'empty) - (setq server-stop-automatically nil) - (run-with-timer 10 2 - #'server-stop-automatically--maybe-kill-emacs)) - ((eq arg 'delete-frame) - (add-hook 'delete-frame-functions - #'server-stop-automatically--handle-delete-frame)) - ((eq arg 'kill-terminal)) - (t - (error "Unexpected argument"))))) +flag can be stopped, and if so, stop the server itself." + :type '(choice + (const :tag "Never" nil) + (const :tag "When empty (no clients, unsaved files, or processes)" + empty) + (const :tag "When killing last terminal" kill-terminal) + (const :tag "When killing last terminal or frame" delete-frame)) + :set (lambda (symbol value) + (set-default symbol value) + (server-apply-stop-automatically)) + :version "29.1") + +(defun server-stop-automatically (value) + "Automatically stop the Emacs server as specified by VALUE. +This sets the variable `server-stop-automatically' (which see)." + (setopt server-stop-automatically value)) (define-key ctl-x-map "#" 'server-edit) -- 2.25.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-07 1:39 ` Jim Porter 2022-12-07 1:49 ` Jim Porter @ 2022-12-07 12:48 ` Eli Zaretskii 2022-12-08 6:02 ` Jim Porter 1 sibling, 1 reply; 10+ messages in thread From: Eli Zaretskii @ 2022-12-07 12:48 UTC (permalink / raw) To: Jim Porter; +Cc: 59668 > Date: Tue, 6 Dec 2022 17:39:52 -0800 > Cc: 59668@debbugs.gnu.org > From: Jim Porter <jporterbugs@gmail.com> > > >> + (const :tag "When empty" empty) > > > > "When empty" doesn't explain itself well enough. Can we come up with a > > better description? > > How about "When empty (no clients, unsaved files, or processes)"? Just leave the text inside the parentheses (but without the parentheses themselves), there's no need to have the "empty part there. > Attached is an updated patch (rebased on top of my previous patches for > bug#51993). OK with the above change. Thanks. ^ permalink raw reply [flat|nested] 10+ messages in thread
* bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom 2022-12-07 12:48 ` Eli Zaretskii @ 2022-12-08 6:02 ` Jim Porter 0 siblings, 0 replies; 10+ messages in thread From: Jim Porter @ 2022-12-08 6:02 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 59668-done On 12/7/2022 4:48 AM, Eli Zaretskii wrote: >> Date: Tue, 6 Dec 2022 17:39:52 -0800 >> Cc: 59668@debbugs.gnu.org >> From: Jim Porter <jporterbugs@gmail.com> >> >> How about "When empty (no clients, unsaved files, or processes)"? > > Just leave the text inside the parentheses (but without the > parentheses themselves), there's no need to have the "empty part there. Ok by me. >> Attached is an updated patch (rebased on top of my previous patches for >> bug#51993). > > OK with the above change. Thanks. Thanks, merged to master as 153c67fa92eaad39410b1809ab9b125616bdc5c1. Closing this bug now. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-12-08 6:02 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-11-29 4:23 bug#59668: 29.0.50; [PATCH] Make 'server-stop-automatically' into a defcustom Jim Porter 2022-12-01 17:08 ` Eli Zaretskii 2022-12-01 18:33 ` Jim Porter 2022-12-01 18:41 ` Jim Porter 2022-12-02 3:30 ` Jim Porter 2022-12-02 14:42 ` Eli Zaretskii 2022-12-07 1:39 ` Jim Porter 2022-12-07 1:49 ` Jim Porter 2022-12-07 12:48 ` Eli Zaretskii 2022-12-08 6:02 ` Jim Porter
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).