This is a discussion/thought-process document with my ideas that I've been adding to recently.
Why a web frontend for Emacs?
- A web frontend would benefit from being cross-platform in the sense that you have one implementation, and now any web browser on any platform is capable of providing an interface for you. Currently Emacs maintains many codebases for different frontends.
- Web browsers will support Wayland faster than Emacs will support Wayland.
- You can embed web pages via iframes, which can be used to browse documentation, or even creating a web browser within Emacs that can display anything a fully fledged browser can.
- You can embed graphics, animations, canvas, GL and other widgets available to a modern web browser, and put this into e.g. a REPL, a code editor (e.g. a colour picker in css-mode).
- Thanks to Electron, you can produce a native "app" from such a web interface, that would look no less first-class than graphical Emacs itself.
- Working over a network (e.g. websockets) would allow you to "live stream" your Emacs to other people who could view it trivially with a web browser (no installation or setup neccessary).
- It would serve as a nice proof-of-concept/fact-finding project in order to consider more ideal implementations, such as an SDL-based Cairo/OpenGL-based implementation of Emacs.
Emacs is a Lisp engine with built-in support for buffers and windowing. It has frontends: a terminal frontend, a Gtk & X.org based frontend (capable of displaying more colours and font sizes and styles), and also Cocoa and Windows frontends.
To provide a web frontend for Emacs, you would need a web page to connect to Emacs via a websocket (for which there's a library in Emacs Lisp) which would:
- Emacs side: Receive incoming keyboard (text typing and commands) and mouse events (clicking, selecting, scrolling) from the client, and run them.
- Web side: Receive updates to the windows and buffers, replacing parts of the buffer that changed along with text properties (they can be rendered to string as plists), creating and destroying overlays, and send keyboard & mouse events to the server.
There would need to be special handling for window management, and for the minibuffer which is always visible, as well as the modeline and "fringe" (which is the left-hand-side bar sometimes used by flycheck and things like that).
To produce a frontend, you hypothetically only need a few things. These things are provided by CodeMirror:
replaceRegion
- can be used to update changed text coming from Emacs, which lets us only change part of the buffer, rather than rewriting the whole document.markText
- can be used to set text properties, which is used for highlighting and visibility among other things in Emacs. jsfiddle example hereaddOverlay
- can be used to create overlays, just as they are done in Emacs.setSelection
- can be used to set the cursor position and the selection.- Capturing keyboard input in a cross-platform manner.
- Capturing scrolling and other mouse input in a cross-platform manner.
Font faces would be sent from Emacs to the Web client periodically
(unless I can find an appropriate Elisp hook; this may be an update
only made available to the C frontends), and encoded as CSS rules,
with custom face properties specified as style
properties in the
DOM.
CodeMirror doesn't render the whole buffer to the DOM, it only renders what needs to be visible based on the scroll position. That's a useful optimization because we can send the whole buffer contents to CodeMirror in one go.
Hard to say whether the general performance of sending keys over a websocket, and then buffer updates back, will be fast enough not to see a noticeable delay. The only way to determine this is to test it out.
Reminder that Emacs's X11 implementation isn't particular beautiful or efficient either.
- The case for a web frontend for Emacs is compelling.
- It should not be much work to create a CodeMirror frontend to Emacs.
What about using react? Then it could be bridged to native platforms to support faster rendering. For example, I'm building a react bridge to GTK, which currently supports WayLand. Of course you could also use the electron react bridge, and hey why not even natively render it to Android and iOS, (although I'm not sure about the implications of the underlying LISP code). Theoretically the LISP code could work on any environment that supports web assembly.