A Trifle Absurd
Matthew Morgan’s software notions
I (Still) Want an Editor
28 March 2006 at 19.31 • in Mac, Programming, OverleafI want a Mac-native text editor that supports:
- syntax-aware automatic indenting
- syntax-aware search (project-wide, both “find definition” and “find all uses”)
- arbitrary programming languages
- proportional fonts
Is that too much to ask? Apparently, yes. I haven’t found a single editor that implements all four. TextMate can’t handle proportional fonts. SubEthaEdit can’t indent intelligently. XCode isn’t extensible. Et cetera.
All this is reminding me why I started working on Overleaf. Too bad I don’t have time for it right now. Maybe I’ll get back to it in the sweet by and by after I ship Trifle.
Overleaf On Hold
8 December 2005 at 11.21 • in OverleafI won’t be getting back to working on Overleaf for a while. I still think it’d be great to have an open-source programmable multi-language Cocoa code editor on the Mac, and I hope to help make one someday. But right now, two considerations hold me back: Trifle’s higher priority and XCode’s surprising adequacy.
The further I get into Trifle, the more tasks spring up—not just coding, but also the machinery of starting a business. If I want to ship Trifle next year, I need to focus on it near-exclusively. And there’s the bottom line: Trifle has a chance of making me a living; Overleaf doesn’t.
Now that I’m coding in Objective-C, XCode is a surprisingly tolerable editor. It allows proportional fonts (unlike TextMate), and it does fully automatic indenting (unlike SubEthaEdit). I wish it was faster, and that its syntax highlighting was more flexible, but in the end, it works.
Fast Enough
13 October 2005 at 09.32 • in Programming, OverleafWhy would you choose to write an application in C when you have higher-level alternatives? I know I’d rather write less code and leave more of the grunt work to the computer. Too often, programming in C is premature optimization. At least, I claim to believe that, but then I fall into the same trap.
For Overleaf, I thought the main challenge would be making syntax highlighting fast enough. So I immediately chose to write it in Objective-C. (And yes, Objective-C, for all its merits, is still C at heart.) On top of that, I decided I should subclass NSTextStorage and implement my own attribute storage mechanism.
I wrote a bunch of code and made it work, but got fed up with Objective-C and decided to switch languages. I still thought that performance was the determining factor, so I looked toward compiled languages like Haskell and (Gambit) Scheme.
But then I started building a Python prototype of Overleaf, as a testbed for proportional-font indenting. I was still convinced Python would be way too slow, and it was—until I ditched my NSTextStorage subclass in favor of a simple delegate. Now it’s more than fast enough, and with a fraction of the code.
I’m sure you know the moral of this story: Premature optimization is the root of all programming evil. I keep harping on this subject, but that’s because—as this incident shows—I still need to get it into my head.
Indenting in Overleaf
11 October 2005 at 17.07 • in Programming, OverleafHere’s how I handle smart indenting in Overleaf, to keep the right things aligned even when using a proportional font.
The ground rules: Overleaf is a plain text editor, and loads and saves plain text files. It must consume and produce ordinary fixed-width indentation using spaces, so that Overleaf users can painlessly share files with users of other editors.
Given that context, I want to keep the plain-text representation of a file untouched, while I set attributes here and there to line things up. The text expansion attribute (see NSExpansionAttributeName) fits the bill: it allows me to stretch or squeeze text horizontally. All I have to do is calculate the correct expansion factor and apply it to a range of spaces, and I can line things up however I like. (And since spaces are non-printing, the stretching has no other visible effect.)
A simple rule helps calculate the expansion factor: one character should match one space. That is, if a line begins with four spaces, its fifth character should line up with the fifth character of the previous line. In practice, this means stretching the spaces to match the additional width of the non-space characters in the prior line.
This way, most things that line up in fixed-width mode will also line up in proportional mode. There are a few exceptions, the trickiest being line-internal indentation; the above rule doesn’t always work, and I haven’t found a clean solution yet.
Prototyping Overleaf
3 October 2005 at 21.16 • in Programming, Overleaf • Comments (2)I’ve been hacking together a new Overleaf prototype on the side (using Python with PyObjC). It’s certainly no more than a prototype, but it is—just barely—usable. And in particular, proportional-font indenting works.
I’m still not sure if programming in a proportional font is worth building a full-blown editor for. The advantage of this quick-and-dirty prototype is that I can try it out and see whether I like it or not.
One thing that’s immediately obvious is that most proportional fonts have symbol characters that just don’t work for programming (though Georgia and Optima aren’t bad). For example, the classic ASCII arrows usually look terrible. I’m hoping that by using NSGlyphInfo, I can substitute in real arrows.
Focus
16 August 2005 at 16.16 • in Trifle, Programming, OverleafI’m going to focus on one (and only one) programming project for a while. With my effort spread among several projects, it’s hard to see visible progress, and that’s discouraging. Also, I haven’t had time to spare for other stuff I like to do, like playing music.
I’ll tackle Trifle first, and put Overleaf and the (still nameless) language-design project on the shelf. Trifle was the first of these I started, so I think it should be the first one to get pushed through to usable reality. Plus, it’s probably the easiest of the three projects, at least for now: I’m starting with a dead-simple item-and-tag model, and it should be straightforward to build a little app around it.
Once Trifle has its first public release, I’ll start working on Overleaf again. The language project may simmer a while longer, though I’ll definitely keep my head in the game by reading LtU and such.
Rewriting Overleaf in Scheme
2 August 2005 at 14.06 • in Languages, Programming, OverleafI’m rewriting (most of) Overleaf in Scheme. I resisted the idea at first, ’cause I didn’t want to have to write a Scheme-to-Cocoa bridge. But then I noticed that my existing (Objective-C) code doesn’t interact with Cocoa much at all, so I could get away with creating a few stub functions in C and calling them via a normal Scheme FFI.
Why switch languages? Objective-C is a frustratingly low-level language; my plans for rearchitecting Overleaf would have involved rewriting a lot of the existing code anyway; and using an interactive language will make testing and debugging far easier.
Why Scheme? It’s higher-level than Objective-C in almost every way; it has several good implementations available; it’s a language I’m likely to use for other projects; and it puts my money where my mouth is regarding the usefulness and advantages for high-level languages for real-world application development. Plus, it’s fun.
The big question mark is performance. I’m hoping to employ the classic strategy of writing everything in Scheme, profiling, and then dropping down to C for the bottlenecks.
No, Really, It’s Evil
12 July 2005 at 11.11 • in Programming, OverleafSome days I need a four-foot sign hanging over my desk: “Premature optimization is the root of all evil.” We all keep saying it, but how often do we act like we believe it?
I tied myself in knots working on Overleaf’s proportional-font-indentation feature. Each scheme I came up with seemed expensive in time, or space, or both. I started wondering if I should just give up on it. But yesterday, in a fit of pique, I decided to hack up a ludicrously inefficient implementation just to see if it would even work. And what do you know, it does.
It’s got some bugs, of course, and there’s no way it will scale to large files the way it stands. But now that I can actually see something real and working, I’ve got the motivation to slog through the work to make it right.
That’s the underappreciated benefit of avoiding premature optimization: by getting something up and running that much more quickly, you get the incremental forward motion of accomplishment that motivates you to do the next thing.
Rejustifying Overleaf
27 June 2005 at 10.01 • in OverleafWhenever Overleaf development gets bogged down—like right now, for instance—I ask myself if the world really needs another text editor. For that matter, do I really need another text editor? I don’t know if the finished product is attractive enough to get me through the hard work of building it; still, I’ve put a lot of work into it already, which I don’t want to throw away.
And then there’s the question of the proportional-font-indenting feature, which was supposed to set Overleaf apart. I’m now realizing just what a hard problem that is. To make proportional-font code editing usable, Overleaf will need to handle internal indenting (e.g. lining up equals signs). The rules for that are bound to be far trickier than for simple left-edge indenting. Is it really worth all this work for a feature I’m not even sure I’ll like?
I’m trying to tell myself that even if that feature never happens, Overleaf will still be worth building. With highly configurable syntax highlighting coupled with an easy-to-learn config language, it will be really easy to whip up modes for new languages—or even multiple modes for the same language, to give you different views of the same code.
Domain-Specific Languages, Smalltalk-Style
31 May 2005 at 18.14 • in Languages, OverleafI recently chose F-Script to specify Overleaf syntax-highlighting modes. Since then, I’ve been experimenting with ways to build a domain-specific language (DSL) in F-Script.
F-Script is essentially a dialect of Smalltalk, and Smalltalk has a tradition of embedded DSLs. I’m used to building DSLs with macros, but I had to change my mindset: Smalltalk doesn’t have macros; instead, its message-sending (read: function-calling) system is extensible enough to make up for it.
I played with different variations for a while, trying to find a scheme that would minimize extraneous punctuation and parentheses. I came to appreciate Smalltalk’s weird precedence rules just a little: they make math expressions odd (1+2*3 is 9 in Smalltalk, unlike virtually all other infix languages, where it’s 7), but if you’re defining your own operators, they make things (relatively) simple. And by defining a few key operators, I came up with a simple, easy-to-read DSL that doesn’t have to stoop to regular expressions to define lexical syntax.
Side note on operators: I’m no big fan of operator overloading — it almost always obscures what an expression is actually doing — but defining new operators is another matter. A new operator won’t get confused with the meaning of an old one, but can simplify code quite a bit. Haskell’s operator system is still the best I’ve seen: you can define new operators at will, use existing functions as operators (via backquotes), and control operator overloading using typeclasses. Good stuff.