Subject: Re: bug#46240: Sorting order of read-char-by-name

From: Juri Linkov <[email-masked]>
Date: Wed, 03 Feb 2021 19:27:54 +0200

> So maybe we need this to be an opt-in behavior.

Here is an option for this:

diff --git a/etc/NEWS b/etc/NEWS
index 7cdb9d9430..0ff78e58e1 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -850,6 +850,11 @@ iso-transl RET', it supports the same key sequences as 'C-x 8',
 so e.g. like 'C-x 8 [' inserts a left single quotation mark,
 'C-x \ [' does the same.
 
+---
+*** New user option 'read-char-by-name-sort-function'.
+It can enable sorting the characters of completion from
+'C-x 8 RET TAB' by codepoints instead of character names.
+
 ---
 *** Improved language transliteration in Malayalam input methods.
 Added a new Mozhi scheme.  The inapplicable ITRANS scheme is now
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 5dc3de4422..6e1e045a4a 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -3083,6 +3083,12 @@ mule--ucs-names-affixation
               (list name (concat (if char (format "%c" char) " ") "\t") "")))
           names))
 
+(defun mule--ucs-names-sort-by-code (names)
+  (let* ((codes-and-names
+          (mapcar (lambda (name) (cons (gethash name ucs-names) name)) names))
+         (sorted (sort codes-and-names (lambda (a b) (< (car a) (car b))))))
+    (mapcar #'cdr sorted)))
+
 (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.
@@ -3104,6 +3110,16 @@ char-from-name
                                            ignore-case))
                 code)))))))
 
+(defcustom read-char-by-name-sort-function nil
+  "Function to sort characters displayed by `read-char-by-name' completion."
+  :type '(choice
+          (const :tag "Sort by character names" nil)
+          (const :tag "Sort by character codepoints"
+                 mule--ucs-names-sort-by-code)
+          (function :tag "Custom function"))
+  :group 'mule
+  :version "28.1")
+
 (defun read-char-by-name (prompt)
   "Read a character by its Unicode name or hex number string.
 Display PROMPT and read a string that represents a character by its
@@ -3130,8 +3146,9 @@ read-char-by-name
 	   prompt
 	   (lambda (string pred action)
 	     (if (eq action 'metadata)
-		 '(metadata
+		 `(metadata
 		   (affixation-function . mule--ucs-names-affixation)
+		   (display-sort-function . ,read-char-by-name-sort-function)
 		   (category . unicode-name))
 	       (complete-with-action action (ucs-names) string pred)))))
 	 (char