Atom Editor was, and still is, an amazing piece of technology. It was the first practical example of web technologies running locally, applied to a really hard problem: text editors. It it was, and still is, darn good at handling code.

But it’s hard, close to impossible, to maintain as the way it is. I want you to take all my opinions with a grain of salt, because these represent my own ideas and feelings on the project – I’m not a full-time Atom developer, nor I intend to be one. I just closely followed its development cycle, helped find bugs and problems in the first editions, and I still am in love with the editor, even when it’s clearly dying.

And while I would love to modernize the editor, making some PRs and fixing some issues, it’s close to impossible to do it. I believe the problem lies on the fact that Atom was an editor, and then Electron was extracted from it. I made the same choice on Chlorine too: I first made the plug-in, then extracted REPL-Tooling from it. Even on a WAY SMALLER codebase (Chlorine), this was HARD: there are still internal, private data that is used inside Chlorine that is not on REPL-Tooling.

Atom is the same. The “setup project” for Atom (prepare Electron, parse cmdline args, etc) is INSANELY huge. There are insane cyclic dependencies (TextEditor depends on components, UI, etc, and these depends back on the editor), there are NPM modules that depend on the editor (so you have code living in Atom that is used on NPM packages, and these also access internal state instead of going thought the public API) and there are outdated web features. There’s also some insanity happening: using newer versions of Node.JS got me 404 trying to run npm install, and even using the node version that Atom says to use in the documentation (that’s also NOT the current LTS version of node, mind you) didn’t work reliably. The only way I was able to install all dependencies was by running yarn install FOUR TIMES, and that did the trick (I got a different error every try, but at least, it worked).

But the problem is not this one: there’s simply too much code that lives “outside” Atom.

I tried to handle around issues on an Electron update, and saw that there are NPM packages that are published explicitly to be used inside Atom – and nothing more. An incomplete list of packages is: @atom/fuzzy-native, @atom/nsfw, @atom/source-map-support, @atom/watcher, fuzzaldrin, fs-admin, fs-plus, nslog, pathwatcher, scandal, keyboard-layout, apm, season, and superstring. Some of these depend on native extensions, which mean debugging on Windows, Mac, Linux, on specific Node.JS and Electron versions.

To handle this too much code, I though I could use shadow.cljs.modern to create Javascript classes, and migrate parts of the codebase to ClojureScript. I tried to handle most edge-cases (they almost work, honestly, and on release build they work all the time) but again, another issue happened: quitting Atom, restarting the computer, and starting Atom again gave me errors sometimes. After I fixed this, I found something interesting: while hot-reload do work, some of the requires on Atom are dynamic: Atom only requires some package fragments when it needs (so, for example, migrating things to ESM would be simply impossible, and also Shadow-CLJS didn’t like that many dynamism in resolving dependencies). Another issue I found: I though that all code from TextEditor would live only inside Atom. And that’s just wrong: the editor, with its component, are written in more than 10k lines of Javascript, and they depend on TextBuffer that lives inside a NPM library (that, mind you, it’s CoffeeScript, not Javascript). It also depends on first-mate and specific grammars, and on the NPM lib bracket-matcher (that, again, depends on internal state of TextEditor). Some of these libs (first-mate and its grammars) I could not find a way to run. Finally, Atom uses custom HTML element, and these do not hot-reload.

Which, obviously, translates into “Hot reload doesn’t work correctly inside Atom”. So, even by migrating things to ClojureScript, I still have the static experience of “restart the editor, try something, didn’t work, restart”. I wanted to get rid of Atom’s UI component etch, and it’s simply not possible if I have to reload everything every time… actually, it’s worse than using pure Javascript, because as I told, Shadow-CLJS gets lost with some code that I did.

UPDATE: after talking with Thomas Heller, shadow-cljs author, I found out the problem: The Atom codebase was overwriting the namespace. I just renamed the namespace, and things are working now… except that hot-reload still don’t work correctly because Atom uses custom HTML elements, and these do not update. But at least, I’m at the same “non-hot-reloadable code” from Javascript, not worse.

So… I’m still looking for alternatives. One possible situation is to replace the whole freaking thing with something greenfield – start an Electron project, make a ClojureScript project, and start to add features. Keep the same-ish plug-in infrastructure of Atom, make a JS proxy code that tries to detect the most used APIs that Atom uses (at least in my common plug-ins) and then… try to use the plug-ins that Atom already have, like tabs, tree-view, etc inside the editor. See if it works.

Again, I’m not really sure if I’ll continue this crazy project. So far, all this crazy experiment live in my GitHub (why bother migrating it to Gitlab? It’s already a dying project, at least it can be more visible right?), and I’ll keep posting if I decide on different things.

1 Comment

Can I split the Atom and, from the parts, generate another thing? – Maurício Szabo · 2022-03-01 at 00:19

[…] my last post was somewhat sad – I tell about how impossible is to keep the Atom editor. Unfortunately, it still holds true […]

Comments are closed.