Roben Kleene

SubEthaEdit Goes Open Source

Classic macOS text editor SubEthaEdit has gone open source (and free as in beer!):

This release fills me with great pride and joy. SubEthaEdit always has a special place in my heart. It is where my journey as a developer in the Apple ecosystem started. I owe it the position I am in today. This connection is why I’m taking the time to maintain it again and try to lead it towards a long lasting future. Therefore I think it is worthwhile looking at how everything came together.

The post itself, and this remembrance by Gus Mueller, are both great reads about the formative days of OS X app development.

SubEthaEdit remains very relevant today. It’s a hat in the ring for how to do collaborative text editing. Google Docs is the only successful application in this space and that’s only for rich text, making live collaboration for plain text, e.g., source code and markdown, still an unsolved problem1. SubEthaEdit is a plain text editor designed specifically for this purpose.

SubEthaEdit’s implementation uses Apple’s Bonjour networking technology (also notable that it’s based on an “old Xerox Parc Paper”):

Luckily one of us dug up an old Xerox Parc Paper that showed how latency free live collaboration can be done. At that time it fit perfectly with the newly released Bonjour technology to allow for networking without configuration between Macs. That was super exciting and we quickly got to a point where we could see this technology as viable and so we went on to build our application.

The major problem with SubEthaEdit’s collaborative editing model is that it’s only available while users are connected with each other. It’s not like Google Docs where anyone with the right URL (and access rights) can just start editing the file. Instead one user has to invite other users to start editing, and the session only lasts as long as the original user keeps that file open in SubEthaEdit. It may seem like the Google Docs model is obviously better when compared this way, but it’s really not that straight forward. The Google Docs model is entirely incompatible with version control for example, whereas SubEthaEdit’s model works brilliantly with it. Of course the fact that SubEthaEdit is also a true first-class Mac native app makes it a joy to use.

One of the interesting bits about SubEthaEdit becoming free is that an application like this thrives on the network effect. If you want to edit a file with someone collaboratively, convincing them to use a $40 application is a big hurdle to overcome. I hope this change means SubEthaEdit gets some wider use, I know I’ll be looking for opportunities to use it with my collaborators now.

  1. See also Roman Dillet for TechCrunch writing about Canvas a great attempt to make a Google Docs for Markdown. It’s now been shuttered; it’s also open source↩︎




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