Replies: 1 comment 3 replies
-
|
I'm not @eval-exec, but I've thought long and hard about this as well. I don't think Python is the right choice here. I've used Python for a long time and my greivances with Python always converge to the same fundamental problem: Python is not Lisp-y enough. For a new editor, I think keeping elisp is ok. What could be better is to support SBCL or some other Common Lisp variant. I personally think that would propel development in a good way for the ecosystem. We don't necessary have to embed a "popular" language as the scripting language here. Having a small barrier in terms of language choice selects for good developers at the end of the day. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi @eval-exec,
I’ve been following Neomacs closely, and I want to start by saying: you are building exactly what the text editor ecosystem desperately needs right now.
To give you some context on where I'm coming from: I’ve spent the last five years as a hardcore Neovim user and Data/System Analyst. Neovim is incredibly fast, but recently, I hit a hard ceiling with its interactive rendering capabilities. Terminal UIs simply cannot handle the kind of rich, 120fps GPU-accelerated and fluid UI manipulations I want in a modern workspace.
Looking for an alternative, I turned to GNU Emacs, and I immediately fell in love with its core philosophy: Extensibility & Unification of Human & Machine. The total malleability of the editor—the idea that it's an introspectable OS rather than just a text editor—is a masterpiece of software design. But then I hit the Emacs ceiling: the single-threaded Lisp architecture. One heavy computation freezes the entire UI.
That led me to Neomacs. By rewriting the core in Rust and utilizing GPU acceleration, you’ve completely solved the rendering and concurrency bottlenecks. You’ve fixed the engine.
But as I looked at the project, I realized there is a secondary bottleneck looming: Community and Ecosystem. For Neomacs to thrive, it needs the gravity of a massive plugin ecosystem. And the hard truth that must be acknowledged is that Elisp—despite its historical brilliance—is the true culprit for the lack of rapid community growth in both Emacs and Neomacs. This has also become the bottleneck for extensibility philosophy in 2026.
I spent the last few weeks in a deep internal debate about how to bring modern extensibility philosophy to Neomacs without sacrificing the Unification philosophy of Emacs.
The Solution: Interface DSL (Domain Specific Language)
My immediate instinct was: What if Neomacs can be configured by the most popular language in the entire programming community? Based on this view, I started exploring alternatives. JavaScript/TypeScript and Python were the best options based on my analysis. Out of those, Python is the clear winner because of specific language technicalities. In short: the marriage between Rust and Python was probably decided in heaven.
My first thought: Lazy Evaluation
I thought this would be an absolute breakthrough. Applying Lazy Evaluation to an editor's architecture would be a paradigm shift. I thought, I am not just suggesting a new language; this would be a completely new way to think about how a text editor handles state and events.
Eager Execution is the culprit (the Old Way). If Neomacs uses Python eagerly (like Neovim uses Lua or Emacs uses Elisp), every time a user presses a key or saves a file, the Rust core would have to wake up the Python interpreter, cross the FFI boundary, run the Python function, and wait for the result. The problem: crossing that boundary thousands of times a second is slow. The Python GIL (Global Interpreter Lock) becomes a bottleneck.
In the Lazy Evaluation approach, Python does zero data processing. It just builds a blueprint and hands it to Rust. Rust then optimizes the blueprint, compiles it into native Rust, and executes it at Rust's speed. At startup, the Python config runs, but it doesn't execute editor commands. Instead, it builds a config blueprint (a graph of keybindings, hooks, and UI states). Python passes this plan to the Rust core via PyO3 and says, "Here is how the editor should behave. I'm going to sleep now." Rust compiles that plan into pure, native Rust. When you type, save, or render the screen, Python is completely out of the loop. The Rust core is executing the plan at 120fps. "Hot-swappable expressions" can be implemented to mimic the live configurability that arises by adopting Python with a lazy evaluation architecture. Crashes due to misconfiguration in the interface language can be completely handled or resolved in the Rust core. It solves the biggest counter-argument: "Python is too slow to run on every keystroke."
When I closely inspected the Python lazy evaluation architecture, this thought struck: What about live execution? The soul of Emacs is image-based persistence and
eval-defun. Mimicking live configurability through hot-swappable expressions means no true live execution. By suggesting a Python-based lazy evaluation architecture, I realized I was killing the soul: the Unification of Human & Machine philosophy.My second idea: Why not write a Python-to-Elisp compiler? (Pylisp)
Pylisp: A declarative DSL, used strictly for editor configuration and UI manipulation, leveraging modern, method-chaining syntax to construct Elisp expressions. Pylisp would allow users to configure Neomacs using clean, Pythonic expressions. But looking at the AST, I realized it's a trap. Python's lexical scoping clashes horribly with Elisp's dynamic history. Furthermore, mapping Python's single-dispatch OOP to Elisp's EIEIO multiple-dispatch system would generate bloated, unreadable Lisp code.
Even though this would be a nightmare to implement, and Pylisp would be an abstract layer on an abstract layer (Elisp) on another abstract layer (Rust), I thought: what's wrong with throwing a little more RAM and CPU at the problem? This doesn't kill the soul.
However, something felt off. I sounded more like a "Javascriptian" than an Analyst. Closer examination revealed that, in the name of suggesting a new language, I would be suggesting the community build an ecosystem not around Python the language, but around a Python package. This convinced me I was entering "JavaScript land" for sure.
The internal debate haunted me: Is the trade-off of philosophy worth it to onboard the Python community and gain access to the Python ecosystem? I came to the conclusion that we can't just "bolt Python onto Emacs" and call it Neomacs. We need an architecture that respects the Lisp Machine legacy while opening the floodgates to the Python ecosystem.
Further exploration suggested no other popular language can come close to Elisp. At this point I was frustrated, thinking there would only be trade-offs, and decided—with the intention to minimize those trade-offs—to examine the Emacs architecture one last time.
The examination gave me a clean picture of what Emacs is: it is an Elisp interpreter. This gave me the hope I was desperate for, because Python is also an interpreted language, albeit a slow one.
The
rustpythonInterpreterBecause of my data analytics background, I had already dealt with the slow Python interpreter by using
numba.njit(). Further exploration led me to the solution: a Rust crate calledrustpythonwhich supports JIT out of the box. This was the "eureka moment" for me. The Elisp interpreter was the soul of Emacs; arustpythoninterpreter can be the soul of Neomacs. And probably a better one, too. My gut intuition is that a newrustpythoninterpreter with a modern architecture will be faster or at least at par with the Elisp interpreter.Syntax Readability (The Pseudocode Effect): Configuration files should be declarative and easy to read. Lisp is deeply nested (the "sea of parentheses"). JavaScript is heavy on brackets and callbacks. Python forces whitespace indentation. A 1000-line Python configuration file fundamentally reads like structured pseudocode. It is cleaner to parse visually.
If we compare Python against Lua (Neovim), JavaScript (VS Codium), or Elisp (Emacs), Python’s Standard Library has
pathlib,subprocess,json,urllib,sqlite3,async, andthreadingbuilt right in. A plugin developer can write a complex, OS-level integrated plugin without needing to go through the hassle of installing a single external dependency. Python provides access to world-class tooling and gradual typing. Editor configurations get huge and complex. Writing thousands of lines of untyped Elisp or Lua inevitably leads to runtime errors that only trigger when you hit a specific key combination. Python supports type hints. The Neomacs Rust core can generate Python stub files (.pyi). When a user is writing their config, their LSP will give them perfect autocomplete, hover documentation, and compile-time error checking for the editor's API. We get a mature, industrial-grade development experience just for configuring the editor.**Introduction of a Rust-based,
uv-inspired package manager:nemx**When I say "uv," I am also referring to Cargo because
uvis already inspired by Cargo.nemxdoesn't just install Rust crates or Python packages; it fundamentally changes how developers interact with their environment. Neovim useslazy.nvim, which is just cloning git repos. If a plugin needs a system dependency, we have to use middleman tools likeMason.nvimor install them via a system-level package manager. VS Code hides everything behind an opaque marketplace. Right now, sharing an Emacs or Neovim config is a nightmare. Even if you share yourinit.elorinit.lua, it causes silent breakages for the person copying it due to environment mismatches.nemxintroduces strict, hash-verified lockfiles. Our entire editor configuration—including the exact commit of every plugin, the exact version of therustpythoninterpreter, and the exact version of the Rust core—will be locked in aneomacs.lockfile. This empowers the user to share their config with anyone on any machine. They runnemx sync, and they get a 100% byte-for-byte identical editor environment in seconds. "It works on my machine" could be permanently solved for text editors. This will also be our line of defense for the "dependency hell" that Python can bring.Above all, no sacrifice on philosophy
I acknowledge the "Ecosystem Bankruptcy." Swapping Elisp means sacrificing 40 years of highly specialized Emacs packages; we lose Magit, Org-mode, etc. I think it is time to take the "Human & Machine Unification" philosophy to another level. We shouldn't force users to write raw Elisp, or only Python. In 1976, the "Machine" was a local CPU; now in 2026, the Machines are local and remote. As I said earlier, Neomacs should support all popular and interpretable languages.
I believe we should build a foundation for the next generation with the help of Rust. If we are trying to bootstrap a brand-new editor in the name of performance, in the era of cloud computing, we are fighting a war for a developer's free time. I believe there should be no entry fee (language barrier) for adopting Neomacs.
This architecture doesn't betray the Emacs philosophy; it evolves it. This is the bet I am making: Rust and Python communities are notorious for rewriting entire domains they can access at their respective scopes.
No priority collision, @eval-exec. The promise you made to Neomacs—complete reverse compatibility—stands. We will implement a Rust-based Elisp interpreter faster and together with a bigger community.
Let me know what you think of this proposal for Neomacs.
Beta Was this translation helpful? Give feedback.
All reactions