System-wide editing shortcuts on macOS

I’ve become a devoted user of Visual Studio Code over the last year and a half and as part of that transition, I’ve adopted some of its text editing features and accompanying keyboard shortcuts.

Sytem wide edit shortcuts

The text editing features I use most are probably duplicating the current line above or below, or deleting the whole line. (You see, in software development it’s all about copying and deleting stuff, nothing gets ever written originally. For bootstrapping we use tutorials and Stack Overflow.)

While my work is mainly with code, the following tips are useful in general, not just when you are programming. And where I mention VS Code, for you this could be some other editor that has certain keyboard shortcuts and features that you wish travelled with you to other apps.

Which is where I found myself: having built the muscle memory to quickly delete a line or duplicate it with a single key combination – and have it all fall apart in another app.

And it’s not even that other apps don’t have those features themselves. In fact they often do. However, they don’t always use the same keyboard shortcuts or have all of the same edit commands.

So in order to define our favourite editing commands and give them keyboard shortcuts we use a customising capability that’s been around in OS X and before it in NextStep for ages: configuring the underlying text system that powers almost any text editing control via the configuration file ~/Library/KeyBindings/DefaultKeyBinding.dict.

Let’s start with an example, which is my current config file defining some of the cherished VS Code commands I mentioned:

// ~/Library/KeyBindings/DefaultKeyBinding.dict
{
  // move line up - option-up
  "~\UF700" = (selectParagraph:, setMark:, deleteToMark:, moveLeft:, moveToBeginningOfParagraph:, yank:, moveLeft:, selectToMark:, moveLeft:);

  // move line down - option-down
  "~\UF701" = (selectParagraph:, setMark:, deleteToMark:, moveToEndOfParagraph:, moveRight:, setMark:, yank:, moveLeft:, selectToMark:);

  // delete paragraph - cmd-shift-K
  "$@K" = (selectParagraph:, delete:);

  // duplicate paragraph above - option-shift-up
  "~$\UF700" = (setMark:, moveToBeginningOfParagraph:, moveToEndOfParagraphAndModifySelection:, copy:, moveLeft:, paste:, insertNewline:, swapWithMark:);

  // duplicate paragraph below - option-shift-down
  "~$\UF701" = (setMark:, moveToBeginningOfParagraph:, moveToEndOfParagraphAndModifySelection:, copy:, moveRight:, insertNewline:, paste:, swapWithMark:);
}

It is a simple text file that you can create with any editor. Changes are picked up on application restart.

Let’s look at the “delete line” config entry in more detail:

"@$K" = (selectParagraph:, delete:);

This maps a sequence of editing commands (selectParagraph: …) to a keyboard shortcut ⇧⌘K – defined as $@K – with the following modifier key symbols

  • @ – Command or ⌘
  • $ – Shift or ⇧
  • ~ – Option or ⌥
  • ^ – Control or ⌃

The commands this will execute pretty much speak for themselves:

  • selectParagraph: – select the paragraph the cursor is in
  • delete: – delete the selection

The interesting part here is that you can assign any number of commands, which are essentially method calls on the UI controls, to a shortcut. Upon invoking the shortcut, they will run in the context of your current edit field.

This is where the text system underlying macOS really shines: it allows you to configure the vast majority of apps using the standard user interface elements in one go.

You can find more information about the text system configuration mechanism in Apple’s Text System Defaults and Key Bindings documentation or check out this osxnotes.net page for a more condensed summary.

Also, this github repository contains a DefaultKeyBinding.dict with many more shortcuts and actions.

One important note: While even Apple’s own docs use lower case characters in the keybinding definitions I have found @$k not to work. It must be defined as @$K.