Text editor done in pure Elm


I’m working on a basic text editor implemented in Elm (need it for elm-browser for ElmEurope), and felt like sharing here.

The source:

A live demo:

So far there’s support for:

  • basic writing / deleting
  • arrows movement
  • mouse movement (by clicking)
  • selection (by mouse)

Yet to do (but no promises):

  • text insertion after selection should replace the text (doesn’t)
  • context menu on rightclick?
  • cut / copy / paste

Basically I don’t delegate anything to textareas etc. - I’m listening to events and rendering everything myself, so there’s total control over what the user is doing (selection etc.)

A thing to note is the “throw random Msgs at update and see if things break” test suite, I’m quite proud of the tests and they’ve been very useful (found quite a number of bugs) :slight_smile: https://github.com/Janiczek/elm-editor/blob/master/tests/CodeEditor.elm

I hope this inspires somebody to try do some stuff in Elm they’ve been needing but seemed too big / hard for them! You might, like me with this project, find out it’s in your reach - no doubt thanks to Elm :slight_smile:


Congrats on the effort! Definitely gonna try this out!


This is awesome!

I’ve wanted to create an editor like this for a long time, the only thing holding me back was that Elm has trouble working with textareas. It seems you worked around that by simply eliminating textareas!

But that does make me think: the reason that most JavaScript-based editors use textareas is to allow the browser to handle native shortcuts. The obvious ones are copy, cut, paste, but there’s also home/end to skip to the beginning or end of a line, Ctrl + arrow to move by word, Ctrl + backspace to delete a word at a time. And many others. (And of course these shortcuts also exist with different key combos on mac). I assume you’ll have to re-implement these in Elm, but they should all be possible and then very configurable. Although I’m not sure about cut/copy… I don’t think JavaScript can programatically insert into the clipboard. Actually, JavaScript kind of can. Although it involves a textarea… basically, JavaScript creates an offscreen textarea, sets the value to the text to copy, selects all the text, and executes the “copy” command. “paste” might be easier… does a “paste” event contain the data from the clipboard?

Anyway, I hope this doesn’t sound discouraging. Just thinking about potential features :wink:


This is amazing! Wow, I was thinking about this just today after playing a bit with Pharo. I though: “hey, Elm is all functions and type declarations, we can build a better editor than a standard text editor…”, I am so happy that you’re building this. I can’t wait to explore the code.


Really cool! Convenient that since it is in one file, I was able to paste it into Ellie!


Really nice, I once tried same solution, but failed to solved problem of moving up and down with non monospaced fonts, do you plan to solve that somehow ?


Not planning to use non-monospaced fonts :slight_smile:


A simple solution might be to know how many character you are along on the line, and position the cursor that many characters along the line above or below when moving up or down - that is, how it currently works.

A solution that maintains the horizontal screen coordinates of the cursor better is going to need to know the pixel width of the text. I had to tackle that recently in order to be able to draw boxes accurately around text in SVG. Package is here, if you feel like doing something with it:


I suppose you could also somehow get bounding rects from the DOM - not sure exactly how to do that for every initial sub-string on a line though. Interestingly, when I tried this with text in SVG sometimes the bounding rect would not be correct - it would be a few pixels too small. So perhaps this kind of approach is not even worth trying.

Either way, getting text widths is a bit of a PITA.

A third way, and something I am interested in exploring, would be to parse the OpenType font into an equivalent set of data structures in Elm - that is codegen them to .elm files. Then implement the width calculations in pure Elm. This becomes worth doing in 0.19, because dead code elimination will cut out any fonts that you don’t use, so a package with a decent set of common fonts could be published and it would not bloat your code.

:+1: Awesome text editor though.


This does text width calculations using the codegen from fonts approach: