I have in my .emacs:

(when (>= emacs-major-version 23)
  (define-key global-map "\C-x8g" (lambda nil (interactive) (ucs-insert `,(cdr (assoc-string "HRYVNIA SIGN" (ucs-names) t)))))
  (define-key global-map "\C-x8e" (lambda nil (interactive) (ucs-insert `,(cdr (assoc-string "EURO SIGN" (ucs-names) t)))))

and with Cygwin Emacs-w32 v26 for:

(assoc-string "EURO SIGN" (ucs-names) t)

I get nil. Is it a bug? How can I get character by Unicode symbol name compatible with Emacs 24/25/26?

  • I do wonder: why are you poking around in ucs-names? What prevents you from just doing (insert-char ?₴) directly?
    – rpluim
    Commented Jul 19, 2018 at 8:11
  • 1
    My .emacs had -*- coding: cp1251 -*- in 2008... I've changed it to utf-8 but habits have remained since that time.
    – gavenkoa
    Commented Jul 19, 2018 at 8:44
  • 1
    You can use Unicode escape syntax: (insert-char ?\N{HRYVNIA SIGN})
    – link0ff
    Commented Jul 31, 2019 at 23:10

2 Answers 2


Do this, instead, starting with Emacs 26:

(gethash "EURO SIGN" (ucs-names))

In other words, use something like this:

(if (> emacs-major-version 25)
    (gethash "EURO SIGN" (ucs-names))
  (cdr (assoc-string "EURO SIGN" (ucs-names) t)))

Unfortunately, for people trying to provide backward-compatibility, they made an incompatible change in ucs-names, from using an alist to using a hash table, in Emacs 26.

Using a hash table is a good idea (more performant), but it breaks backward-compatibility.

They could have made ucs-names test the Emacs version and do the right thing for each version, but (unfortunately) Emacs Dev apparently didn't care about backward compatibility in this case, even though providing compatibility is simple here.

  • "Emacs Dev doesn't really care about backward compatibility" - hmm, that's not my experience. It feels like you're generalizing from this specific case, which to me looks like it was an oversight.
    – npostavs
    Commented Jul 30, 2019 at 19:29
  • Updated to be specific to this case - thanks. IMO it's also the case more generally that backward compatibility is not always a very high priority. But yes, backward compatibility is considered. Let's just say that it's not considered as much as I would like.
    – Drew
    Commented Jul 30, 2019 at 20:57
  • My imagination must be failing me today: how could ucs-names have switched to using a hash table whilst maintaining backward compatibility? Or are you saying the hash table version should have had a different name?
    – rpluim
    Commented Jul 31, 2019 at 8:44

I ended with:

(defun my--get-char (name)
  "Get character by Unicode `name'."
   ((>= 26 emacs-major-version)
    (gethash name (ucs-names)))
   ((>= 23 emacs-major-version)
    (cdr (assoc-string name (ucs-names))))
   (t (error "Emacs version is too old and lacks Unicode support..."))))

(when (>= emacs-major-version 23)
  (define-key global-map "\C-x8g" (lambda nil (interactive) (ucs-insert (my--get-char "HRYVNIA SIGN"))))
  (define-key global-map "\C-x8e" (lambda nil (interactive) (ucs-insert (my--get-char "EURO SIGN"))))
  • 2
    Why the t as default value for the gethash call? Do you really want it to return t if the char cannot be found? E.g., (gethash "NONSENSE" (ucs-names) t) returns t, not a char and not nil. Maybe you meant to use the t with assoc-string, which lets name be any case (lower, upper, mixed)?
    – Drew
    Commented Jul 19, 2018 at 4:01
  • @Drew Fixed, thanks!
    – gavenkoa
    Commented Jul 28, 2019 at 10:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.