+(defvar ucs-names nil
+ "Alist of cached (CHAR-NAME . CHAR-CODE) pairs.")
+
+(defun ucs-names ()
+ "Return alist of (CHAR-NAME . CHAR-CODE) pairs cached in `ucs-names'."
+ (or ucs-names
+ (setq ucs-names
+ (let (name names)
+ (dotimes (c #xEFFFF)
+ (unless (or
+ (and (>= c #x3400 ) (<= c #x4dbf )) ; CJK Ideograph Extension A
+ (and (>= c #x4e00 ) (<= c #x9fff )) ; CJK Ideograph
+ (and (>= c #xd800 ) (<= c #xfaff )) ; Private/Surrogate
+ (and (>= c #x20000) (<= c #x2ffff)) ; CJK Ideograph Extension B
+ )
+ (if (setq name (get-char-code-property c 'name))
+ (setq names (cons (cons name c) names)))
+ (if (setq name (get-char-code-property c 'old-name))
+ (setq names (cons (cons name c) names)))))
+ names))))
+
+(defvar ucs-completions (lazy-completion-table ucs-completions ucs-names)
+ "Lazy completion table for completing on Unicode character names.")
+
+(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
+Unicode property `name' or `old-name'. You can type a few of first
+letters of the Unicode name and use completion. This function also
+accepts a hexadecimal number of Unicode code point or a number in
+hash notation, e.g. #o21430 for octal, #x2318 for hex, or #10r8984
+for decimal. Returns a character as a number."
+ (let* ((completion-ignore-case t)
+ (input (completing-read prompt ucs-completions)))
+ (cond
+ ((string-match "^[0-9a-fA-F]+$" input)
+ (string-to-number input 16))
+ ((string-match "^#" input)
+ (read input))
+ (t
+ (cdr (assoc input (ucs-names)))))))
+