Ah-hem. I meant to say Death to monospace and the TTY layer.
—Who radicalised you?
—The 70s, man.
A messy overview, and ways to get there.
First, I assert that monospace (fixed-pitch) fonts are hard and unpleasant to read, and that for decades now there has been no good reason to keep inflicting this relic on users. Even if these users are mostly developers. Developers are people and deserve humane treatment.
Further, I assert that terminal emulators—which use these monospace fonts—have grown into an absurd joke regardless, and should have largely disappeared a long time ago—if only we weren’t both completely incompetent as an industry and apathetic as people.
I’m not going to bother supporting these assertions here.
I can push the point across more simply. These are the same thing, only minimally iterated upon:
The Teletype Model 33 on the left is from 1963. 60+-year-old technology, in heavy use today, due to getting ossified within UNIX and its derivatives. The fixed character grid is a purely technical limitation carried over.
Meanwhile, here is a research computer from 1973. 50+ years old. Fully graphical. You can reprogram the environment from within itself in real time.[1] Its main problem was cost.
NeXT, Inc. later decided to combine the two concepts—UNIX and Smalltalk—into what’s now called macOS. It’s an automobile towing a horse.[2]
We take ASCII for granted, but we’re stuck with some extremely weird basic
glyphs and key meanings for the rest of computing history. For example,
the underscore (_) is there purely for formatting,
the backtick (`) purely for diacritics (it has no
stand-alone sense, yet it’s now a spacing character),
and the hyphen-minus (-) doesn’t know what it is.
The backslash (\) is a bizarre invention for approximating
∧ ∨ as /\ \/, funnily shown as ¥ or ₩ in Japanese
or Korean Windows instead.[3]
Strong typewriter legacy. Admittedly, the diacritics set
("',^`~) is useful for the
compose key mechanism,
even if you don’t use a teletype.
I deeply enjoy good typography. I like graphical user interfaces. Yet I punished myself with years of terminal-heavy Linux usage, while GNOME kept pulling the rug out from under me and made the GUI parts of the system unbearable.
Enough is enough, it’s time to figure this out.
Places where variable pitch was used in programming contexts. The general observation is that we gave up on modernity in the 90s.[4]
It largely points towards Xerox PARC (which influenced Niklaus Wirth, who then influenced Rob Pike[5]).
~1973 Smalltalk (on the aforementioned research computer, see the screenshot above)
~1974 The Alto actually let you program in the first WYSIWYG editor ever, Bravo.[6]
~1980s Interlisp-D, and certainly its Medley Interlisp version (in the Exec REPL) combined fixed pitch with variable pitch, though not to any greater extent.
~1982 The Cedar programming environment lets you put pictures in source code.
~1984 MacPascal, ~1986 Lightspeed/THINK Pascal
~1987 Oberon System
~1994 Plan 9’s Acme editor defaults to proportional fonts. Rob Pike explains why. This is from someone who had seen a Teletype in person. Sadly, his prediction didn’t come true:
Fixed-pitch will soon follow in the footsteps of CAPITAL LETTERS AND PUNCHED CARDS.
1998 Serial Experiments Lain is fictional but I can’t leave it out.
~2011 Lamdu is an experimental AST-based editor.
I wish I could find more. Alas.
~1986 MPW Shell lets you use the Enter key to execute lines in the middle of a buffer. Otherwise it uses fixed pitch.
~1992 Plan 9 from Bell Labs in general. Shell transcripts can be freely edited, as if they were one big text file. This works by treating only text after the ‘output point’—which gets reset to the end of each shell prompt—as pending shell input to be sent on Return. All editing is handled by the window system.
rio/rc/mc can align command output to columns in a proportional font, through what I consider a hack, though it’s not the default look of the system.
These also qualify, in their own way:
A Minimalist Global User Interface (a 1991 paper) is about Help, the predecessor of Acme.
Acme: A User Interface for Programmers (a 1994 paper) explains Acme in detail.
It is a great shame that my brain is hardwired for Vim’s modal navigation, and I can’t stand coarse bitmap fonts. Though you can always make new derivatives of older stuff.
Report on the Algorithmic Language ALGOL 60 (1960, revised)
Smalltalk-80: The Interactive Programming Environment, Mesa Language Manual, and other books related to Xerox PARC.
Algorithms + Data Structures = Programs by Niklaus Wirth (1976, revised), Project Oberon: The Design of an Operating System, a Compiler, and a Computer (1992, revised), and other books of the same provenance.
The C++ Programming Language, 3rd edition by Bjarne Stroustrup (1997) explicitly argues for proportional-width fonts in 1.1.1. This note disappeared in the 4th edition.
TeX: The Program (1986, with revisions approaching π) is the output of the program specified in the document itself. This also-book goes one step further than the rest, because it uses ligatures in code.
Pseudocode in papers is typically given in variable pitch.
The primary problem is that we put pre-typeset code and markup in source files, following semi-arbitrary, often locally invented standards. The formatting should happen automatically, and tabs vs spaces should not be a question.
If you try to use classic character-based wrapping, hoping for the best, you will get odd results. First, compared to fixed-pitch, variable-pitch fonts have much wider capitals. Second, any bold text is automatically much wider as well. Font weight jumps of syntax highlighting become more jarring than usual.[7]
Variable-pitch-based wrapping produces different results for every font. The only reliable solution is, therefore, dynamic line wrapping in the editor. The wrapping should be syntax-aware, just like automatic formatters—prefix-marked comments are particularly troublesome, as they need to invent characters.
You can’t use the wrap guide/right margin functionality of editors anymore, at least not in a meaningful way. Perhaps in the sense of CSS max-width.
If you only use soft wrapping, line-based diffs may become noisier.
You want to use tabs for indentation as well as alignment. The common two-space indent in particular is normally extremely thin. Space alignment will never match.
Automatic formatters like gofmt or clang-format can’t deal with a tab-only style, unless you patch them (which has recently been made cheap with LLMs).
If the spaces must remain in files, you can create an automatic filter that converts files on opening and saving.
Thin characters can be difficult to hit precisely with a mouse.
If you like to separate sections of code with horizontal lines, you’re in
a tough place. Emacs sets a precedent by using ^L form feed characters
for this purpose. These can be rendered prettily: in fact, its form-feed
and page-break-lines packages do exactly that. A modern alternative approach
is adding an extremely wide // --- ligature to fonts. That will survive
autoformatters.
A large subset of variable-pitch fonts doesn’t particularly care about legibility, i.e., ‘I’ and ‘l’, or ‘O’ and ‘0’ looking like different characters. This can often be toggled using OpenType font features, which are not exactly user-friendly: first you need to know which features you want, then either 1. toggle them in the editor, if at all possible; 2. force them at the system level (Fontconfig rules can do that); or 3. hardcode them in font files using the OpenType Feature Freezer.
On style mismatch, one group will get the short end of the stick. It may help to create an automatic filter that converts files on the fly, as mentioned before.
Syntax-aware dynamic wrapping: I’m not aware of any meaningful implementation. It’s up for further research. That said, many editors can at least make soft wrapping follow indentation, which may be good enough.
Elastic tabstops (also see): simple, occasionally supported by things, not necessarily well.
They don’t solve asterisk alignment in C, though that’s a minor issue.
A sample of appropriate fonts:
Go sans-serif is a good start, though perhaps not very nice to read, and semi-abandoned.
Lisnoti Code has pretty ligatures, and other programming-relevant features.
Atkinson Hyperlegible Next
Iosevka Etoile and Input Sans are no improvement over monospace. Why bother?
Iosevka Aile and other fonts need font features toggled for good legibility.
With the assumption that you want to keep on using major operating systems, and popular programming or markup languages.
Say goodbye to Vim—gVim doesn’t know what to do with proportional fonts. Luckily, many programming editors and IDEs with decent Vim emulation handle them just fine:
Qt Creator has FakeVim integrated.
Visual Studio Code has a VSCodeVim extension.
Zed has a Vim mode integrated.
Kate has vi-mode integrated.
Emacs has variable-pitch-mode and evil-mode. tabble-mode implements elastic tabstops.
As an aside, the Go programming language is notably well suited to editing in something like the Acme editor, used by at least Rob Pike and Russ Cox:
It standardises tab character indentation.
The suggestion to use semantic linefeeds has different reasoning behind it but works in our favour.
If you take a moment to notice, Go reads very well without syntax highlighting. You can’t say this about that many languages.
It still has gofmt’s space alignment problem but making an appropriate filter program to adjust sources on load is made easy: the go/printer package may only need RawFormat toggled. It’s elastic tabstops from there.
If you don’t feel like using Plan 9 or plan9port, you’re basically out of luck if you’re looking for something comprehensive.
These are misguided or useless:
mlterm may be the only real *nix terminal emulator that supports proportional fonts. The rest of your system keeps assuming a regular cell grid, so it’s not particularly useful.
Various attempts at combining *nix terminals with a web browser, or similar. Examples: TermKit, DomTerm.
The UNIX-HATERS Handbook: chapter 6 talks about additional problems with the implementation of teletypes on UNIX.
The Day of a new Command-Line Interface: Shell is also a good hypertext root.
Comments
Use e-mail, webchat, or the form below. I'll also pick up on new HN, Lobsters, and Reddit posts.