Emacs-ng: A project to integrate Deno and WebRender into Emacs
github.com
github.com
Emacs desperately needs to deal with its tech debt, but adding a new language runtime without addressing the mountain of architectural issues is just circling around the problem, without actually even looking at it. Hats off for the effort but I'll pass.
This is one of the things that _are_ addressed by the project.
Regarding your broader point, I don't know if adding a new language would/will help emacs or not but it's _plausible_ something like that would work. The plugin ecosystem in the vim world became more vibrant once writing them in lua was an option.
I don't think it is plausible. Emacs extensibility and power stems from the fact you can see and change almost everything. You can add advice, i.e. modify, any function there is. And you can inspect any object that exists in the heap. If you add another language into the mix, these two languages either have to share an object/data structure model or they have to bridge them somehow. In vim you have plugins that add new commands, or hook into some callbacks. But in emacs you can extend every third-party functionality with another third-party library. Fragmenting the ecosystem into two language camps would probably diminish this advantage.
For LSP (language server protocol), eglot worked out of the box quite well once installed. It ships by default in emacs in the latest versions.
That said, I would love to see the issues you mentioned addressed, and would love to see how the EAF[1] does in the future.
Ecosystem yes, and also it's architecture and culture. ELisp I would say no. If we ignore the specific flavor, then 99% of what's realistically done with with elisp, is also covered by other dynamic languages like JavaScript. And the rest is so esoteric that it's probably not that worth the trouble.
> I don't see how supplementing ELisp with JS would make Emacs more attractive;
Not everyone likes lisp, not everyone is willing to learn a new strange language for unknown benefits. And JS has a vast ecosystem of its own. Far bigger even that Emacs heritage, but on different areas. A well working combination of both, with no side making significant sacrifices, could be very alluring for many more people than Emacs has now.
Emacs is unique and I'd like to preserve that.
>What's wrong with spreading all this to other spaces, and letting other people learn about them, making them more accessible?
Because the philosophy of Emacs and the computing tradition it grew out of is fundamentally at odds with those other spaces. Everything being in one dynamic language is a huge and intrinsic part of that tradition.
I suppose you could write an Emacs entirely in javascript if you wanted to, if you followed the same software philosophy. But personally I think Javascript is such an inelegant language that a lot of the power of the idea would be lost even in that case.
I don't think that's true at all. Emacs is a lisp-machine, but that's just the means, an implementation-detail, not the culture and the aim. Every shell, web browsers, any REPL is pretty much the same as Emacs, just in a different flavor. The culture I'm talking about is to have a customizable tool & workspace. Something that adapts to you, a canvas where only your time and imagination is the limit. Limiting Emacs to being "just" lisp, is doing it a disservice.
I can almost see the argument for browser, but we left user customization as the default in browsers a long long time ago.
To make my point a bit more concrete, the culture of lisp-machines was that the user was in full control. Curious what will happen if you type something? You can literally lookup what will happen on any keystroke or button press. Curious what code runs for a function? Odds are high that you can jump into the code for any feature and edit it on the fly. Yes, there are some native code sections that you can't do this for, but the vast majority is not that.
Browsers are nothing like Emacs in design philosophy(except Nyxt, which gets close, but falls a bit short due to intrinsically having to deal with a bunch of JS; an excellent example of my point, come to think of it).
Take Firefox for example. It has extensions, but they're intrinsically limited by the fact that they're sandboxed and can only interact with the browser through a limited API. And yes, you could certainly extend it arbitrarily by changing the C++/Rust/whatever code and recompiling it. But it's not designed to be extended that way by users.
In emacs, the configuration is really just patches applied to the code at runtime. There fundamentally is nothing you can't do through the configuration.
But why Lisp you say? Precisely because Lisp is a dynamic meta-programming language, which is the ideal paradigm for this. It can be molded to be a highly abstracted configuration language without losing the ability to run arbitrary code. You get all the upside of JSON, YAML, XML and other configuration languages with none of the downside of being limited in what you can do.
Adding javascript to the mix just complicates this simple and elegant model. You gain nothing in extensibility, and will probably lose quite a lot unless you take extreme effort to avoid it through clever design.
That's design, a choice. It used to be different in old Firefox, and other browsers are different in that aspect even today. But to be fair, I mainly meant the page-context, not the application-context. Most normal web browser support userscript, bookmarklets and debugging some way or another. Or should I say, still. Because this is a bit in decline. And if you take something like web- or electron-apps, the page-context becomes the app itself. All just a matter of implementation and architecture.
> There fundamentally is nothing you can't do through the configuration.
You can't patch the C-core, can you? Another necessary implementation-detail.
> Precisely because Lisp is a dynamic meta-programming language, which is the ideal paradigm for this.
It was ideal when Emacs was created. Today, we have many alternatives.
> You gain nothing in extensibility,
Except more ability, more heritage, more users... At the end, it's all a matter of managing the tradeoffs, the implementation-details.
The C core contains low-level things or performance-sensitive things that one really doesn't want to patch. Nevertheless, lots of things in the C core are configurable and extendable through hooks.
> Except more ability, more heritage, more users... At the end, it's all a matter of managing the tradeoffs, the implementation-details.
Regarding heritage, you can't get more than Enacs has, which was around when GUI didn't even exist yet.
Users who are put off by the choice of configuration language are unlikely to be productive extension writers [edit: in any language].
Something as simple as getting advice for solving a problem on web forums would also be affected by the dichotomy. I think that might be worse for newbies.
Still, I think it's fine to run the experiment, and see if that is what people want.
Im curious why someone would use emacs if they dislike lisp. To me its like writing SPAs without js
Why use Windows (or MacOS, or Linux) if you don't like C?
Which aren't unreasonable questions; there are a lot of people who use XMonad despite not caring about Haskell, just because they enjoy using it.
Emacs has a much more focused UI than vscode. It's not obvious to me how to make all the extraneous things I'm not editing disappear.
The emacs-compatible extensions as far as I've seen still haven't been able to make switching files in vscode as fast and convenient as switching in emacs. I spend more time maintaining software than writing new code in a single file, so this is a noticeable slowdown.
VSCode doesn't feel as fast. I never fully investigated all the reasons. But I might make another attempt to move to it after it has a few more years to improve.
If you want to use JS, there are plenty of places to do it. Some of us just want to avoid that dumpster fire.
And if JS is so wonderful, why not make a JS editor from the ground up?
As much as I dislike elpa package manager, the mere thought of having to use npm or similar in Emacs makes me nervous already.
Is that really true?
https://github.com/search?q=repo%3Amagit%2Fmagit%20defmacro&...
I think it's fair to say that if you don't like ELisp, Emacs might be the wrong choice for you. I'm not being elitist, I just think the two are glued together even closer than POSIX and C, and it would be extremely difficult to avoid it.
Not sure how much of it has eventually become part of it, as I seldom use Emacs, even though 10 years of usage leave their mark on the brain. :)
I see Emacs finally adopting Guile as a much better path going forward, than attempts like these.
Deno and WebRender have good integration with workers, webrender offers the option of providing better GUI integration (although it's not clear exactly how it will be leveraged), jumping to Javascript gets rid of dynamic scoping, and (in my experience, although mileage may very much vary) tends to handle IO-blocking better.
The project's performance justifications it lists are:
> Async I/O from Deno, WebWorkers, and WebAsm, gives you the tools to make Emacs a smoother and faster experience without having to install additional tools to launch as background processes or worry about shared library versions.
I don't disagree necessarily, in some ways adding another language instead of fixing the one that's still going to be the dominant way most integration is handled is a very, for lack of a better word, temporary fix. If Lisp isn't good enough for an editor, then we'd all jump ship to VSCode or whatever. There is something hacky about saying, "we're not leveraging this language well, let's just add another."
But even saying that, I do still (at least at first glance and without looking into it harder) see the appeal.
Even dropping the JS entirely, WASM workers seem like a non-terrible way to get better worker support and to get rid of the IO-blocking-UI problem (which I agree is a problem, and might be one of my biggest criticisms of Emacs). Am I missing something?
And if you try to solve it using workers you introduce an annoying programming paradigm of async/await and IPC.
Copying data over IPC can be slow, and having to set up IPC to share the data you need to run in a worker is also annoying.
The great thing about the single threaded shared memory model of elisp is that it's a lot easier to code against. And yeah sometimes someone blocks the UI doing synchronous I/O, but that comes at the benefit of making it really easy for people to write addons that do all sorts of things.
A lot of the I/O blocking UI problems could be alleviated by just moving to async I/O primitives without incurring the runtime and developer experience problems of a multi process architecture
I don't want to dismiss the argument; maybe it's just that Emacs packages are bad at avoiding that behavior? But I'm not sure that async I/O primitives are enough for a text editor, even though I would generally agree with you.
On the subject of that last sentence:
> A lot of the I/O blocking UI problems could be alleviated by just moving to async I/O primitives without incurring the runtime and developer experience problems of a multi process architecture
This sounds like an advertisement for Javascript to me? This is one of the reasons I think why NodeJS became so popular when it was first introduced, literally because it was single-threaded with good async I/O primitives (or good enough, this was before Promises were in the language), and that led to huge performance improvements over other server implementations that prioritized workers.
So while I still don't like the kitchen sink approach, I'm still left feeling like a lot of the problems and solutions being proposed here are kind of things that would be addressed by using Deno in Emacs? At least, I'm seeing the appeal. Single-threaded memory pool to help make developer experience better and to improve performance, coupled with decent async I/O primitives -- that's Javascript, that's one of the things the language is sort of good at. You have workers for larger tasks, and that's definitely handy, but most of your programming is happening in a single-threaded event loop using promises.
If I looked at this sentence in isolation, I would think that you were arguing in favor of adding Deno.
That is a pretty strong argument which I agree with. The somewhat dismissive answer I could give around JS in Emacs is that if I wanted to write JS so badly that I was willing to rewrite the ecosystem in order to do it, I'm not sure why I shouldn't just use VS Code.
I'm floating the idea that JS would be a good fit for a lot of these problems, but it is correct to ground that with the idea that having 2 separate coding languages in a text editor just feels weird and cumbersome and I don't know, isn't the ecosystem fragmented enough? I can't actually avoid Elisp in Emacs and I wouldn't be able to just because Javascript was added.
As far as I can tell Emacs already supports the primitives required to implement an async/await style interface. The way it works now, is that the editor is one big event loop. The event loop handles reading keyboard input and eval'ing the elisp functions bound to those keys, and while that's not happening, non-blocking things like subprocesses are being progressed. This happens outside of elisp, inside of the C part of Emacs somewhere.
Right now subprocesses support using custom "sentinels", these are an elisp function that gets called by the event loop whenever the subprocess progresses in some way.
I'm not really a concurrency expert but I think you could work these already existing things into a nice interface. Having built in support for this would be a huge upgrade!
There are libraries like emacs-aio that try to do this, but I don't know very much about them right now, but that should at the least serve as a proof of concept.
That's literally fork/wait + pipes.
async/await APIs are just a fancy abstraction over an event loop and callbacks and whatnot.
Even just having "promises" would be a nice upgrade.
Maybe it's just me but I find the current functions for doing non-blocking stuff very clunky and awkward.
So, yes, you can block the UI thread. There have been ways to not do that basically forever. I welcome better ways to manage this, but there will always be some way to do code on the UI thread, such that it will always be possible to somewhat block things.
The alternative is to make all code preemptive, it seems. And that just begs for race conditions on the shared mutable state that is the editor.
The problem is I had to use Atom for a while seriously before I understood how often it failed for me. If you're just trying out a text editor to see if it's comfortable, you don't see these failure modes as clearly. So I've tried VSCode before, but I don't know if it's better or worse at avoiding hanging the UI, because I don't use it constantly all day long with a ton of packages installed.
If I had to make a list of all the times I get frustrated at Emacs, a long operation that has nothing to do with the UI blocking everything is pretty high on the list, that is a regular complaint that I have. I feel comfortable saying that I wish Emacs packages would get better at this, and maybe there are ways to improve it within Emacs.
But I guess truthfully for all I know VS Code could have the same problem but even worse.
I agree that making code preemptive is probably not a good idea.
Sure, it’s possible to write code that doesn’t block the UI, but it’s very difficult in Emacs and just about every built-in functionality is an offender. This includes network operations, which can block forever. You’d be laughed out of the room if you implemented a text editor today that can lock up completely and indefinitely with M-x package-list-packages.
You are right that it is difficult in many respects. But it is far from impossibly difficult. And most of the tricks you could do to make it easier typically lead to some silly hard edge cases in the code.
Me too.
I routinely run emacs on a Raspberry Pi IV building large rust projects
Blocking has never been an issue
I bury the compilation buffer and carry on as usual
The main problem I have is too many options and possibilities
I think a better thing to do is organise all the third party packages with decent documentation
The documentation in the package ecosystem ranges from barely adequate to woeful with the emphasis on the latter
I genuinely don't think it is - Javascript is just a language. Why not implement Async I/O and WebWorkers APIs in Elisp? Why complicate things with an entirely new language?
And with Elisp native compiled on most platforms, it seems doubtful WebAsm is going to make a noticeable difference in performance.
Yes, it will change its name from Emacs (8 megabits and constantly swapping) to Etacs (8 terabits and constantly swapping). /s
Backward compatibility is the elephant in the room about some of this stuff that most Emacs users absolutely take for granted. I personally have about 20 years worth of Emacs Lisp config files; and others have more decades worth. They largely have continued working for all those years.
I hope that whoever is working on this fancy Deno/Javascript stuff realizes this, and actually talks to some Emacs users if they want any kind of actual adoption.
When I look at the README, I'm seeing one mention of "Warning: This feature is currently unmaintained", and another of "Note: This feature is currently outdated and been disabled. However there is this to bring it back." This...does not inspire confidence in the minds of long-term Emacs users.
Now, maybe I'm being curmudgeonly and unfair. Like the README says, I do want Emacs to be a an editor for the next 40+ years. I just doubt it's going to get there without Emacs Lisp.
I am a game programmer by trade, and I had experiencing embedding JS into projects from a previous engine I worked on where JS was the primary gaming scripting layer.
I love emacs and I love lisp in general - I added JS to emacs mainly to find out if I could do it. I also had a hope that adding JS could expand emacs usage to people that don't know elisp, and have JS be a "gateway" into elisp.
I think that the JS integration is a huge testament to the flexibility and quality of emacs and elisp.
As I have gotten older, I've had less and less time for open source, but I don't consider this project abandoned. I still want to upgrade us to the latest deno. My previous upgrade attempt (which you can see in draft PR at the time of this comment) was a little too ambitious - I tried to move us to a more multithreaded approach, but I think I need to work on this more incrementally.
Edit: I decided to have a quick poke around, and there are ~40 non-upstream commits this year. About half of those are minor cleanups and cargo dependency updates.
There are plenty of problems in Emacs that need to be resolved, but this is NOT one of them.
Helix is great and I have a plugin in mind and I aspire to get more acquainted with the lisp perspective (though I find emacs a bit much). It's gonna be fun.
I tip my hat and then some to the fine folks rolling this stone up the mountain. And that’s coming from someone who is married to elisp.
> The GNU Shepherd is a service manager written in Guile that looks after the herd of daemons running on the system. It can be used as an “init” system (PID 1) and also by unprivileged users...
Not systemd, but it is an init system.
The other unfortunate part of this is that it's based on the gtk branch, which breaks certain input chains that I personally rely on
Would this allow emacs to be used as a web application?
No.
I think that it is already possible if you compiled emacs with gtk3/pgtk as toolkit of choice and use Broadway GDK backend.