One of the small annoyances about Mac OS Terminal.app is that is
claims to be
xterm-256color but its default key escape codes are
incomplete and somewhat weird. (For example, alt-left generates ESC-b
which is the Emacs
backward-word binding, rather than a VT-style
I wanted to fix this properly, so here’s what I did.
Terminal.app keeps its config in
~/Library/Preferences/com.apple.Terminal.plist which can be
manipulated by the
plutil command-line utilities.
However most of the interesting Terminal.app configuration is nested
Window Settings key (which corresponds to Terminal’s
“Preferences -> Profiles” tab) and
defaults isn’t great at tweaking
values in nested structures.
Instead, on Terminal’s “Preferences -> Profiles” tab, there’s a
cogwheel at the bottom of the list of profiles where you can import
and export your configuration. You can also import a config by
profile.terminal file in the Finder, or using
These configuration files are also
plist files, in XML format, so
they are relatively hackable.
Most of a
plist file is easily edited by hand, but there
are a few magic numbers; to find out what they mean you can adjust the
drop-down list in the GUI then run
defaults read com.apple.Terminal
to see what the value is.
As well as the key bindings, I want to configure the font and colous.
plist file stores these settings as binary blobs containing
serialized Objective-C objects.
So I had to configure them in the GUI and copy around the exported
values to make my canonical
There are several layers of annoyance here.
The system-wide control-arrow bindings: I disabled these in the GUI at “System Preferences -> Keyboard -> Shortcuts -> Mission Control”, so I can make them behave like Emacs instead.
Terminal.app has some command-arrow bindings listed in its menus, which are oddly mislabelled: in the View menu, page-up/down are labelled as command-up/down whereas they are actually bound to command-page-up/down, and plain command-up/down are bound to the mark navigation actions in the Edit menu.
Terminal.app’s default key escape code configuration does not have bindings for page-up/down or home or end, so by default these keys do the same thing whether bare or with command.
I wanted the command-arrows to do window-scrolly things, and bare arrows or with other modifiers to send xterm-compatible escape sequences.
Configuring this in the GUI is very tedious and error-prone, so I wrote a script.
The relevant documentation for
xterm keyboard escape sequences is
under the PC-style function keys heading in
plist file, the key bindings are in a
dictionary attached to
keyMapBoundKeys. This is only present if the
key bindings were changed before the
.terminal file was exported.
keyMapBoundKeys dictionary looks like the following, where
CODE identifies the key and
ESCAPE is a raw escape sequence.
You’ll want to use
cat -v to look at a
.terminal file to
stop the escape sequences doing weird things.
<key>keyMapBoundKeys</key> <dict> <key>CODE</key> <string>ESCAPE</string> ... </dict>
CODE is a hex number, for instance, F700 is the up arrow
key. (These codes are in a Unicode private-use area.) If you have
XCode installed, you can find a full list of values in
The hex number can be prefixed with a set of modifier characters.
$ Shift ~ Option / Alt ^ Ctrl @ Command / Pretzel # Numeric Keypad
With that information I made a script to generate the
keyMapBoundKeys part of my
I belatedly found while writing these notes that someone at Google has published their Mac OS Terminal.app key bindings script.
This Terminal.app configuration is a glimpse at the Mac OS input system. There is a global set of key bindings (which by default includes a load of Emacs bindings) that can be reconfigured with similar flexibility.