Multi-stroke Key Bindings

A year ago I wrote about key bindings for switchers explaining how to make home/end and page up/down work (system wide) as most Windows users expect them to work.

Using the same key binding system we can make insertion of the various Apple-centric keyboard glyphs easy. This is useful when we want to cite a keyboard sequence like ⇧⌘V or similar.

If you look in the HTML bundle there is an Entities submenu (depicted below.) This is what I used when writing the TextMate manual, i.e. typing command and pressing tab () to get etc.

HTML Entities Menu

This is fine when we are inside TextMate and writing HTML/Markdown, but when you are getting used to having the key glyphs available, the need for them tend to creep up in other applications as well.

Jacob Rus got the great idea to create a multi-stroke key binding dictionary for inserting these glyphs. The problem would normally be that there are dozens of these glyphs, and we do not have dozens of free key equivalents, but by using multi-stroke key bindings we can hide all of them behind ⌃M.

The format for multi-stroke key bindings is explained here so without further ado here is a key binding dictionary for most Apple-centric glyphs. Credits to Jacob Rus for compiling the dictionary.

You need to save the paste as ~/Library/KeyBindings/DefaultKeyBinding.dict and then relaunch the applications for which you want this to work. If you already have a local key binding file, you need to add the bindings to this, rather than overwrite it.

Note: Key bindings only work for Cocoa applications.

Below is a table of the glyphs and their key sequence using this key binding dictionary. The logic behind the arrow glyphs is that they follow the default (emacs inspired) movement keys, i.e. forward, backward, next (down), previous (up.) As for the other glyphs, they mostly use the first letter of the glyph name, and control (⌃) is used for the “primary” glyph on that key.

Glyph Description Key Sequence
Space ⌃M + ⌃␣
Return ⌃M + ⌃E
Enter ⌃M + E
Tab ⌃M + ⌃T
Backtab ⌃M + T
Delete ⌃M + ⌃D
Forward Delete ⌃M + D
Command (apple)⌃M + ⌃A
Option ⌃M + ⌃O
Control ⌃M + ⌃C
Shift ⌃M + ⌃S
Caps Lock ⌃M + S
Solid Left (back) ⌃M + ⌃B
Solid Right (forward) ⌃M + ⌃F
Solid Up (previous) ⌃M + ⌃P
Solid Down (next) ⌃M + ⌃N
Dotted Left (back) ⌃M + B
Dotted Right (forward)⌃M + F
Dotted Up (previous) ⌃M + P
Dotted Down (next) ⌃M + N
Home ⌃M + ⌃H
End ⌃M + H
Page Up ⌃M + ⌃U
Page Down ⌃M + U
Escape ⌃M + ⌃X
Eject ⌃M + X

17 Comments

  1. 10 Jul 2006 | # djones wrote…

    It's sad that on Windows Enter, Delete, Forward Delete, Command, Option, Control, Escape, and Eject are not supported entities. I think on Internet Explorer only the solid arrows are supported. As a result I've resorted to using images for displaying keyboard glyphs on the web. :4a7d3d609129a9296bf7ac0608c2097

  2. 10 Jul 2006 | # guerom00 wrote…

    That's great but…
    I had a DefaultKeyBinding.dict file previously for Emacs-like search which looked like this :

    {
        /* IncrementalSearchInputManager */
        "^s" = "ISIMincrementalSearch:";
        "^r" = "ISIMreverseIncrementalSearch:";
        "^g" = "abort:";
    
        "^@" = "setMark:";
        "^ " = "setMark:";
        "^w" = "deleteToMark:";
        "^x" = {
            "^x" = "swapWithMark:";
            "^m" = "selectToMark:";
        };
    
    }
    

    Those two files don't seem to be compatible with each others, unfortunately. Is there something I can do to have both glyphs and incremental search ?

  3. 10 Jul 2006 | # Zzen wrote…

    Makes me wonder if there are not more important things to be fixed/extended in/around TextMate. While this may not be the case with Allan and Jacob, I'd say most other people do not have everyday need to insert these special characters.

  4. 10 Jul 2006 | # oliver wrote…

    You do when you're writing documentation for an app.

  5. 11 Jul 2006 | # Jacob Rus wrote…

    djones: that's because most of them are unicode arrows. Apple only includes the ones they need in Lucida Grande. Almost no fonts have more than the most basic unicode arrows.

    guerom: why would it be incompatible? Yours is ⌃X⌃M, the one allan describes is ⌃M⌃X. Two completely different bindings. Incidentally, TM defines ⌃S and ⇧⌃S for incremental search, and I decided to change my default bindings to that just for consistency, ignoring emacs convention.

    Zzen: Aww… everyone needs special characters. Especially if you're trying to explain how use Mac apps on IRC, or in a Manual, or pretty much anywhere online.

  6. 11 Jul 2006 | # Chriztian Steinmeier wrote…

    This was SO easy, and the fun part is that I spent a good two hours yesterday (really) diggin' through various sources, trying to find a way to type these glyphs. As always, the (temporary) fix was to use TextMate (which is always running anyway)… a gazill ion thanks!

  7. 11 Jul 2006 | # Martin Ström wrote…

    Great! I recreated AutoPairs.app functionality using KeyBindings. Read about it here

  8. 12 Jul 2006 | # Jacob Rus wrote…

    Martin: you don't need to use a mark to go forward and back I don't think. Instead you just want:

    "(" = ("insertText:", "()", "moveBackward:");
    

    etc.

  9. 13 Jul 2006 | # guerom00 wrote…

    @ Jacob : you're right. The two are indeed compatible. Thanks.

  10. 22 Jul 2006 | # marios wrote…

    Very useful. One question: I haven't tested all Glyphs yet, but on the return key I get an error:

    /tmp/temp_textmate.3Fofq9:68:in `+': 
      cannot convert nil into String (TypeError)
      from /tmp/temp_textmate.3Fofq9:68
    

    using the suggested key sequence. I checked, wether I have a dict file for key-bindings, but I couldn't find any.

    One other question: what would one best do, to have a key-sequence, that inserts those as Unicode html entities in one go ?

    (I also think that this is very helpful for many folks)

    regards, marios

  11. 23 Jul 2006 | # Allan Odgaard wrote…

    Mario: That error is when you press ⌃M + ⌃E?

    More likely you press ⌃⇧E and get the “Execute Line as Ruby” and the error just relates to what Ruby will give if treating your current line as Ruby.

    As for HTML entities: Have a look in the Entities submenu of the HTML bundle, it has most of these glyphs as well using tab triggers.

  12. 23 Jul 2006 | # marios wrote…

    @Allan,

    Hmm, I checked and used ⌃M + ⌃E. But still no go, that's the only key binding, that doesn't work. Regarding the other question, may be I didn't formulate it correctly.

    What I meant: How fantastic would it be, if you could insert these Glyphs with another hidden key binding, that would insert the Glyph as entity right away. Would it be possible, to extend the dictionary for that, or with a script of some sort ?

    regards, marios

  13. 23 Jul 2006 | # marios wrote…

    Hey, guess what. when I type the T key afterwards, the Glyph suddenly gets inserted. I am using a wireless Microsoft keyboard on my Mac Mini, so problems do sometimes occur. But that one is alien to me. Strange though.

    regards, marios

  14. 23 Jul 2006 | # marios wrote…

    Cancel, that one was the tab glyph, I just confused the Glyphs, so ignore my previous post.

    regards, marios

  15. 08 Nov 2006 | # grant wrote…

    If you already have a DefaultKeyBinding.dict in XML format, add this to it:

    <key>^m</key>
    <dict>
        <key>^ </key>
        <array>
            <string>insertText:</string>
            <string>␣</string>
        </array>
        <key>^e</key>
        <array>
            <string>insertText:</string>
            <string>↩</string>
        </array>
        <key>e</key>
        <array>
            <string>insertText:</string>
            <string>⌅</string>
        </array>
        <key>^t</key>
        <array>
            <string>insertText:</string>
            <string>⇥</string>
        </array>
        <key>t</key>
        <array>
            <string>insertText:</string>
            <string>⇤</string>
        </array>
        <key>^d</key>
        <array>
            <string>insertText:</string>
            <string>⌫</string>
        </array>
        <key>d</key>
        <array>
            <string>insertText:</string>
            <string>⌦</string>
        </array>
        <key>^a</key>
        <array>
            <string>insertText:</string>
            <string>⌘</string>
        </array>
        <key>^o</key>
        <array>
            <string>insertText:</string>
            <string>⌥</string>
        </array>
        <key>^c</key>
        <array>
            <string>insertText:</string>
            <string>⌃</string>
        </array>
        <key>^s</key>
        <array>
            <string>insertText:</string>
            <string>⇧</string>
        </array>
        <key>s</key>
        <array>
            <string>insertText:</string>
            <string>⇪</string>
        </array>
        <key>^b</key>
        <array>
            <string>insertText:</string>
            <string>←</string>
        </array>
        <key>^f</key>
        <array>
            <string>insertText:</string>
            <string>→</string>
        </array>
        <key>^p</key>
        <array>
            <string>insertText:</string>
            <string>↑</string>
        </array>
        <key>^n</key>
        <array>
            <string>insertText:</string>
            <string>↓</string>
        </array>
        <key>f</key>
        <array>
            <string>insertText:</string>
            <string>⇠</string>
        </array>
        <key>b</key>
        <array>
            <string>insertText:</string>
            <string>⇢</string>
        </array>
        <key>p</key>
        <array>
            <string>insertText:</string>
            <string>⇡</string>
        </array>
        <key>n</key>
        <array>
            <string>insertText:</string>
            <string>⇣</string>
        </array>
        <key>^h</key>
        <array>
            <string>insertText:</string>
            <string>↖</string>
        </array>
        <key>h</key>
        <array>
            <string>insertText:</string>
            <string>↘</string>
        </array>
        <key>^u</key>
        <array>
            <string>insertText:</string>
            <string>⇞</string>
        </array>
        <key>u</key>
        <array>
            <string>insertText:</string>
            <string>⇟</string>
        </array>
        <key>^x</key>
        <array>
            <string>insertText:</string>
            <string>⎋</string>
        </array>
        <key>x</key>
        <array>
            <string>insertText:</string>
            <string>⏏</string>
        </array>
    </dict>
    
  16. 01 Dec 2006 | # Eric C wrote…

    Hello and thanks for this tip. Being able to reproduce the Mac modifier key glyphs will be most helpful supporting Mac newbs which I do a lot of. Just one thing I wanted to mention is that you must install the DefaultKeyBinding.dict file at the user level i.e. ~/Library/KeyBindings/DefaultKeyBinding.dict if you install it at the domain level i.e. /Library/KeyBindings/DefaultKeyBinding.dict it will not work. Thanks again.

  17. 29 Oct 2007 | # David G. Kay wrote…

    Hello;

    I have remapped my keyboard using DefaultKeyBinding.dict; my bindings are similar in flavor to Emacs (though not the same keys). They work fine in TextEdit and XPad; they work mostly fine in Mail and Pages.

    But in TextMate, it appears to me that the Mark and Select-to-Mark commands aren't implemented; at least, my bindings for them just give me an invalid-keystroke beep. Am I missing something, or are there plans to implement these in the future?

    Thanks,

    –DGK

Comments closed, you can use the mailing list for discussion.