Key bindings for switchers
This entry isn’t just for switchers, but I’ve gotten several requests for making the home/end function keys go to the beginning/end of current line, which is how Windows does it, hence the title.
While this is possible to setup within TextMate, I’m certain that the people requesting this would be happier with a solution that applies to all good OS X citizens (i.e. who make use of the standard key bindings system like Mail, Safari and other Cocoa applications). So here’s a detailed description of how to achieve this and more.
The standard key bindings are located in this file: System ▸ Library ▸ Frameworks ▸ AppKit.framework ▸ Resources ▸ StandardKeyBinding.dict
. This file is in XML, and function keys are stored using their actual character code, making it a bit hard to decipher, for our customization we’ll use the old-style ASCII format, and we’ll ignore this base file (since the system merges the files, giving our local file precedence when there’s a conflict).
Our local file should be located in ~/Library/KeyBindings
, this folder may not exist, so to create it (from Terminal) execute:
mkdir ~/Library/KeyBindings
Next we’ll create the actual key bindings file, which for some reason is named DefaultKeyBinding.dict
. To create the file (if it doesn’t already exist), again from Terminal execute:
cd ~/Library/KeyBindings
touch DefaultKeyBinding.dict
open -a TextMate DefaultKeyBinding.dict
This should open a (probably blank) file in TextMate (if you want to use another text editor, you’re on your own!). The format of the key bindings file is this:
{
«key» = «action»;
…
}
The key is a string representation of the key you want to bind, and action is one of the many Cocoa action methods defined in the NSResponder
class (scroll down and you’ll see them, most are self explanatory by name).
The string representation of a key is more tricky. For normal characters (like letters, digits, punctuation etc.), the string representation is the actual character. If you want to include a modifier in the binding, you can prepend one or more of the following characters to the string representation:
Character | Represents |
---|---|
$ | Shift (⇧) |
^ | Control (⌃) |
~ | Option (⌥) |
@ | Command (⌘) |
# | Number pad |
Shift is only used with function keys. E.g. if you want to bind something to shift-A, you’ll use A
(as opposed to $a
), and if you want to bind to shift-1, you’ll use !
(which makes the binding keymap sensitive).
Function keys are for the most part defined (as character codes) in NSEvent.h
. In the string representation these would be written as \Unnnn
. Here’s a table of the most interesting keys:
Character code | Description |
---|---|
\UF700 |
Arrow up |
\UF701 |
Arrow down |
\UF702 |
Arrow left |
\UF703 |
Arrow right |
\UF728 |
Forward delete |
\U007F |
Backward delete |
\UF729 |
Home |
\UF72B |
End |
\UF72C |
Page up |
\UF72D |
Page down |
\U001B |
Escape |
\U0009 |
Tab |
\U0019 |
Backtab (shift tab) |
\U000D |
Return |
\U0003 |
Enter |
Given the above information we can now rebind home/end to move to the beginning/end of line, and page up/down to actually move the caret. This would look like the following:
{
/* home */
"\UF729" = "moveToBeginningOfLine:";
"$\UF729" = "moveToBeginningOfLineAndModifySelection:";
/* end */
"\UF72B" = "moveToEndOfLine:";
"$\UF72B" = "moveToEndOfLineAndModifySelection:";
/* page up/down */
"\UF72C" = "pageUp:";
"\UF72D" = "pageDown:";
}
Now save the file and restart your Cocoa applications for the changes to take effect.