· 3 min read ·

The Quiet Satisfaction of Editing Code in a Program You Wrote

Source: lobsters

There is a long tradition of programmers writing text editors. It sits alongside writing a compiler or a raytracer as the kind of project that teaches you something a textbook cannot. Most people build one, learn from it, and go back to Neovim. jsbarretto did not.

The post on his blog documents not just the process of building an editor, but actually using it day-to-day as his primary tool. That shift, from hobby project to daily driver, changes the entire nature of the work.

What building an editor actually involves

A text editor is deceptively large in scope. At the surface it seems like: display characters, move a cursor, save a file. In practice you end up dealing with:

  • Buffer representation. Gap buffers and ropes are the two main approaches. A gap buffer keeps a contiguous block of memory with a gap at the cursor position; insertions and deletions are cheap as long as you stay near the gap. Ropes trade that simplicity for better performance on large files and arbitrary edits.
  • Undo/redo. Not just storing previous states, but deciding what constitutes a single undoable unit. Did pasting a paragraph count as one action or many?
  • Syntax highlighting. Either you integrate a library like Tree-sitter, or you write your own lexer. Both choices have consequences that ripple through the rest of the codebase.
  • Rendering. Terminal editors have it somewhat easier here, but you still have to think about wide characters, combining marks, and tab widths.

None of these problems are unsolvable. But each one is a rabbit hole, and the rabbit holes interact with each other in ways that become apparent only when you’re actually using the tool under real conditions.

Daily-driving changes what you optimize for

This is the part that interests me most. When you only use your editor for the project itself, you develop in a comfortable loop: the things you need to do match the features you have already built. But when you use it for everything else, you immediately discover which gaps are merely annoying and which ones are blockers.

Painful undo behavior that you can work around on a small project becomes unacceptable when you’re editing a config file at 11pm and accidentally delete the wrong block. Search that works well enough for a 200-line file hits a wall on a larger codebase. Syntax highlighting bugs that look fine in screenshots become distracting when you stare at the editor for hours.

Committing to daily-driving your own tool is a form of dogfooding that imposes a discipline you can’t fake. You fix what actually breaks in practice, not what seems theoretically important.

The systems programming appeal

There’s a reason this kind of project attracts people who lean toward systems programming. Text editors sit at an interesting level of abstraction: low enough that you’re managing memory, thinking about buffer layout, and caring about latency; high enough that the end product is something genuinely useful rather than a benchmark.

Building a Discord bot, by comparison, is mostly about orchestrating APIs and handling state in a distributed system. Building a text editor is about the machine itself. How does it move bytes around? How does it redraw the screen efficiently? What does it cost, in CPU time and memory, to handle a keypress?

Those questions have satisfying answers, and getting to live with your own answers every day is a different experience from reading about how someone else solved them.

If you have ever started a text editor project and abandoned it when life got busy, this post is worth reading. Not as motivation, but as a concrete example of what it looks like to see the thing through.

Was this interesting?