notes from /dev/null

by Charles Choi 최민수


An accidental lock-in feature of the Apple ecosystem

12 Jun 2024  Charles Choi

It’s WWDC week, when Apple shines their spotlight on its developer ecosystem every June. Given the moment, I’d like take this opportunity to give all the flowers to the unsung developers who have built and maintained a feature in Apple products that I hold quite dear: the Emacs keybindings in Apple UI frameworks.

If you don’t know, when using a macOS native app like Notes, OmniGraffle, or Safari, you can use the following keybindings in any text field:

  • C-a - move cursor to beginning of line
  • C-e - move cursor to end of line
  • C-f - move cursor forward one character
  • C-b - move cursor backward one character
  • C-k - kill text to end of line
  • C-y - yank killed text (mostly, more on this later)

It can not be overstated how extraordinarily convenient this feature is to Emacs users. Even more astonishing is how this set of bindings has continued to be maintained (since 2001!) across the different OS variants Apple ships (macOS, iOS, iPadOS, tvOS).

Backstory

My anecdotal understanding of this feature’s history is that it started with the NextStep OS back in 1988. The developers of NextStep used Emacs and so whenever they typed in the text widgets of the NextStep UI, they naturally wanted to use Emacs bindings. It was unlikely that this was ever an exec-level requirement. But the developers wanted it, so they made it happen.

Fast forward in time, NeXT effectively acquires Apple and in doing so repackages the NextStep frameworks to ship Mac OS X (now called macOS). This decision fatefully keeps NextStep’s text system and its conventions intact in the UI framework called AppKit as part of family of frameworks called Cocoa. Fast-forward to 2007, the iPhone becomes a thing. Apple makes another fateful decision to build iPhone OS (now called iOS) off of Cocoa but create a new touch-based UI framework called UIKit. UIKit’s text system is heavily influenced by Cocoa where it too carries over the Emacs keybindings. Variants of iOS in the form of iPadOS and tvOS come to be, further propagating these keybindings. In 2019, a declarative UI framework called SwiftUI is created where its text system too adopts the Emacs keybindings.

Configuring Keybindings in macOS

Wonderfully enough, you can still configure the keybindings in AppKit-based apps on macOS using the NextStep style configuration as shown in the Text System Defaults and Key Bindings document. There it provides guidance on adding more Emacs-style keybindings.

Of note is that macOS has always supported an alternate clipboard to emulate the Emacs kill-ring. This works independent of the system clipboard, and requires a bit of configuration to get working. There are two steps to this:

  • Redefine the keybinding C-y to yankAndSelect:

In the file $HOME/Library/KeyBindings/DefaultKeyBinding.dict (for details see the link above), add the following line in the body between the braces.

"^y" = "yankAndSelect:";
  • Use the command line utility defaults to set the variable NSTextKillRingSize.

This variable controls the size of the kill ring. Here we will set it to 5.

$ defaults write NSGlobalDomain NSTextKillRingSize 5

You can confirm the value in NSTextKillRingSize as follows.

$ defaults read -g NSTextKillRingSize

Refer to man defaults for more information on it.

At this point, you will need to log out and back in for the new keybindings to take effect.

Caveats

You can’t have everything though as not all apps are built with AppKit. Focusing on only the default Emacs bindings, here’s a survey of the different levels of support for them from the different UI frameworks.

Binding AppKit/SwiftUI (macOS) UIKit/SwiftUI (iOS, iPadOS) Mac Catalyst
C-a Y Y Y
C-e Y Y Y
C-f Y Y Y
C-b Y Y Y
C-k Y Y Y
C-y Y N N

Unsurprisingly, UIKit chose to not support a kill ring, so effectively C-k is a delete function and yanking is not supported. The column for Mac Catalyst is a category of apps built to work for both iPadOS and macOS based largely on UIKit. Such apps include Messages and Stocks.

Closing Thoughts

I’ll never take for granted the repeated decision over the years by the Apple text system developers to keep supporting the Emacs keybindings. While perhaps not intended, this feature quite seriously is an ecosystem lock-in factor for me. It is a gift and to some extent, a secret handshake, that I’ll always be grateful for. To whoever was, is, or will be involved with keeping this feature alive, thank you.

emacs   ios   computer

 

AboutMastodonInstagramGitHub

Feeds & TagsGet Captee for macOS

Powered by Pelican