A keyboard experiment

As soon as I unboxed my new MacBook Air, I knew there’d be one problem I’d have to get around: Apple had assigned a special action to every function key.

MacBook Air function keys

Every Mac keyboard I’d used before this one had some empty function keys in the middle of the row. And for at least a decade, I had mapped one of them, F5, to the Show Desktop action. The Desktop is a convenient spot to save temporary files, and dragging them to and from the Desktop is most easily done when you have a simple way to show and hide all your windows while in the middle of a drag. Mapping the Show Desktop toggle to F5 gave me that simple way. And it’s become such a regular part of how I use a Mac that I was afraid I couldn’t retrain myself to use anything else.

I tried. For a couple of weeks, I had Show Desktop mapped to ⌥⌘D, but it never felt right. There’s a certain “pat your head while you rub your belly” aspect to using a three-finger keyboard combination with one hand while dragging with the other. I know it sounds silly, but the added work of arranging my left hand to press more than one key often made my right hand drop what it was dragging. Old dog, new tricks.

So this meant I had to do what I was hoping to avoid: turn on the dreaded “Use F1, F2, etc. keys as standard function keys” setting.

Keyboard settings for function keys

(By the way, has anyone at Apple read the text of this option carefully? Why would my MacBook Air’s keyboard be considered external? Even on an iMac or Mac Pro, I wouldn’t think of the keyboard that comes with the computer as external. An external keyboard is what I use when working on my iPad.)

There are two reasons I have always avoided turning on the standard function key setting:

  1. I use some of the special actions quite often, especially the volume control keys over at the right end. Using the fn key with them is inconvenient because it’s a two-handed action.
  2. It’s clear that Apple expects you to keep that option turned off, and I have learned over the years that doing things outside Apple’s expectations often leads to weird behavior.1

But I really wanted F5 to Show Desktop, so I clicked the checkbox and mapped F5 the way I wanted. That worked fine, but as I had feared, it ruined other behavior.

According to the description,

When this option is selected, press the Fn key to use the special features printed on each key.

That was true for the volume and brightness control keys, but not for Spotlight (F4), Dictation (F5) or Do Not Disturb (F6). Pressing these keys along with fn did absolutely nothing after activating the standard function key setting. So I had to work through all the settings (and do a little work in Keyboard Maestro) to get reasonable access to all the features:

I haven’t bothered remapping F1 or F2 because I very seldom change the screen brightness.

The two Mission Control actions I’ve mapped to F3 and F4 don’t get used as much as F5, but they’re very helpful in digging out buried windows, especially on a small notebook screen where there’s lots of overlap. And there’s a logic to their positioning helps me remember what they do, even for the two that don’t have their function printed on the key.

Function key actions

Was all this dicking around worth it? I think so. Hesitating over common operations doesn’t just waste time; it makes you shift your thinking back and forth between what you’re working on and the mechanical operation of your computer. Almost anything that keeps you focused is worth it.

I will feel a little foolish if someone emails me and says “Why didn’t you just do X?” and they have a way of getting F5 mapped to Show Desktop without going through all the rest of this nonsense. But if there is an easier way, I’ll happily adopt it.


  1. This isn’t just an Apple thing. I’ve found certain settings mess up Windows, too, because Microsoft just didn’t test their behavior as thoroughly as it did the more standard parts of the OS. 


Case and Keyboard Maestro

The best thing about blogging your little automations is that other people see them and come up with improvements. In an article in iMagazine, Wojtek Pietrusiewicz redid my Cocoa keybindings as Keyboard Maestro macros. The article is in Polish, but you shouldn’t have any trouble getting the gist of it.

Wojtek’s macros are better than my keybindings because they work in any app, even those that don’t honor Cocoa keybindings, like Messages, Twitter, and Slack. Of course, they only work if you have Keyboard Maestro, but if you’re serious about Mac automation, you probably do.

Wojtek does the case changing through Keyboard Maestro filters. I had never looked at Keyboard Maestro’s Filter action before. It has a remarkable list of transformations:

Keyboard Maestro Filters

There are 47 filters in this list, more even than you’ll find in BBEdit’s Text menu.1 I’m not sure why I’d never noticed the Filter action before, but now that I have, I won’t forget it.

While Wojtek’s macros are an improvement on my Cocoa keybindings, they don’t replace the AppleScripts I wrote for BBEdit because they don’t handle the situation in which text is already chosen. Wojtek mentions in his article that he plans to add that ability, but I couldn’t wait. I extended his macros to work like my AppleScripts, but in any app.

Here’s the Lower Case macro. The Upper Case and Capitalize macros are the same except for the filter.

Keyboard Maestro Lower Case macro

The first thing it does is save whatever you have on the system clipboard. We’ll restore that at the end of the macro. It then initializes the clipboard with an empty string—this is necessary to work with the logic of the later steps.

The next step is to simulate a ⌘C keystroke. If there’s text selected, it gets put on the clipboard; if there’s no text selected, the clipboard remains an empty string.

Now we test the contents of the clipboard. If it’s an empty string, we simulate a ⌥⇧← keystroke to select back to the beginning of the word and a ⌘C keystroke to put that text on the clipboard. If the clipboard is not an empty string, we do nothing.

As we leave the macro’s conditional chunk, whatever text we want to change the case of is both selected and on the clipboard. The next two steps change the case of the clipboard and paste it in to replace the selection. Finally, we restore the clipboard to what it was before we started.

Thanks to Wojtek, I now have a set of case-changing macros that work consistently in every app.


  1. Ultimately, I’d say BBEdit wins because a couple of its Text menu items allow you to filter text through any Unix command or script that you’ve written. 


Keys and case

Setting up a new computer from scratch is the perfect opportunity to rethink the way you’ve been working. Because it takes some time to find and import your old scripts and settings, the small amount of extra time it takes to tweak them doesn’t seem like much of a burden. I’ve used the setting up of my M1 MacBook Air to fiddle with my longstanding capitalization keybinding.

As I’ve explained before, I have a problem typing capitalized words. Usually, my pinkies lift off the Shift key a little too soon, and the word ends up all lower case. Sometimes, as I try to correct for that tendency, my pinkies linger too long on the Shift key, and I end up with words that have their first two letters CApitalized. For as long as I’ve used scriptable text editors, I’ve written macros to correct for this tendency. Emacs, NEdit,1 TextMate, BBEdit—they’ve all been given a way for me to correct my miscapitalizations. The macros have all worked the same way:

  1. I realize that I’ve typed part of a word—or maybe the entire word—and didn’t capitalize it.
  2. I type some key combination. For a long time, this has been ⌃⌘C.
  3. The editor goes back to the beginning of the word, capitalizes it, and then resets the cursor to where it was before I typed ⌃⌘C.

On the Mac, I can extend this correction to (some) other apps through the Cocoa text system and keybindings. If you know about keybindings, it’s probably through Brett Terpstra. His huge set of keybindings is unquestionably the best set of examples you can find on the topic, but I still think Jacob Rus’s old web pages (here and here) are the best tutorials.

So anyway, after a couple of days of using my new MacBook Air, I realized that my typing of capitalized words hadn’t improved, and I needed to install both my BBEdit capitalization macro and my keybindings file. As I was doing so, I thought about extending them. For example, I’ve run into situations when I needed ALL CAPS, but I didn’t press the Caps Lock key long enough for it to activate, and I’d type path in a shell script instead of PATH. And if I were going to add an uppercase keybinding, I might as well add a lowercase one while I was at it.

Writing the commands was simple enough (I’ll show them later)—what was tricky was deciding where to bind them. I took inspiration from the X, C, and V keys used for Cut, Copy, and Paste. They work because they’re all in a row, they’re in the same order as we usually list the functions, and two of the keys have a nominal relationship to their function. I chose three keys at the other end of the lower row: <, >, and ?.

Case keys

The relationship between the names of these keys and their function is tenuous, but the < key can be related to the idea of “making what’s to the left smaller” and the > key to “make what’s to the left larger.” More important is that the order of the keys from left to right is the order I associate with case changing: Lowercase, Uppercase, Capitalize.

Of course, I can’t just combine the Command key with these to run my macros. ⌘-Period has been used to cancel commands for as long as the Mac has been around.2 And ⌘-Comma is the standard shortcut for opening an app’s preferences window. So, to hold onto some connection with my older use of ⌃⌘C, I chose to combine Control and Command to the three keys.

The Cocoa text system keybindings are saved in ~/Library/KeyBindings/DefaultKeyBinding.dict. This is a plain text file that’s formatted in a way that’s reminiscent of JSON.

{
    "^@," = (setMark:, moveWordLeft:, moveRight:, lowercaseWord:, swapWithMark:);
    "^@." = (setMark:, moveWordLeft:, moveRight:, uppercaseWord:, swapWithMark:);
    "^@/" = (setMark:, moveWordLeft:, moveRight:, capitalizeWord:, swapWithMark:);
}

The keybindings come before the equals sign, and the caret and at symbol are ASCII substitutes for Control and Command. After that come the series of Cocoa text selectors that do the work of moving the cursor around and changing case.

These keybindings work in apps that use the Cocoa text system and honor the keybindings. Luckily for me, that includes many of the apps I write in, especially Mail. It doesn’t include the app I do most of my writing in, BBEdit, but that’s OK because BBEdit has a very capable AppleScript dictionary, which can do everything the keybindings can do and more. Here are the scripts for Lowercase,

applescript:
 1:  tell application "BBEdit"
 2:    tell window 1
 3:      if length of selection is 0 then
 4:        set cursorPoint to characterOffset of selection
 5:        find "\\b\\w" options {search mode:grep, backwards:true} with selecting match
 6:        find "\\w+\\b" options {search mode:grep, extend selection:true} with selecting match
 7:        change case selection making lower case with replacing target
 8:        select insertion point before character cursorPoint
 9:      else
10:        change case selection making lower case with replacing target
11:      end if
12:    end tell
13:  end tell

Uppercase,

applescript:
 1:  tell application "BBEdit"
 2:    tell window 1
 3:      if length of selection is 0 then
 4:        set cursorPoint to characterOffset of selection
 5:        find "\\b\\w" options {search mode:grep, backwards:true} with selecting match
 6:        find "\\w+\\b" options {search mode:grep, extend selection:true} with selecting match
 7:        change case selection making raise case with replacing target
 8:        select insertion point before character cursorPoint
 9:      else
10:        change case selection making raise case with replacing target
11:      end if
12:    end tell
13:  end tell

and Capitalize

applescript:
 1:  tell application "BBEdit"
 2:    tell window 1
 3:      if length of selection is 0 then
 4:        set cursorPoint to characterOffset of selection
 5:        find "\\b\\w" options {search mode:grep, backwards:true} with selecting match
 6:        find "\\w+\\b" options {search mode:grep, extend selection:true} with selecting match
 7:        change case selection making capitalize words with replacing target
 8:        select insertion point before character cursorPoint
 9:      else
10:        change case selection making capitalize words with replacing target
11:      end if
12:    end tell
13:  end tell

You’ll note that these scripts behave differently under different conditions. If there’s no selection, they work just like the keybindings: jump back to the beginning of the word, change the case, and return the cursor to where it was. But if text is selected, they do something simpler: change the case of whatever is selected. This makes it easy to change the case of a whole set of words at once.

Have I occasionally typed ⌃⌘C instead of ⌃⌘/ over the past few weeks? Of course I have—you don’t break a 15-year habit overnight. But I’ve been pleasantly surprised at how few times I’ve done it. The logic of the new keybindings is winning.


  1. No, that one’s supposed to have the first two letters capitalized. 

  2. I suspect most of us use the Escape key now, but early Macs didn’t have an Escape key. 


Apple and links

Yesterday, there was a crisis among iOS automation people, as Apple broke all the icloud.com links to shortcuts. How this happened—or even what happened—has not been explained, but Apple seems to be slowly restoring the links as I write this.

This reminded me of Apple’s bad behavior with online documentation URLs, specifically those for man pages. For a few years, Apple kept changing where it kept its HTML-formatted man pages, breaking links all over the internet. As I said in a post five years ago, complaining about this:

… Apple is a terrible citizen of the web. Links, especially to programming documentation, should be maintained. If a directory structure has to be changed, redirects should be used to send visitors to the new locations. This is Web 101.

More recently, Apple has stopped moving its man pages around and just deleted them from the internet entirely. As best I can tell, there is no way to see an online version of any of the man pages that ship with macOS. Unless you want to go straight to the nroff source, which is kind of hard to read.

The SS64 site has what they say are macOS man pages, and they rank high in Google and DuckDuckGo searches, but I find they often don’t match what I get from running man in the Terminal. For example, SS64’s sort page doesn’t have a DESCRIPTION section, and its explanations of several options differ from my local man page for sort.

So when I blog about a command, I can’t always link to an accurate man page. Worse, my old posts are littered with broken links, and there’s no longer a way to fix them.