7

I often find myself needing to insert Unicode characters that have no default binding in iso-transl-ctl-x-8-map, i.e., characters that can't be inserted using C-x 8 followed by one or more letters/punctuation characters.

To add bindings to the C-x 8 keymap, I usually

  1. define a custom command for inserting a given Unicode character, such as:

    (defun ucs-rightwards-arrow ()
      "Insert unicode symbol: →"
      (interactive)
      (insert-char #x2192))
    
  2. add a binding for this command to the map via

    (define-key iso-transl-ctl-x-8-map (kbd "a") 'ucs-rightwards-arrow)
    

Since the C-x 8 keymap really only pairs key bindings with single characters I'm wondering:

Q: Is there a more light-weight/idiomatic way of extending the C-x 8 keymap?

Drew
  • 75,699
  • 9
  • 109
  • 225
itsjeyd
  • 14,586
  • 3
  • 58
  • 87

2 Answers2

7

There's no need to define a command to bind a unicode char:

(define-key 'iso-transl-ctl-x-8-map "a" [?α])

binds α to C-x 8 a. While

(define-key 'iso-transl-ctl-x-8-map (kbd "M-s") [?ς])

binds ς to C-x 8 M-s.

Adobe
  • 1,859
  • 13
  • 27
4

Library ucs-cmds.el can help.

It provides a macro, ucsc-make-commands, for quickly creating a set of commands that insert Unicode characters. You provide a regexp to it, which is matched against all Unicode character names (in ucs-names). An insertion command is created for each of the characters whose name matches. (The command names are essentially the same as the char names - see below.)

Sample command creations:

 (ucsc-make-commands "^math") ; Math symbols
 (ucsc-make-commands "latin") ; Latin alphabet characters
 (ucsc-make-commands "arabic")
 (ucsc-make-commands "^cjk")  ; Chinese, Japanese, Korean characters
 (ucsc-make-commands "^box drawings ")
 (ucsc-make-commands "^greek [a-z]+ letter") ; Greek characters
 (ucsc-make-commands "\\(^hangul\\|^circled hangul\\|^parenthesized hangul\\)")

This is the doc string:

ucsc-make-commands is a Lisp macro in `ucs-cmds.el'.

(ucsc-make-commands REGEXP)

Create commands to insert Unicode characters whose names match REGEXP.
Letter case is ignored for matching.

The set of char names used is taken from `ucs-names'.  There are
*many* such chars, so consider using a tighter regexp to limit the
number of commands created.

The commands created have the same names as the chars they insert,
except that `SPC' chars in the character names are replaced by
hyphens (`-'), and the command names are lowercase.

If you wanted to bind the commands you create to keys in a systematic way, then you could easily create a macro based on the code of ucsc-make-commands that both creates the commands you want and binds them. Macro ucsc-make-commands just iterates over all of the Unicode cars and creates commands for those whose names match the REGEXP argument.

During an iteration you have access to the character name and its code point. Figure out a convenient regular mapping of either code points or char names to keys, and your macro can add the appropriate define-keys in addition to the command defuns.


The library also provides a command, ucsc-insert, that can replace vanilla command insert-char. The behavior and code of ucsc-insert are identical to those of insert-char except for what happens when you use a negative prefix argument:

  1. It acts as if the prefix-arg value was positive. So a value of -3 inserts three copies of the character, just as 3 does.

  2. In addition to inserting the character, it defines a command that you can use thereafter to insert that character. You can use a prefix argument with that command to insert multiple copies of the given character.

This gives you a command that is tailor-made to insert a given Unicode character. You can then bind the command to a key sequence, effectively adding Unicode characters to your keyboard.

Whenever insert-char does anything (it does nothing for a negative prefix arg), ucsc-insert does the same thing. Because of this, you can bind ucsc-insert to C-x 8 RET as a replacement for insert-char:

(define-key global-map [remap insert-char] 'ucsc-insert)

If you need only a few such commands for inserting particular Unicode characters, then using ucsc-insert to define them is sufficiently convenient. If you need a lot of such commands then macro ucsc-make-commands is your friend.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks, `ucsc-insert` looks like it could help cover my use cases. Defining new commands interactively (via `M--` `M-x` `ucsc-insert` `RET` `#x2190` `RET`) works fine, but when I try to execute them (after binding them via `(define-key iso-transl-ctl-x-8-map (kbd "b") 'left-arrow)`) I get "Wrong type argument: wholenump, nil". Could you give an example of how `ucsc-insert` can be used to programmatically define a binding for a specific Unicode character? – itsjeyd Jan 11 '15 at 12:22
  • Right you are! There was a bug here. Fixed now on Emacs Wiki [`ucs-cmds.el`](http://www.emacswiki.org/emacs/download/ucs-cmds.el). Should be mirrored to MELPA within 24 hours. **Thx.** – Drew Jan 11 '15 at 17:32
  • Glad I was able to help you find and fix a bug :) I can now define and bind commands for inserting specific Unicode symbols via `(ucsc-insert #x2192 -1) (define-key ctl-x-map (kbd "8 a") 'right-arrow)`, which is definitely more concise than my original approach. I need to ask, however, if this is the *intended* way of using `ucsc-insert` to define commands for Unicode symbols that persist across sessions? I have a feeling it might not be, because it causes Emacs to insert characters for which I am defining custom commands into the `*scratch*` buffer at start-up... – itsjeyd Jan 11 '15 at 21:41
  • The intended use of `ucsc-insert` is for it to behave just like `ucs-insert`, aka `insert-char`, unless you use a negative prefix arg - *it always inserts a char*. If you do not want to insert a char, but just want to define a command to insert a char, then you could use macro `ucsc-make-commands`. But you are right (again) that it would be good to have a function that just defines a single command. So I added function (command) `ucsc-define-char-insert-cmd`. E.g.: `(ucsc-define-char-insert-cmd 8592)` defines the command and returns its symbol, `left-arrow`. Please try the latest. Thx. – Drew Jan 11 '15 at 23:22
  • Thanks, will try it out once the update makes it into MELPA! – itsjeyd Jan 12 '15 at 15:25
  • Pardon my n00b question, but I have inserted this `(ucsc-make-commands "^greek [a-z]+ letter")` into my .emacs file, and it errors. if I add `require "ucs-cmds"` it does not find the file. Plus, even when I do, It's not really clear to me how to actually type the Greek keys (or whatever) or if I have to make additional keymappings. – jjmerelo Dec 26 '16 at 12:03
  • As always, to `require` a library you need to put its directory in your `load-path` - e.g., `(add-to-list 'load-path "/PATH/TO/MY/DIR/")`. `ucsc-make-commands` defines a command for each such char (in this case, greek letters). Just bind whichever of those commands you want to whichever keys you want - see the Emacs manual, node [Key Bindings](http://www.gnu.org/software/emacs/manual/html_node/emacs/Key-Bindings.html) and its subnodes. – Drew Dec 26 '16 at 16:34