Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Last active December 7, 2023 16:10
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdone/f874ac1c872c004d6ce9e3cb20cc59e0 to your computer and use it in GitHub Desktop.
Save chrisdone/f874ac1c872c004d6ce9e3cb20cc59e0 to your computer and use it in GitHub Desktop.
Idea: A web frontend for Emacs via CodeMirror

Idea: A web frontend for Emacs via CodeMirror

This is a discussion/thought-process document with my ideas that I've been adding to recently.

Motivation

Why a web frontend for Emacs?

  1. 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.
  2. Web browsers will support Wayland faster than Emacs will support Wayland.
  3. 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.
  4. 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).
  5. 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.
  6. 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).
  7. 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 background

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.

Web frontend

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:

  1. Emacs side: Receive incoming keyboard (text typing and commands) and mouse events (clicking, selecting, scrolling) from the client, and run them.
  2. 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).

CodeMirror as a frontend

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 here
  • addOverlay - 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.

Performance

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.

Conclusions

  1. The case for a web frontend for Emacs is compelling.
  2. It should not be much work to create a CodeMirror frontend to Emacs.
@clayrisser
Copy link

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.

@clayrisser
Copy link

clayrisser commented Oct 21, 2018

Oh BTW, here is my react bridge I'm working on. Currently it's only proof of concept, but I'm planning on really buckling down and finishing it in 2019.

@clayrisser
Copy link

@thomasjm
Copy link

This is an awesome idea. A couple thoughts:

-- I've done something similar myself by running xterm.js in a browser, with a websocket connected to a terminal where Emacs is running in terminal mode. Emacs works fine this way and the latency is fine on a good internet connection.

-- However, one of the most aggravating parts of running Emacs in the browser is that it's impossible to capture certain hotkeys in a browser without jumping through extra hoops. Most sadly for Emacs users on Chrome this includes Ctrl+n; see https://stackoverflow.com/questions/7295508/javascript-capture-browser-shortcuts-ctrlt-n-w.

@gtusr
Copy link

gtusr commented Feb 24, 2023

Can Emacs NG - A new approach to Emacs help make this excellent proposal a reality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment