From: Jim Porter <jporterbugs@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 58909@debbugs.gnu.org
Subject: bug#58909: 29.0.50; [WIP PATCH] Deleting the last frame of an emacsclient doesn't ask to save
Date: Mon, 31 Oct 2022 12:28:23 -0700 [thread overview]
Message-ID: <53238b5b-3e0a-3dfe-eeba-f37cafa81f50@gmail.com> (raw)
In-Reply-To: <83zgdcduxm.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 1757 bytes --]
On 10/31/2022 5:44 AM, Eli Zaretskii wrote:
>> Date: Sun, 30 Oct 2022 15:29:30 -0700
>> From: Jim Porter <jporterbugs@gmail.com>
>>
>> However, if you use 'C-x 5 0' instead, that terminates the Emacs client,
>> but *doesn't* prompt to save foo.txt. I think it should prompt in this
>> case too: all three of 'C-x #', 'C-x C-c', and 'C-x 5 0' have the effect
>> (in this simple case) of deleting the Emacs client and returning to the
>> calling process. (A user who wanted to bail out of an Emacs client
>> without saving should use 'sever-edit-abort' instead.)
>
> I'm uneasy with this incompatible behavior change. I can think of
> some legitimate use cases where "C-x 5 0" should not prompt, e.g., if
> the user intends to keep editing the file, and no application is
> waiting for the client to finish. Why break such flows?
After thinking about this some more, I realized that I didn't properly
address this part of your message. If no application is waiting for the
client to finish, then the user hopefully used "--no-wait" when starting
emacsclient. We could avoid prompting in that case.[1]
If an application *is* waiting for the client to finish, then
"--no-wait" would be unset. In that case, prompting the user has some
value. See the attached patch. (I changed the code to only prompt when
deleting the last frame of a *non-nowait* client.)
[1] Currently, 'C-x C-c' from a nowait frame prompts via
'save-some-buffers' (so long as there's another frame; see
'server-save-buffers-kill-terminal'). Maybe we could avoid prompting
then too? After prompting, it just calls 'delete-frame', so it's very
similar to 'C-x 5 0' in this scenario... Still, as you say, it's
probably good to be careful about making incompatible changes here.
[-- Attachment #2: 0001-When-deleting-the-last-frame-of-an-Emacs-client-ask-.patch --]
[-- Type: text/plain, Size: 3898 bytes --]
From 68b9f41685256870f3409ea468971ee0b64cf136 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Sat, 29 Oct 2022 20:40:49 -0700
Subject: [PATCH] When deleting the last frame of an Emacs client, ask to save
* src/frame.c (delete_frame): Call 'delete-frame-functions' with
'call2' instead of 'safe_call2' to allow hooks to quit, cancelling the
frame's deletion.
* lisp/server.el (server-save-some-buffers): New function...
(server-handle-delete-frame, server-save-buffers-kill-terminal):
... use it.
---
lisp/server.el | 33 ++++++++++++++++++++-------------
src/frame.c | 2 +-
2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/lisp/server.el b/lisp/server.el
index 90d97c1538..f04f993426 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -479,12 +479,26 @@ server-unselect-display
(when (buffer-live-p buffer)
(kill-buffer buffer)))))
+(defun server-save-some-buffers (proc &optional arg)
+ "Save modified file-visiting buffers from the emacsclient file list.
+PROC is the emacsclient process. If ARG is non-nil, save all
+with no questions."
+ (let ((buffers (process-get proc 'buffers)))
+ (save-some-buffers
+ arg (if buffers
+ ;; Only files from emacsclient file list.
+ (lambda () (memq (current-buffer) buffers))
+ ;; If there's no emacsclient file list: don't override
+ ;; `save-some-buffers-default-predicate' (unless ARG is
+ ;; non-nil).
+ (and arg t)))))
+
(defun server-handle-delete-frame (frame)
"Delete the client connection when the emacsclient frame is deleted.
\(To be used from `delete-frame-functions'.)"
(let ((proc (frame-parameter frame 'client)))
(when (and (frame-live-p frame)
- proc
+ (processp proc)
;; See if this is the last frame for this client.
(not (seq-some
(lambda (f)
@@ -492,7 +506,9 @@ server-handle-delete-frame
(eq proc (frame-parameter f 'client))))
(frame-list))))
(server-log (format "server-handle-delete-frame, frame %s" frame) proc)
- (server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
+ (server-save-some-buffers proc))
+ ;; Let delete-frame delete the frame later.
+ (server-delete-client proc 'noframe)))
(defun server-handle-suspend-tty (terminal)
"Notify the client process that its tty device is suspended."
@@ -1752,17 +1768,8 @@ server-save-buffers-kill-terminal
;; 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)))
+ (server-save-some-buffers proc arg)
+ (server-delete-client proc))
(t (error "Invalid client frame"))))))
(defun server-stop-automatically--handle-delete-frame (frame)
diff --git a/src/frame.c b/src/frame.c
index f076a5ba54..8a85d5a400 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2037,7 +2037,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
x_clipboard_manager_save_frame (frame);
#endif
- safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
+ call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
}
/* delete_frame_functions may have deleted any frame, including this
--
2.25.1
next prev parent reply other threads:[~2022-10-31 19:28 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-30 22:29 bug#58909: 29.0.50; [WIP PATCH] Deleting the last frame of an emacsclient doesn't ask to save Jim Porter
2022-10-31 12:44 ` Eli Zaretskii
2022-10-31 17:36 ` Jim Porter
2022-10-31 18:25 ` Eli Zaretskii
2022-10-31 19:38 ` Jim Porter
2022-10-31 19:52 ` Eli Zaretskii
2022-10-31 20:28 ` Jim Porter
2022-11-01 6:17 ` Eli Zaretskii
2022-10-31 19:28 ` Jim Porter [this message]
2022-10-31 19:43 ` Eli Zaretskii
2022-10-31 20:01 ` Jim Porter
2022-10-31 20:21 ` Eli Zaretskii
2022-10-31 21:06 ` Jim Porter
2022-11-01 6:39 ` Eli Zaretskii
2022-11-01 16:11 ` Jim Porter
2022-11-01 22:39 ` Jim Porter
2022-11-02 12:16 ` Eli Zaretskii
2022-11-02 16:36 ` Jim Porter
2022-11-02 17:11 ` Eli Zaretskii
2022-11-02 18:17 ` Jim Porter
2022-11-02 18:42 ` Eli Zaretskii
2022-11-02 19:16 ` Jim Porter
2022-11-02 19:23 ` Eli Zaretskii
2022-11-02 19:57 ` Jim Porter
2022-11-02 20:09 ` Eli Zaretskii
2022-11-02 22:09 ` bug#58909: 29.0.50; [PATCH] " Jim Porter
2022-11-03 6:25 ` Eli Zaretskii
2022-11-06 20:23 ` Jim Porter
2022-11-08 14:47 ` Eli Zaretskii
2022-11-08 15:08 ` Robert Pluim
2022-11-08 15:13 ` Eli Zaretskii
2022-11-08 15:29 ` Robert Pluim
2022-11-08 16:52 ` Jim Porter
2022-11-09 10:06 ` Robert Pluim
2022-11-17 5:17 ` Jim Porter
2023-09-07 21:03 ` bug#58909: 29.0.50; [WIP PATCH] " Stefan Kangas
2023-09-08 1:21 ` Jim Porter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53238b5b-3e0a-3dfe-eeba-f37cafa81f50@gmail.com \
--to=jporterbugs@gmail.com \
--cc=58909@debbugs.gnu.org \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.