Subject: bug#71411: 30.0.50; Show Unicode names when describing translations

From: Robert Pluim <[email-masked]>
Date: Fri, 07 Jun 2024 14:16:38 +0200

>>>>> On Fri, 07 Jun 2024 14:08:33 +0300, Eli Zaretskii <[email-masked]> said:

    Eli> Does this mean that if I type "C-h k a" I will be told that a is LATIN
    Eli> SMALL LETTER A?  That'd be an annoyance, I think.

Thatʼs not a translated binding, so no.

Let me attach the patches.

Robert
-- 
>From 847d582f89110f8c2f0e88c1533ced0606970fba Mon Sep 17 00:00:00 2001
From: Robert Pluim <[email-masked]>
Date: Fri, 7 Jun 2024 12:05:34 +0200
Subject: [PATCH 1/3] Add 'char-to-name' convenience function
To: [email-masked]

* lisp/international/mule-cmds.el (char-to-name): New function.  This is
the inverse of 'char-from-name'.
* doc/lispref/nonascii.texi (Character Codes): Document it.
* etc/NEWS: Announce it.
---
 doc/lispref/nonascii.texi       | 5 +++++
 etc/NEWS                        | 4 ++++
 lisp/international/mule-cmds.el | 7 +++++++
 3 files changed, 16 insertions(+)

diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index b33082e2b24..195b818c0bd 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -435,6 +435,11 @@ Character Codes
 @end example
 @end defun
 
+@defun char-to-name char
+This function returns the Unicode name of @var{char}.  Returns
+@code{nil} if @var{char} is not a character or has no Unicode name.
+@end defun
+
 @defun get-byte &optional pos string
 This function returns the byte at character position @var{pos} in the
 current buffer.  If the current buffer is unibyte, this is literally
diff --git a/etc/NEWS b/etc/NEWS
index 5fb1625a76c..c63e231f44f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2186,6 +2186,10 @@ it returns a short "unique" string that identifies the function.
 In either case, the string is propertized so clicking on it gives
 further details.
 
+** New function 'char-to-name'.
+This is a convenience function to return the Unicode name of a char (if
+it has one).
+
 ** New function 'cl-type-of'.
 This function is like 'type-of' except that it sometimes returns
 a more precise type.  For example, for nil and t it returns 'null'
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index e80c42f523a..7d784ef3b1b 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -3183,6 +3183,13 @@ mule--ucs-names-group
            (script (and char (aref char-script-table char))))
       (if script (symbol-name script) "ungrouped"))))
 
+(defun char-to-name (char)
+  "Return the Unicode name for CHAR, if it has one, else nil.
+Return nil if CHAR is not a character."
+  (and (characterp char)
+       (or (get-char-code-property char 'name)
+           (get-char-code-property char 'old-name))))
+
 (defun char-from-name (string &optional ignore-case)
   "Return a character as a number from its Unicode name STRING.
 If optional IGNORE-CASE is non-nil, ignore case in STRING.
-- 
2.39.2

>From 5ff4c3ac95d8dfcc172ad36f0ebd9c12443c9046 Mon Sep 17 00:00:00 2001
From: Robert Pluim <[email-masked]>
Date: Fri, 7 Jun 2024 12:07:50 +0200
Subject: [PATCH 2/3] Use 'char-to-name'
To: [email-masked]

* lisp/international/emoji.el (emoji--name): Lookup name using 'char-to-name'.
* lisp/international/textsec.el (textsec-domain-suspicious-p): And here.
* lisp/simple.el (what-cursor-position): And here.
---
 lisp/international/emoji.el   | 2 +-
 lisp/international/textsec.el | 2 +-
 lisp/simple.el                | 3 +--
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el
index 4f3aab5a6be..cbf7c547f4c 100644
--- a/lisp/international/emoji.el
+++ b/lisp/international/emoji.el
@@ -245,7 +245,7 @@ emoji--fontify-glyph
 
 (defun emoji--name (glyph)
   (or (gethash glyph emoji--names)
-      (get-char-code-property (aref glyph 0) 'name)))
+      (char-to-name (aref glyph 0))))
 
 (defvar-keymap emoji-list-mode-map
   "RET" #'emoji-list-select
diff --git a/lisp/international/textsec.el b/lisp/international/textsec.el
index 4740dd81345..224363732fe 100644
--- a/lisp/international/textsec.el
+++ b/lisp/international/textsec.el
@@ -296,7 +296,7 @@ textsec-domain-suspicious-p
                             ""
                           (concat ": " (string char)))
                         char
-                        (get-char-code-property char 'name)))))
+                        (char-to-name char)))))
      domain)
     ;; Does IDNA allow it?
     (unless (puny-highly-restrictive-domain-p domain)
diff --git a/lisp/simple.el b/lisp/simple.el
index 68209eadc41..8d7e379b584 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1827,8 +1827,7 @@ what-cursor-position
   (interactive "P")
   (let* ((char (following-char))
          (char-name (and what-cursor-show-names
-                         (or (get-char-code-property char 'name)
-                             (get-char-code-property char 'old-name))))
+                         (char-to-name char)))
          (char-name-fmt (if char-name
                             (format ", %s" char-name)
                           ""))
-- 
2.39.2

>From a2adb11e15a60ad30741c6cd8c47f03b5b1a902e Mon Sep 17 00:00:00 2001
From: Robert Pluim <[email-masked]>
Date: Fri, 7 Jun 2024 12:21:11 +0200
Subject: [PATCH 3/3] Show character names when describing translations
To: [email-masked]

This implements Bug#71411.

* lisp/help.el (help-key-description): Use 'char-to-name' to show the
Unicode name of translated keys.
(help--describe-command): And here.

* etc/NEWS: Announce the change.
---
 etc/NEWS     | 14 ++++++++++++++
 lisp/help.el |  9 +++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index c63e231f44f..66bc4d741ff 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -182,6 +182,20 @@ This user option controls outline visibility in the output buffer of
 *** 'C-h m' ('describe-mode') uses outlining by default.
 Set 'describe-mode-outline' to nil to get back the old behavior.
 
+*** 'C-h k' ('describe-key') shows Unicode name.
+For translated keys only, this will now show the Unicode name of the
+translation, e.g. 'C-h k C-x 8 E' will now show
+
+    € 'EURO SIGN' (translated from C-x 8 E)
+
+*** 'C-h b' ('describe-bindings') shows Unicode names.
+For translated keys only, Unicode names will now be shown, i.e.
+
+    A-!			¡	INVERTED EXCLAMATION MARK
+    A-$			¤	CURRENCY SIGN
+
+and so on.
+
 ** Outline mode
 
 *** New commands to show/hide outlines by regexp.
diff --git a/lisp/help.el b/lisp/help.el
index 2feb178ff6c..878dd404256 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -883,7 +883,9 @@ help-key-description
       (let ((otherstring (help--key-description-fontified untranslated)))
 	(if (equal string otherstring)
 	    string
-	  (format "%s (translated from %s)" string otherstring))))))
+          (if-let ((char-name (char-to-name (aref string 0))))
+              (format "%s '%s' (translated from %s)" string char-name otherstring)
+            (format "%s (translated from %s)" string otherstring)))))))
 
 (defun help--binding-undefined-p (defn)
   (or (null defn) (integerp defn) (equal defn #'undefined)))
@@ -1664,7 +1666,10 @@ help--shadow-lookup
 (defun help--describe-command (definition &optional translation)
   (cond ((or (stringp definition) (vectorp definition))
          (if translation
-             (insert (key-description definition nil) "\n")
+             (insert (concat (key-description definition nil)
+                             (when-let ((char-name (char-to-name (aref definition 0))))
+                               (format "\t%s" char-name))
+                             "\n"))
            ;; These should be rare nowadays, replaced by `kmacro's.
            (insert "Keyboard Macro\n")))
         ((keymapp definition)
-- 
2.39.2