Introducing Ymacs

Ymacs is an Emacs-like editor that works in your browser. Currently (starting with tag v0.4 in the code repository) it works in recent versions of Firefox (and other Gecko-based browsers), Google Chrome and Apple Safari.

This project is based on DynarchLIB, my AJAX toolkit.

News

2012-03-28 — tagged version 0.5. Thought it was dead, huh? It's not. I did some smallish fixes lately related to OS clipboard, a better Lisp mode (it implements an additional parser to support better forward_sexp (C-M-f) / backward_sexp (C-M-b)), added comment_dwim (M-;), comment_region and uncomment_region , which currently work in JavaScript mode and Lisp mode. Some more color themes, etc.

2010-01-17 — We now support Chrome and Safari officially. Tagged version 0.4 in the repository.

2009-12-14 — Added a CSS mode, toggle_line_numbers (C-x l), mark_whole_buffer (C-x h). Various small fixes and improvements. Tagged version 0.3 in the repository.

2009-12-08 — Lots of new stuff, although the user-visible changes are not very big. In any case, this refactoring was needed: commands are now separated into functions and interactive commands. The M-x completion menu will only list interactive commands. We support a subset of Emacs' interactive codes for defining commands. With the above came the easiness to define commands that take arguments—hence M-g, for now, which moves to a certain line number. We also now have prefix arguments (C-u). Tagged version 0.2 in the code repository.

2009-12-04 — Look ma, M-x! :-) M-x eval_region, even. And TAB completion for command names. Some commands from that list aren't meant to be called interactively—I'll start some refactoring for this soon. Other new stuff: C-x b to switch buffers (TAB completion available, but the default value, which should have been to switch to the previously visited buffer, is missing). Using C-x b you can also create a new buffer—just type a name for it. Then use M-x javascript_mode, or xml_mode etc. M-x htmlize_region — will create a new buffer and put into it the HTML containing the current “syntax highlighted” code (uses class, not inline styles). For more, check the commit logs.

2009-11-24 — Checked in a new bunch of changes, and updated the build: we now have a Lisp mode with basic syntax highlighting, automatic indentation, paren matching and auto-closing (C-c ]); text selection using the mouse, and fixed it for variable-width fonts; basic Markdown mode. Various other fixes. Press C-TAB in the demo to reach the Lisp or Markdown buffers and test.



How much Emacs-like?

Of course, Emacs is a gigantic beast with some 30 years of history. I'm not ambitious enough I don't have enough time to copy all it's features, but however Ymacs currently can do the following (and I think it's worth its name):

Emacs-like movement keys: by character ( ARROW_RIGHT , ARROW_LEFT , C-f , C-b ) by line ( ARROW_UP , ARROW_DOWN , C-n , C-p ) by word ( C-ARROW_RIGHT , C-ARROW_LEFT , M-f , M-b ) by paragraph ( C-ARROW_UP , C-ARROW_DOWN ) even by balanced expressions in some modes ( C-M-f , C-M-b , C-M-n , C-M-p )

(but this is really slow currently) beginning of buffer ( C-HOME , M-< ) end of buffer ( C-END , M-> )

Emacs-like text manipulation commands: transpose chars ( C-t ) transpose words ( M-t ) transpose lines ( C-x C-t ) upcase word ( M-u ) downcase word ( M-l ) capitalize word ( M-c ) center line ( M-s ) word killing ( M-d , M-DELETE , C-BACKSPACE ) dabbrev-expand ( M-/ ) — autocomplete the word at point text filling ( M-q )

Emacs-like editing modes (currently JavaScript, XML, Lisp and Markdown): modes can provide custom keymaps and syntax highlighting and automatic indentation highlighting matching parentheses

And other features implemented in a very Emacs-like fashion: undo queue mark, kill ring and transient mark minibuffer and mode line interactive search multiple buffers split frames ( C-x 2 or C-x 3 to split frame, C-x 1 to delete-other-frames) prefix keys, keymaps markers, overlays and text properties M-x



Of course, these features aren't hard-coded in ways that you can't change. Ymacs is customizable and extensible. For example, if you're not happy with Emacs key bingings, it's fairly trivial to define a different default keymap to mimic, say, Eclipse, or Visual Studio. However I'm not familiar with any of these, so I can only hope that this will be implemented by contributors. Do you want to become one?

How did it start?

Like most cool projects, Ymacs started out of necessity. What's ironic is that after hacking on it for a few days, I almost forgot the purpose I had in mind and kept adding features to make it more Emacs-like, faster and more stable and currently, it still doesn't have the features that I wanted in the first place. (however, it got close: it should be easy now to add a decent Lisp-mode).

It started because one day I wanted to learn Common Lisp. I've read some materials, done some trivial applications to see how it's like, and next I thought "OK, let's do websites with it". So I started building a pretty simple content management system, with an AJAX interface based on DynarchLIB. Things were progressing nicely, albeit rather slowly. I implemented my database with PostgreSQL and cl-perec, after serious hassling to learn how to use the latter (which is almost completely undocumented), then I discovered Hunchentoot which is a fine Web server written in Common Lisp, and cl-who from the same author as Hunchentoot (BTW, this guy is fantastic!). CL-Who is a cool way to write XML (thus HTML) directly in Lisp. You could call it a template engine, but it's really Lisp and gets compiled into machine code (depending on the Lisp implementation), which is nice because the templates run blazing fast.

In my CMS I was using an "WYSIWYG" widget for editing pages, which is pretty cool. But each page has one cl-who template. Initially I thought that the templates would reside on the server and would not be editable through the AJAX interface, but then I thought “whY not?”.

So I quickly hacked a new table into the database to hold the templates, and threw together a simple editor for them which was using a TEXTAREA. When I first tried it, I realized that writing Lisp in a textarea is not just unbearable, it's downright impossible. You have to count all those parens. You have to look until your eyes hurt to find out if a string is properly closed or not. There's no editing commands, etc. I'm not blaming the textarea—it wasn't designed for this—I'm just saying that no no, you can't write code into it.

Similar projects - CodeMirror

So I looked for alternatives. There are a few in-browser source code editors (one even claims to be Emacs-like, but that seems to be a joke). The one that worths mentioning is CodeMirror, a project that claims "in-browser code editing made almost bearable". It does stand to it—it works pretty well, it's fast enough, it has very good syntax highlighting and automatic indentation for a few languages. When I checked the author (Marijn Haverbeke) I found that he is a Lisp programmer who actually built some stuff that my CMS prototype indirectly relies on, how cool is that? :-) (Postmodern, a nice library for accessing PostgreSQL databases from Lisp.)

CodeMirror is based on designMode; you should read Marijn's story about writing CodeMirror to see the struggles that the man went through in order to build his editor on top of this interface (by the way, this is a good time to give proper credit: his story inspired me on handling syntax highlighting and indentation using a resumable parser that saves its state at the end of each line).

So, first I thouhgt about using CodeMirror. But I really wanted Emacs keybindings. I have some experience with designMode and I know that it's extremely difficult to figure out where the caret is, for example—which would be necessary to implement movement by word, transposition commands or upcase/downcase/capitalize. It seemed crazy so I rejected the idea to modify CodeMirror. Besides, where's the fun if I'm not doing it myself? :-)

How do you do it without designMode and without textarea? Well, draw your own text, draw your own cursor, intercept all keypress events and figure out what to do with them. That's what Ymacs does.

You can read more about the architecture if you're interested.