Subject: Re: bug#61413: [PATCH] Make warnings show a "warning" emoji instead of a stop-sign

From: Kévin Le Gouguec <[email-masked]>
Date: Sun, 02 Mar 2025 12:01:15 +0100

Eli Zaretskii <[email-masked]> writes:

>> From: Mauro Aranda <[email-masked]>
>> 
>> Kévin Le Gouguec <[email-masked]> writes:
>> 
>>  > Mauro Aranda <[email-masked]> writes:
>>  >
>>  >> But, now we don't know if the help-echo property was effectively added
>>  >> by the library or it was already there :-(.  Sadness.
>>  >
>>  > Would the attached address that problem?  (To apply on top of the
>>  > previous patch; I'll squash it all if we are happy with it)
>> 
>> Looks good to me, thanks.
>
> If you want me to install some patches, please post them.

Thanks for the nudge; re-attaching the patch that makes button.el
preserve help-echo strings; reviewed by Mauro in two parts¹², then
squashed³.  I can install it if we think that fix is unambiguously good.

There is another (independent) patch in-flight for changing the
presentation of warnings⁴; no feedback on code nor effect yet.
Personally not very invested in it, but I felt it was important to
explore the other ideas raised in this thread (replacing ⛔ with a
regular text button; adding a warning sign).

¹ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=61413#93
² https://debbugs.gnu.org/cgi/bugreport.cgi?bug=61413#99
³ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=61413#102
⁴ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=61413#108

>From 5668adb52c0f97b38cf47cdab77b8ffb4e923706 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= <[email-masked]>
Date: Thu, 20 Feb 2025 22:37:13 +0100
Subject: [PATCH] Prevent button.el from clearing help-echo strings

In order to fix one of the issues discussed in bug#61413, i.e.
'buttonize' clobbering the help-echo property set by
'icon-string'.

This is a reasonable interpretation of the button.el
docstrings - "if HELP-ECHO, use that as the `help-echo'
property"; conversely, if not HELP-ECHO, then do not do
anything, preserving existing values for that property.

* lisp/button.el (button--properties): Only add a help-echo
property if HELP-ECHO is non-nil.  Add an additional property
for bookkeeping.
(unbuttonize-region): Check for that bookkeeping property
before clearing help-echo.
* test/lisp/button-tests.el (button--preserve-help-echo):
Validate these changes.
---
 lisp/button.el            | 32 +++++++++++++++++++++-----------
 test/lisp/button-tests.el | 28 ++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/lisp/button.el b/lisp/button.el
index 674de1bb4fa..58f00c4c2ad 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -652,15 +652,19 @@ buttonize
     string))
 
 (defun button--properties (callback data help-echo)
-  (list 'font-lock-face 'button
-        'mouse-face 'highlight
-        'help-echo help-echo
-        'button t
-        'follow-link t
-        'category t
-        'button-data data
-        'keymap button-map
-        'action callback))
+  (append
+   (list 'font-lock-face 'button
+         'mouse-face 'highlight
+         'button t
+         'follow-link t
+         'category t
+         'button-data data
+         'keymap button-map
+         'action callback)
+   (and help-echo
+        (list 'help-echo help-echo
+              ;; Record that button.el is responsible for this property.
+              'help-echo-button t))))
 
 (defun buttonize-region (start end callback &optional data help-echo)
   "Make the region between START and END into a button.
@@ -681,8 +685,14 @@ unbuttonize-region
     (when (overlay-get o 'button)
       (delete-overlay o)))
   (with-silent-modifications
-    (remove-text-properties start end
-                            (button--properties nil nil nil))
+    (remove-text-properties
+     start end
+     (append
+      (button--properties nil nil nil)
+      ;; Only remove help-echo if it was added by button.el.
+      (and (get-text-property start 'help-echo-button)
+           (list 'help-echo nil
+                 'help-echo-button nil))))
     (add-face-text-property start end
                             'button nil)))
 
diff --git a/test/lisp/button-tests.el b/test/lisp/button-tests.el
index 7f6a5bd52cd..b784cf02e28 100644
--- a/test/lisp/button-tests.el
+++ b/test/lisp/button-tests.el
@@ -101,4 +101,32 @@ button--help-echo-function
       (setq button (insert-button "overlay" 'help-echo help))
       (should (equal (button--help-echo button) "overlay: x")))))
 
+(ert-deftest button--preserve-help-echo ()
+  "Ensure buttonizing functions preserve existing `help-echo' properties."
+  ;; buttonize.
+  (let* ((string (propertize "button text" 'help-echo "help text"))
+         (button (buttonize string #'ignore)))
+    (should (equal (get-text-property 0 'help-echo button)
+                   "help text")))
+  ;; buttonize-region.
+  (with-temp-buffer
+    (insert (propertize "button text" 'help-echo "help text"))
+    (buttonize-region (point-min) (point) #'ignore)
+    (should (equal (get-text-property (point-min) 'help-echo)
+                   "help text"))
+    ;; unbuttonize-region should not clear the property either.
+    (unbuttonize-region (point-min) (point))
+    (should (equal (get-text-property (point-min) 'help-echo)
+                   "help text")))
+  ;; unbuttonize-region should still clear properties applied with
+  ;; buttonize.
+  (with-temp-buffer
+    (insert "button text")
+    (buttonize-region (point-min) (point) #'ignore nil "help text")
+    (should (equal (get-text-property (point-min) 'help-echo)
+                   "help text"))
+    (unbuttonize-region (point-min) (point))
+    (should (equal (get-text-property (point-min) 'help-echo)
+                   nil))))
+
 ;;; button-tests.el ends here
-- 
2.48.1