I suspect a lot of us who bought M1 MacBook Airs are thinking about the next generation low-end MacBooks (whether Apple calls them Airs or not) and wondering if maybe we should have waited a year for a step up in Apple Silicon power. That’s certainly the common regret in computer buying—that if we’d just held off a little longer, we’d have gotten something much better. But recently I’ve been thinking that regret may work the other way this time.

These are the things I’ve been putting together:

Undoubtedly, there are people who will happily trade five of six hours of battery life for a significantly lighter machine. And there may come a time when I’ll be one of them. But not now. Because of Apple’s weird interim Air design, I may have stumbled into the ideal computer for me.

What’s the diff?

This morning’s post by John D. Cook brought up an interesting problem: what’s a good way to check for differences between files when the files consist of just a few (or maybe just one) very long lines?

The problem is that diff, the standard Unix tool for finding differences, tells you which lines are different. This is great for source code files, which are written by human beings and in which the lines tend to be short, but not so much for machine-generated files like JSON, XML, and some HTML files, in which line breaks may be few and far between.

Cook’s solution for comparing long-lined files is to pass them through fold before sending them to diff:

diff <(fold -s -w 20 temp1.txt) <(fold -s -w 20 temp2.txt)

The -s option tells fold to break at space characters instead of in the middle of a word. The -w 20 option tells it to make the new lines no more than 20 characters long. Breaking the text into lines of only 20 characters is overkill, but it certainly is easy to see differences between lines when you have only 20 characters to scan through.

The <() thing is a bit of clever shell scripting known as process substitution. It’s used instead of piping when you have more than one input that needs to be fed to a command.

I was unfamiliar with fold until today. Whenever I’ve needed to reformat a text file to a given line length, I’ve used fmt. What I like about fmt is that it defaults to breaking lines at spaces—no need for the equivalent of the -s option. So I’d do

diff <(fmt temp1.txt) <(fmt temp2.txt)

if I were OK with fmt’s default line length of 75 characters, or

diff <(fmt -20 temp1.txt) <(fmt -20 temp2.txt)

if I wanted to use Cook’s extremely short lines.

But I’d be even more likely to open both files in BBEdit and use its Search▸Find Differences▸Compare Two Front Windows command. That would give me this nice two-pane output:

BBEdit differences

In this example, there’s only one line, but it’s broken into easily digestible pieces by BBEdit’s soft wrapping, and the exact spot at which the difference occurs is highlighted by the darker purple background.1

There is a diffing app called Kaleidoscope that I’ve heard good things about, but I’ve never felt hampered by BBEdit.

  1. In his example text, Cook punned by changing Melville’s “hypos” to “typoes.” Not to be outpunned, I changed it to “typees.” 

The two Johnnies

I was out running errands in the middle of the day, so I only saw the last 15 minutes or so of today’s Apple Event. But it didn’t take long to catch up.

Apple Event logo

Given the pre-event rumors and the graphic in the invitation, I don’t suppose it surprised anyone that colors came back to the iMac. I admit, though, that I was surprised at how bold the colors are, at least on the back sides.

New color iMacs

For over a year, ever since Jony Ive said good-bye, I’ve been waiting for color to return to the iMac. It seemed to me that the spare aluminum iMac, whose fundamental design has been unchanged since 2012, was Jony’s ideal iMac. Oh, I’m sure he would’ve gotten rid of the bulge in the back if it weren’t for the thickness of spinning disks and the need to cool Intel’s chips, but I think he considered the bare aluminum and glass look to be pure and honest. It’s the truest evocation of the materials used to make the device and what he’d been working toward for years. That’s why the 2012 design persisted for so long. Why mess with perfection? And who was left at Apple to tell Jony that it wasn’t perfect?

But now that it’s been a decent interval since he left, Apple’s industrial design can move on. I expect we’ll see colors leak back into several colorless product lines. I’m not sure what we’ll see in the upcoming large iMacs and more powerful MacBook Pros; Apple may still be reluctant to add anything more than anemic pastels to its “pro” line. But the MacBook Air is an obvious target. The first M1 Airs, like the one I’m typing on right now, kept the old look because it was faster and cheaper to do it that way, but I’d be very surprised if the next generation of Airs weren’t at least as colorful as what we saw in today’s small iMacs.

The other big change in the look of today’s iMacs is due primarily to someone who isn’t on the industrial design team: Johny Srouji. The iPad-like look of the new iMac is possible because of the iPad-like chip that drives it. And the size and shape of every Mac that Apple makes from now on is going to be based on parameters set by Johny’s chips. Small, efficient, and cool, those chips are going to set the boundaries within which Evans Hankey and her team will work.

I’m sure Jony is happy with his decision to leave Apple after so many years. But I suspect he sometimes looks down from his pure white realm and thinks about what he could do with Macs if he had Johny’s chips to work with.

A Drafts custom syntax for book lists

One of the things I use Notes for is to keep track of books I’ve bought and read. It works well enough but not the way I’d really like it to. I want two checkmarks for each item—one saying I own the book and the other saying I’ve read it—and Notes allows only one. My compromise is to use the real checkmark for ownership and a checkmark character (✔, the Unicode heavy check mark) for read status after the title.

Book list in Notes

The obvious downside to this compromise is that I have to set the cursor after the title and then type in the second checkmark. If it were a real checkmark, I could just tap it.

Recently, David Sparks made a video about using Drafts for lists. While I was watching it, I started thinking about using Drafts for my book lists. Drafts now allows custom syntaxes and themes, so it seemed likely I could start with the Simple List syntax and rewrite it to fit my needs.

After a bunch of trial and error, I got more or less what I wanted:

Book list in Drafts

The theme is not yet in final form—I’m still experimenting with line spacing and font sizes—but the syntax is working well. I can now tap to toggle both the owned and read status.

The syntax rules are very simple:

  1. If a line starts with any character other than a ○ (Unicode white open circle), a ◉ (Unicode fisheye), a space, or a newline, it’s a heading.
  2. If a line starts with a ○ or a ◉, it’s a list item.
  3. The ○ and ◉ characters act as checkboxes wherever they appear in a line. Tapping on one toggles to the other.

Here’s the custom syntax definition:

 1:  {
 2:    "name": "Media List",
 3:    "description": "Checklist for books, movies, etc. Checkbox before title indicates ownership; checkbox after title indicates completion.",
 4:    "sampleText": "Media List\n\n○ Not owned or completed ○\n◉ Owned but not completed ○\n◉ Owned and completed ◉",
 5:    "author": "Dr. Drang - adapted from Simple List",
 6:    "scopeName": "text.medialist",
 7:    "rangeExtensionType": {
 8:      "default": "lineExtended"
 9:    },
10:    "listCompletionDefinitions": [
11:      {
12:        "comment": "",
13:        "enabled": true,
14:        "match": "^( *)(([\\u25CB\\u25C9]) )(.*)",
15:        "captures": {
16:          "indent": "1",
17:          "prefix": "2",
18:          "line": "4",
19:          "sequence": ""
20:        },
21:        "replacements": {
22:          "◉": "○"
23:        }
24:      }
25:    ],
26:    "fileExtensions": [
27:    ],
28:    "patterns": [
29:      {
30:        "match": "^([^\\u25CB\\u25C9 \\n].*)$",
31:        "exclusive": true,
32:        "comment": "Heading or title",
33:        "captures": {
34:          "1": {
35:            "scope": "text.heading"
36:          }
37:        }
38:      }
39:   ],
40:    "navigationPatterns": [
41:      {
42:        "match": "^([^\\u25CB\\u25C9 \\n].*)$",
43:        "rangeCapture": "0",
44:        "comment": "Header or title",
45:        "prefix": "Header",
46:        "labelCapture": "1",
47:        "identifierCapture": "1",
48:        "level": 0
49:      }
50:    ],
51:    "taskMarkDefinitions": [
52:      {
53:        "enabled": true,
54:        "match": "([\\u25CB\\u25C9︎])",
55:        "comment": "Checkboxes",
56:        "rangeType": "task",
57:        "captures": {
58:          "interactive": "1",
59:          "state": "1"
60:        },
61:        "states": [
62:          "○",
63:          "◉"
64:        ],
65:        "scopes": {
66:          "interactive": "text.checkbox"
67:        }
68:      }
69:    ]
70:  }

I started with the Simple List syntax file, altered the definitions in the heading, navigation, and task mark sections, and stripped out everything else.

I’m not saying that building a custom syntax is easy, but it is relatively straightforward if you read the documentation with one of the built-in syntax files open in front of you. The main things I had to remember were to double the backslashes (a common requirement when strings are interpreted in two stages) and to use Unicode hex codes (\u25CB and \u25c9) within the regular expressions and the characters themselves (○ and ◉) elsewhere.

As for the theme, I made a copy of the built-in Light theme, changed the color of headings to black (I dislike the brownish purple headings of the Light theme) and added a section for the new text.checkbox scope:

"text.checkbox": {
    "name": "Checkbox Text",
    "settings": {
        "fontWeight": "normal",
        "fontSize": "normal"

At present, this scope is sort of a placeholder. It’s basically the same as the text.normal style, but it gives me the ability to alter the style of the checkboxes in the future without changing the syntax.

You’ll notice that the checkboxes in the screenshot are blue even though there’s no such color specification in the theme. I think that’s because clickable text in Drafts is always blue. According to the documentation, the foreground color of a task mark cannot be changed. Maybe in a future version.

One last thing. The ○ and ◉ characters may appear quite different in size here in the blog, but they are the same size in Drafts. Do I know why? No. I do know that I chose those two characters because my original choices, ☐ and ☑︎, were different sizes in Drafts, and when I tapped to toggle between the two states, the different sizes for those characters caused the line to jump up or down. I didn’t like that, so I switched from boxes to circles.1

I suspect the character size differences are due to some sort of font substitution going on behind the scenes, but I don’t feel like digging into the problem.

  1. Although I keep calling them checkboxes