.@ Tony Finch – blog


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.

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.

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.