I come from a strange land where we program in a language called Dylan (opendylan.org).
In that land, we have an editor called Deuce, which is a descendent of ZWEI, a predecessor to emacs.
It has some interesting features:
- Lines are polymorphic. They can contain text, graphics, etc.
- There is the concept of ‘Source containers’ and ‘source sections’. A buffer is composed of ‘source sections’ which can come from different containers. In a nutshell this means you can have a single buffer where different parts of that buffer come from different files. For example, Deuce uses this to display a single buffer containing all the callers of a method. Each method definition in the buffer comes from a different source file. Editing that section of the buffer edits the original file.
- The capability for graphics is included.
- A simple presentation framework is part of the design. Allowing ‘live’ objects in the editor.
- GUI presentation is separated from editor functionality allowing different GUI back ends to be used
This editor is used in our IDE, which is currently only on Windows, but it actually works and the code is fairly straight forward (and MIT licensed).
A discussion of this editor is briefly contained in https://groups.google.com/forum/#!msg/comp.lang.dylan/3uuUb3Z9pAc/6NbE9gYpeAIJ
The code itself can be found here: https://github.com/dylan-lang/opendylan/tree/master/sources/deuce
The original code was written by Scott McKay (who posted in that discussion linked above) in the late 1990s, so the considerations of time for memory usage and performance may apply well today. Scott McKay was also a former employee of Symbolics and worked on the Lisp Machine there, so there’s quite an interesting history and heritage to this code.
This code is, almost entirely, independent of the GUI that displays it, so it could help inform the parts of the Atom editor that handle the text, independent of the DOM that is used to display it. (This would be useful for handling large files for example.)
Overall, the code structure is:
windows.dylandefines a window object. A window holds a buffer (among other responsibilities).
buffers.dylandefines a buffer which is linked to a source container. There is also a file
browsing-buffers.dylanwhich defines composite buffers that link to multiple other buffers. This is how search / callers / etc can be handled. Saving a composite buffer actually goes out and saves the buffers that it refers to.
containers.dylandefines the source containers, which usually correspond to a file. A container can be sectionized (divided into sections) using a “mode” (like a language mode). This makes it easy to do things like IntelliJ does with dividers between method definitions, etc.
sections.dylandefines the source sections, which are a sequence of lines originating from a source container. Sections are actually linked into buffers via nodes (
nodes.dylan). This lets a single section be present in multiple buffers at once.
There are a number of other files (obviously) and more to the overall architecture, but I’m hoping that the above might be interesting and informative and this already a long post.
I’d be happy to answer questions about this or talk about it more.