I finally got around to writing a script to auto-generate the documentation for my DefaultKeyBinding.dict file. The script now reads my comments in the file and creates tables of keystrokes and descriptions ready for GitHub. From now on, my fickle changes will be reflected in the readme.md file in the repo and the keystrokes will stay current. You can see the current output here.

If you’ve taken off with KeyBindings already and your file wildly diverges from mine, the script is available for use by anyone. It requires a certain format in the file (I built it specifically for my own needs), but a little modification and you should be able to generate quick cheat-sheets for your own bindings.

You can find the script in the KeyBindings repo (it’s called document_keybindings.rb). You’ll want to modify the various sections of the output, so you’ll need to know a little Ruby to dink around with it. It’s not a bulletproof script by any means, but if you know a few regular expressions and some basic logic you’ll be able to make it do what you want. Note that by default it reads from “DefaultKeyBinding.dict” in the same directory as the script, and writes out to “readme.md” (in the same directory).

.dict file format

The basic comment/command format is:

	// > defaults write -g NSTextKillRingSize -string 6
	// replace yank: command with yankAndSelect for use with the kill ring
	"^y" = (yankAndSelect:);
  • Lines beginning with “// >” are added as parenthetical notes to the next command’s description
  • Lines beginning with “// TODO” are ignored
  • The description of the command comes before the line it’s defined on
  • I doesn’t handle free-spaced commands yet, command definitions should be on a single line (for now)

Groups are defined similarly:

	"^@c" = { // Commenting commands
      // comment with "//"
      "/" = (setMark:, moveToBeginningOfParagraph:, insertText:, "// ", swapWithMark:, moveRight:, moveRight:, moveRight:);
      // comment with "#"
      "\\" = (setMark:, moveToBeginningOfParagraph:, insertText:, "# ", swapWithMark:, moveRight:, moveRight:);
  • The title of the group is on the same line as the starting bracket
  • Commands within the group will be prefixed with the group’s key combination in the output

Any top-level commands (not in a group) will be gathered and output at the top of the output. You can modify the script to title that table any way you like.

The output table is currently in MultiMarkdown format but converted to HTML (using /usr/local/bin/multimarkdown, so you’ll need that installed) before writing to the ‘readme.md’ file. You can change or remove all of the prefixed verbage just by editing the INTRO variable.

Hopefully this will help keep things cleaner and minimize the number of explanations I have to send out in emails. Something about sharing a complicated trick and then modifying the steps without updating the documentation seems to throw people off. Fancy that.