The text system uses a generalized key-binding mechanism that is completely re-mappable by the user, although defining custom key bindings dynamically (that is, while the application is running) is not supported. Key bindings are specified in an dictionary file that must have an extension of .dict; the format of this file should be an XML property list, but the text system can also understand old-style (NeXT era) property lists. The standard key bindings are specified in /System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict. These standard bindings include a large number of Emacs-compatible control key bindings, all the various arrow key bindings, bindings for making field editors and some keyboard UI work, and backstop bindings for many function keys.
To customize bindings, you create a file named DefaultKeyBinding.dict in ~/Library/KeyBindings/ and specify bindings to augment or replace the standard bindings. You may use the standard bindings file as a template. It is recommended that you use the Property List Editor application to edit a bindings dictionary. You may use another application such as TextEdit or Xcode, but if you do you must ensure the encoding of the saved file is UTF8.
Key bindings are key-value pairs with the key being a string that specifies a physical key and the value identifying an action method to be invoked when the key is pressed. (Many of these action methods are declared by NSResponder.) You can compose physical-key strings using the following elements:
The alphanumeric character that appears on a US keyboard. For example, "f" or ">". (As noted below, some special characters are reserved for modifier flags.)
For a few keys, such as Escape, Tab, and backward Delete (BS), the octal number from the ASCII table that identifies the key. For example, the octal number identifying the Escape key (sometimes used as a modifier key) is \033.
An enum constant assigned a unique Unicode value that is used to identify a function key. These constants are defined in NSEvent.h. Examples of these constants are NSF7FunctionKey, NSHomeFunctionKey, and NSHelpFunctionKey.
One or more key modifiers, which must precede one of the other key-identifier elements. The following special characters are used for modifier flags:
“^” for Control
“~” for Option
“$” for Shift
“#” for numeric keypad
For example, the following string would identify the 0 (zero) key on the numeric keypad when the Control key is pressed simultaneously: "^#0".
The text system supports the specification of multiple keystroke bindings through nested binding dictionaries. For instance, Escape could be bound to cancel: or it could be bound to a whole dictionary which would then contain bindings for the next keystroke after Escape.
The following sample binding files illustrate how you might customize bindings. The first one adds Option-key bindings for some common Emacs behavior. This might be useful where the Option key bindings are not standard. With these bindings it would be necessary to type “Control-Q, Option-f” in order to type a florin character instead of moving forward a word. This sample also explicitly binds Escape to complete:. (In Mac OS X, this is the default so this override changes nothing.)
/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ |
{ |
/* Additional Emacs bindings */ |
"~f" = "moveWordForward:"; |
"~b" = "moveWordBackward:"; |
"~<" = "moveToBeginningOfDocument:"; |
"~>" = "moveToEndOfDocument:"; |
"~v" = "pageUp:"; |
"~d" = "deleteWordForward:"; |
"~^h" = "deleteWordBackward:"; |
"~\010" = "deleteWordBackward:"; /* Option-backspace */ |
"~\177" = "deleteWordBackward:"; /* Option-delete */ |
/* Escape should really be complete: */ |
"\033" = "complete:"; /* Escape */ |
} |
The following example shows how to have multi-keystroke bindings. It binds a number of Emacs meta bindings using Escape as the meta key instead of the Option modifier. So Escape followed by the "f" key means moveWordForward: here. This sample binds Escape-Escape to complete:. Note the nested dictionaries
/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ |
{ |
/* Additional Emacs bindings */ |
"\033" = { |
"\033" = "complete:"; /* ESC-ESC */ |
"f" = "moveWordForward:"; /* ESC-f */ |
"b" = "moveWordBackward:"; /* ESC-b */ |
"<" = "moveToBeginningOfDocument:"; /* ESC-< */ |
">" = "moveToEndOfDocument:"; /* ESC-> */ |
"v" = "pageUp:"; /* ESC-v */ |
"d" = "deleteWordForward:"; /* ESC-d */ |
"^h" = "deleteWordBackward:"; /* ESC-Ctrl-H */ |
"\010" = "deleteWordBackward:"; /* ESC-backspace */ |
"\177" = "deleteWordBackward:"; /* ESC-delete */ |
}; |
} |
Once you have completed specifying key bindings, you must save the file and relaunch the application for the bindings to take effect. With the right combination of key bindings and default settings, it should be possible to tailor the text system to your preferences.
Xcode uses Application Kit's key binding mechanism as described above to define key bindings for its code editor. These key-binding definitions are in /Developer/Applications/Xcode.app/Contents/Resources/PBKeyBinding.dict. You may define your own key bindings to supplement or replace these default Xcode bindings in a private dictionary of key bindings, PBKeyBinding.dict in ~/Library/KeyBindings.
Xcode merges all key-binding dictionaries to create a composite dictionary. The order of merging is:
Text system's default dictionary
Text system's user dictionary
Xcode's default dictionary
Xcode's user dictionary
Because the merge processes replaces earlier bindings with later corresponding ones, the bindings in your personal dictionary take precedence over the other bindings. The merge process affects bindings of multi-key sequences, like the Control-X family of bindings, where the binding for the first key of the sequence is another dictionary which contains the bindings for the subsequent keys in the sequence. If you want to add your own Control-X binding to the existing bindings, first copy the Control-X dictionary from Xcode's PBKeyBinding.dict file and add it to your own PBKeyBinding.dict file. Then modify the bindings as needed.
Last updated: 2007-03-16