>From d767d5c658278bb102dea9a716da7a04dccb34aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= Date: Sun, 29 Jan 2023 11:23:01 +0100 Subject: [PATCH] Avoid spurious pause in kill-ring-save (Bug#60841) 'indicate-copied-region' checks whether the region is "highlighted" and if not, briefly moves point to mark to give a visual cue of the extent of text that was saved to the kill ring. The region is considered "highlighted" if (a) it is active and (b) its face specifies a :background. That latter condition does not account for the multiple ways in which the face can make the region "visually distinct" from the default face, so switch to a more extensive predicate. * lisp/faces.el (face-differs-from-default-p): Filter out :extend; add rationale for the attributes we ignore. * lisp/simple.el (copy-region-blink-predicate): Add option to let user explicitly opt into or out of blinking point and mark. (region-indistinguishable-p): New function to detect "if there is currently no active region highlighting", leveraging face-differs-from-default-p. (indicate-copied-region): Use it. * etc/NEWS: Announce user option. --- etc/NEWS | 12 ++++++++++++ lisp/faces.el | 11 ++++++++++- lisp/simple.el | 22 ++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index e0175bacfdf..6a069b74332 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -59,6 +59,18 @@ This allows the user to customize the prompt that is appended by * Editing Changes in Emacs 30.1 +--- +** New user option 'copy-region-blink-predicate'. +By default, when copying a region with 'kill-ring-save', Emacs only +blinks point and mark when the region is not denoted visually, that +is, when either the region is inactive, or the 'region' face is +indistinguishable from the 'default' face. + +Users who would rather enable blinking unconditionally can now set +this user option to 'always'. To disable blinking unconditionally, +either set this option to 'ignore', or set 'copy-region-blink-delay' +to 0. + --- ** New command 'kill-matching-buffers-no-ask'. This works like 'kill-matching-buffers', but without asking for diff --git a/lisp/faces.el b/lisp/faces.el index 3323eab205a..4933b495a6c 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -304,7 +304,16 @@ face-differs-from-default-p If FRAME is t, report on the defaults for face FACE (for new frames). If FRAME is omitted or nil, use the selected frame." (let ((attrs - (delq :inherit (mapcar 'car face-attribute-name-alist))) + ;; The _value_ of :inherit teaches us nothing about how FACE + ;; looks compared to the default face. Instead, we will ask + ;; `face-attribute' to take inheritance into account when + ;; examining other attributes. + (delq :inherit + ;; A difference in extension past EOL only matters when + ;; relevant attributes (such as :background) also + ;; differ from the default; otherwise this difference + ;; is a false positive. + (delq :extend (mapcar 'car face-attribute-name-alist)))) (differs nil)) (while (and attrs (not differs)) (let* ((attr (pop attrs)) diff --git a/lisp/simple.el b/lisp/simple.el index 7bda368d85d..94b08543f44 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5871,6 +5871,25 @@ copy-region-blink-delay :group 'killing :version "28.1") +(defcustom copy-region-blink-predicate #'region-indistinguishable-p + "Whether the cursor must be blinked after a copy. +When this condition holds, and the copied region fits in the +current window, `kill-ring-save' will blink the cursor between +point and mark for `copy-region-blink-delay' seconds." + :type '(radio (function-item region-indistinguishable-p) + (function-item :doc "Always blink point and mark." always) + (function-item :doc "Never blink point and mark." ignore) + (function :tag "Other predicate function")) + :group 'killing + :version "30.1") + +(defun region-indistinguishable-p () + "Whether the current region is not denoted visually. +This holds when the region is inactive, or when the `region' face +cannot be distinguished from the `default' face." + (not (and (region-active-p) + (face-differs-from-default-p 'region)))) + (defun indicate-copied-region (&optional message-len) "Indicate that the region text has been copied interactively. If the mark is visible in the selected window, blink the cursor between @@ -5891,8 +5910,7 @@ indicate-copied-region ;; was selected. Don't do it if the region is highlighted. (when (and (numberp copy-region-blink-delay) (> copy-region-blink-delay 0) - (or (not (region-active-p)) - (not (face-background 'region nil t)))) + (funcall copy-region-blink-predicate)) ;; Swap point and mark. (set-marker (mark-marker) (point) (current-buffer)) (goto-char mark) -- 2.39.0