Typewriter ImageI love the keyboard, and I love keyboard shortcuts. It’s one of the reasons TextMate and I get along so well. There’s one thing that bothers me any time I’m editing text (in any application), though: having to move my right hand all the way over to the arrow keys just to move forward a couple of characters, say, after an auto-paired set of parenthesis that I want to get out of.

I know, it’s stupid for two reasons: first, it’s just not that big a deal, and second, I could just use the Emacs keybindings (^F,^B,^P,^N, etc.). Well, to that I say “phooey” on both counts. It is a big deal; I’ve probably lost hours of my life to that motion. As to the latter, I didn’t grow up on Emacs, and those shortcuts have just never nestled into my muscle memory. In related news, I already have some of those keys bound elsewhere.

I used to use KeyRemap4Macbook to map control-j,i,l and m to the cursor keys, but haven’t installed it since my last clean wipe (just in case it was part of the reason I had to do the clean wipe to begin with). I missed that convenience, though, so after 15 minutes of Googling, here’s the answer…

Allan Odgaard, creator of TextMate, offers the beginning of the solution on the TextMate blog. I found a little more detailed information around the net, too. Basically, you can add or edit a file called DefaultKeyBinding.dict in ~/Library/KeyBindings/ to add the keystrokes to all Cocoa applications. Mine looks like this now:

{
  "^j" = "moveBackward:";
  "^l" = "moveForward:";
  "^m" = "moveDown:";
  "^i" = "moveUp:";
  "^E" = "\"editInTextMate:\"";
}

The first part of each pair is the keystroke, and the second part is the action. To find a list of the available actions, I just looked at /System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict, which has all of the default OS X keybindings in it. You’ll need Property List Editor to view the file in its default state. To view the file in a text editor, you have to convert it to an XML (old school and plain text) plist. If you’re curious, copy the file to your Desktop and, in Terminal, run plutil -convert xml1 ~/Desktop/StandardKeyBinding.dict.

After editing DefaultKeyBinding.dict and restarting your Cocoa apps, your new keyboard shortcuts will be available. That’s when I found the next problem. TextMate has ^J mapped to “Reformat and Justify” under the Text menu. I never, ever use that command, so that was just annoying. I first tried to just override it in System Preferences->Keyboard->Application Shortcuts, but that didn’t do anything. Next I found a post on macosxhints that offered a Terminal (defaults) command for changing default Application shortcuts. For example:

defaults write com.macromates.textmate NSUserKeyEquivalents -dict-add "Reformat and Justify" "nil"

Guess what? That didn’t do it. TextMate was still pwning the ^J shortcut. Next stop, the Resources folder of the TextMate application. There I found KeyBindings.dict, where it was easy to locate the offending shortcut. I commented out the line (//) and restarted TextMate. Ta. Dum. My new keyboard shortcuts now function perfectly.

By the way, the reason I didn’t use “k” for down is I actually do regularly use the kill keybinding to delete to the end of the line (as well as ^a to move to beginning and ^e to the end). Also, you might skip mapping “m” to down, as “n” right next to it is already mapped to moveDown:, as mentioned while complaining about Emacs keybindings. I have them both mapped now, so I can have lazy fingers if I want to. Further, note that these keybindings will not work when selecting text; once you press the shift key, you’re in a whole new world. You’d have map those as well if you wanted that functionality.

I’m happy now, and so are my fingers. Have any other brilliant keybinding stories? I’d love to hear them.