Roben Kleene

You Don't Need a Mac

Matt Gemmell on the direction the wind is blowing for the future of iOS and the Mac:

But you don’t need a Mac. You need Xcode on the iPad. That’s all. […]

There’s no particular reason you can’t write and debug code on an iPad, and it’s going to happen. Same for Logic, and Final Cut, and Photoshop, and so on. Oh sure, maybe it won’t be those specific apps (though in a lot of cases, it will be), but tasks themselves are always more interface-agnostic than you think.

I see where he’s coming from, and there’s a part of me that agrees, or at least wants to agree. The architecture of iOS is fundamentally more secure and easier to use than macOS, and I love fantasizing about a future where it’s the only OS I ever need.

But the mistake I think he’s making is equating programming to just another task. For computers, it’s not a task, it’s the task; it’s what makes everything else possible. And you still can’t do it on iOS1. Has any platform ever become a first-class programming platform retroactively? They’re usually designed to be bootstrapped as fast as possible.

I’m increasingly convinced that this process of bootstrapping builds features into the nature of platform, and that these features can’t be retroactively changed or added2. And if that’s true, it means the ship has already sailed on iOS ever being a great programming platform. I really hope Apple proves me wrong on this.


  1. It’s such an obnoxious term, but so perfectly apt I can’t help using it: iOS only allows “toy” programming. ↩︎

  2. For examples of where Apple has tried to change the nature of macOS, see Spaces, the Mac App Store (especially sandboxing), replacing “Save As” with “Duplicate” in Mac OS X Lion, and “App Nap” from OS X Mavericks↩︎








`fd` For Find Files

One of the concepts I want to emphasize is the advantage of using small “composable” Unix utilities. To this end, I use rg for all kinds of operations that search or list files. One advantage of this approach is that convenient rules setup in rg, e.g., ignoring .git directories and files in .gitignore, then propagate over every file and search operation I perform.

But something that’s always bothered me is since rg doesn’t support finding directories (understandably), I lose rg semantics when searching for directories, and instead get decades old find semantics, which don’t do smart things like ignoring things that probably should be ignored.

So I was delighted when I followed the ripgrep GitHub issue to the fzf README to fd. A utility that does exactly what I’m looking for, find directories while replicating the smart take on semantics used by rg (and other modern unix utilities).

Here’s an example of my favorite use of this, replacing the built-in fzf zsh widget’s FZF_ALT_C_COMMAND, which enables a key command to fuzzy filter a directory to cd to recursively.

fd




A Quick Command-Line Interface for Safari History

I got so frustrated by not being able to quickly find web pages in my Safari history that I hacked together a simple command-line interface that lets me search my history with fzf.

It comes in two pieces, a shell script that uses the sqlite3 command-line utility to dump the title and URL of each web page:

read -r -d '' select << EOM
SELECT title, url
FROM history_visits
INNER JOIN history_items
ON history_visits.history_item = history_items.id
ORDER BY visit_time desc
LIMIT 1000;
EOM

sqlite3 -noheader -separator $'\t' ~/Library/Safari/History.db \
  "$select" 2>/dev/null \
  | uniq

And a zsh function that pipes its output through fzf:

fzf-safari-history-open() {
  local result=$(safari-history-dump \
	| FZF_DEFAULT_OPTS="-m --reverse --prompt \"Safari History> \" \
	--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS" $(__fzfcmd) +m \
	| cut -f2)
  if [[ -n $result ]]; then
	open "$result"
  fi
}

Here’s what it looks like:

safari-history




TextMate's Command Composability

For its complexity level, TextMate is the most well-designed application I’ve ever encountered. Featurewise1, it doesn’t compete with Vim2, Emacs, or Sublime Text—but the features it does implement are better designed than anywhere else.

TextMate’s design elegance is exemplified by its command composability. “Composability” here means commands can be chained together to produce cumulative effects that are logical and useful.

For example, lets say you want to change the name of the startTime variable to startDate in this Swift snippet:

struct ProcessInfo: Equatable {
    let identifier: Int32
    let startTime: NSDate
    let commandPath: String
    init(identifier: Int32, startTime: NSDate, commandPath: String) {
        self.identifier = identifier
        self.startTime = startTime
        self.commandPath = commandPath
    }
}

One approach you could take is the following:

  1. Select startTime.
  2. Press ⌘E to “Use Selection for Find”.
  3. Press ⌘F to bring up the “Find” dialog.
  4. Press ⌥⌘F to “Find All”.
  5. Tab to the “Replace:” field.
  6. Enter startDate.
  7. Click “Replace All”.
  8. Press ⌘W to dismiss the “Find” dialog.

Here’s how TextMate’s command composability can be used accomplish the same goal in less steps, and without any annoying dialog boxes or clicking for “Replace All”3:

  1. Select startTime.
  2. Press ⌘E to “Use Selection for Find”.
  3. Press ⌥⌘F to “Find All”.
  4. Enter startDate.
  5. Enter ⇧⇧ to end multiple cursors.

Here’s what it looks like:

TextMate Demo

The key is the interpretation of ⌥⌘F for “Find All”. When interpreting this command, TextMate considers the context, and performs the most logical action:

  1. The “Find” dialog is not visible.
  2. The find pasteboard is populated (by the ⌘E earlier).

Choosing to initiate multiple cursors.

TextMate’s composability can be demonstrated further by performing the same commands with an active text selection. In that case, only instances of startDate within the text selection are edited. This idea of acting on the current selection or, in the absence of a selection, the whole document, is pervasive throughout TextMate4.

Command composability is a defining trait of well-designed software—learning a piece of software is an investment, and one of the best ways an application can make the most of that investment is to amplify what you can accomplish for the same effort through command composability.


  1. Autocomplete, linter integration, split windows, and ctags are the most problematic missing features. ↩︎

  2. Vim deserves special attention in this post because it also excels at command composability. But Vim has far more design flaws than TextMate. I’d be surprised if anyone can read the chapter on regular expressions in Practical Vim and not come to this same conclusion. ↩︎

  3. “Replace All” does have a keyboard shortcut, ⌃⌘G, but it’s hard to remember. And frankly, OS X dialog boxes don’t work very well when you want to choose any button other than the default (or esc to dismiss). And “Replace All” is too dangerous to make the default. ↩︎

  4. “Filter Through Command…” is my favorite example. ↩︎


Euclidean Sequencer

Euclidean Sequencer

I’ve built an Euclidean Sequencer1 for Ableton Live in Max for Live. I’ve been interested in Euclidean rhythm ever since I first heard about it because it looks like a good solution to some of the problems that come up when making music with a computer. Most of these problems revolve around what I call “the grid”.

Monome

Monome 256 by soundcyst / CC BY-SA 2.0 / Cropped from original

This is a Monome2, it’s a 16 x 16 grid of LED buttons that can be mapped to control any aspect of an electronic composition. By far the most common thing they’re mapped to is sequencing notes in time (called “steps”). The 16 buttons across mean four steps per measure in 4/4 time3.

808

Roland TR-808 by Brandon Daniel / CC BY-SA 2.0

The Monome isn’t the originator of the 16 steps by any means, that goes back decades: The Roland TR-808 is a historic example of this layout. It’s an electronic music tradition that’s been passed down for generations.

The disadvantages of this design are obvious, the rhythmic possibilities of 16 steps were exhausted ages ago, but it’s the advantages that are more interesting. This small palette acts as a scaffolding for more adventurous ideas. It’s a familiar base that can lure listeners far outside of their comfort zone. It’s what allows DJs to blend songs together, the unsung benefit of DJ sets is just how much experimental music gets slipped in and actually enjoyed (by people who’d never otherwise find themselves staring face-to-face with a trout mask).

The grid has been so successful as a compositional tool that it permeates through all kinds of electronic instruments, to the degree that it can be an uphill battle to deviate from it. In many ways this is a good thing. Innovation happens when the common cases are effortless, freeing the musician to focus their effort on invention. The balancing act for new tools is how to facilitate the exploration of new ideas without interfering with existing workflows.

This is where Euclidean rhythm comes in. An Euclidean sequencer is basically polyrhythm generator, it takes two parameters: a number of notes and a number of steps; and it algorithmically positions the notes as equidistant as possible in the number of steps. For example, three notes and seven steps results in the pattern E(3,7) = [x . x . x . .]. It turns out that equidistant distribution is a key to creating rhythms that sound musical, an extraordinary number of traditional rhythms can be generated through this simple process, see the example rhythms section.

Polyrhythms are a great way to make rhythms sound fresh: Multiple repeating rhythms at different rates creates variation over time. And being difficult to work with, they’re under-explored. The grid in particular makes polyrhythms impossible in many situations, when the number steps that don’t match the 16 subdivisions, and difficult at best. The beauty of the Euclidean sequencer is that it simultaneously addresses all of these problems, while also working seamlessly with the benefits of grid.

Now I just have to make a tool to generatively manipulating the Euclidean sequencer’s parameters, and I can sit back and leave the music making to the machines entirely. I like making software more anyway. My Euclidean sequencer is on GitHub.


  1. The repository has some nice examples of using Literate CoffeeScript to annotate the Euclidean algorithm↩︎

  2. I love the Monome’s design because it distills the converging trend in electronic instrument design towards flexibility to its essence. Predictably, it’s been tremendously influential, a google image search for grid midi controller reveals seemingly endless Monome-inspired designs. ↩︎

  3. The 16 steps are a great example of embracing constraints↩︎