From 5fc9250f02cbb26d6c2765a3fa7893f66fa4e6c5 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-inhibit-blink): Add option to let user explicitly opt into or out of blinking point and mark. (region-stands-out-p): New function to detect "if the region is highlighted", leveraging face-differs-from-default-p. (indicate-copied-region): Use it. * etc/NEWS: Announce user option. --- etc/NEWS | 13 +++++++++++++ lisp/faces.el | 11 ++++++++++- lisp/simple.el | 21 +++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index e0175bacfdf..b69b5af9101 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -59,6 +59,19 @@ This allows the user to customize the prompt that is appended by * Editing Changes in Emacs 30.1 +--- +** New user option 'copy-region-inhibit-blink. +By default, when copying a region with 'kill-ring-save', Emacs +refrains from blinking point and mark when the region is denoted +visually, that is, when the region is active, and the 'region' face is +visibly distinct from the 'default' face. + +The way Emacs evaluated this latter condition sometimes yielded false +negatives, so point and mark would blink despite the region being +active and visually distinct. The false negative was fixed; users who +consider blinking unconditionally to be a feature can now set this +user option to 'ignore'. + --- ** 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..b5e6255fca9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5871,6 +5871,24 @@ copy-region-blink-delay :group 'killing :version "28.1") +(defcustom copy-region-inhibit-blink #'region-stands-out-p + "Whether we should refrain from blinking the cursor after a copy. +When this condition holds, `kill-ring-save' will not blink the +cursor between point and mark to denote the copied region." + :type '(radio (function-item region-stands-out-p) + (function-item :doc "Always inhibit: never blink point and mark." always) + (function-item :doc "Never inhibit: always blink point and mark." ignore) + (function :tag "Other predicate function.")) + :group 'killing + :version "30.1") + +(defun region-stands-out-p () + "Whether the region can be distinguished visually. +This takes into account whether the region is active, and whether +the `region' face displays differently from the default face." + (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 +5909,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)))) + (not (funcall copy-region-inhibit-blink))) ;; Swap point and mark. (set-marker (mark-marker) (point) (current-buffer)) (goto-char mark) -- 2.39.0