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.