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
escape.)
I wanted to fix this properly, so here’s what I did.
configuration files
Terminal.app keeps its config in
~/Library/Preferences/com.apple.Terminal.plist which can be
manipulated by the defaults and plutil command-line utilities.
However most of the interesting Terminal.app configuration is nested
under the 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
double-clicking the profile.terminal file in the Finder, or using
the open command.
These configuration files are also plist files, in XML format, so
they are relatively hackable.
what’s inside
Most of a .terminal 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.
But the plist file stores these settings as binary blobs containing
serialized Objective-C objects.
Wat.
So I had to configure them in the GUI and copy around the exported
values to make my canonical .terminal file.
key problems
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.
key references
The relevant documentation for xterm keyboard escape sequences is
under the PC-style function keys heading in
ctlseqs.ms.
In a .terminal XML 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.
The keyMapBoundKeys dictionary looks like the following, where
CODE identifies the key and ESCAPE is a raw escape sequence.
You’ll want to use vis or 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>
The key 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 NSEvent.h.
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 .terminal file.
other links
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.
See Jacob Ruson customizing the Cocoa text system and the SS64 Mac OS key bindings how-to which has more useful links at the bottom.
Tony Finch – blog