Wednesday, October 10, 2012

Finishing with ACE

‹prev | My Chain | next›

Last night I was able to get the ACE code editor up and running (with Emacs support, which is all that really matters in life). Tonight, I hope to completely integrate it with my fork of Mr Doob's awesome code editor.

It turns out that ACE and the CodeMirror editor (which is currently used by the code-editor) share a similar API. Updating the contents of both is accomplished with a setValue() method and retrieving the contents is done via a similarly named getValue(). So I perform a quick search and replace of code.getValue / code.setValue for ace.getValue / ace.setValue.

With that, and a little CSS work, I get the code stored in code-editor's localStorage to show up in ACE and the preview to show "behind" it:



That was surprisingly easy. But I am not quite done yet.

Although the code and preview are working, updates are not working. When the programmer updates the code, the preview should be updated to reflect the code changes. Nothing is happening right now. The explanation is simple enough: I removed the editor's on-change handler. Now I need to figure out how to get the ACE equivalent.

Like many of the other ACE settings that I have used so far, the on-change handler is part of the edit session:
ace.getSession().on( "change", function () {
  save();

  if ( documents[ 0 ].autoupdate === false ) return;

  clearTimeout( interval );
  interval = setTimeout( update, 300 );
});
That does the trick. When I update code in ACE, the contents are immediately saved to localStorage. Then, if the auto-update checkbox is enabled, the preview is updated. There is a 0.3 second delay in case the programmer is still typing.

All that remains now is minor clean-up and tweaks. The iframe used to preview the editor contents had scrollbars. I am unsure why this happens now, but the fix is easy enough: set the document margin to 0 pixels.

It seems that the API between CodeMirror and ACE is similar, but not exactly the same. ACE defaults the setValue() method to select all of the contents of the editor. This seems a recipe for deleting everything. Fortunately, there is a second argument to setValue() that specifies cursor position. -1 means at the beginning of the contents:
  ace.setValue( documents[ 0 ].code, -1 );
A few other settings for the editor are:
ace.getSession().setUseWrapMode(true);
ace.setPrintMarginColumn(false);
The first setting means that code will wrap and thus not create horizontal scrolling. The editor is the size of the window, so it is silly to accommodate long horizontal lines of code. I'll break kids of that bad habit before it begins. The last setting removes the visible print margin. I may reinstate that and tell kids not to code past that line. For now, though I remove it as it may be confusing.

I am still unsure whether I prefer CodeMirror or ACE. The default behavior of setValue() in ACE is annoying, but easily addressed in the 3 places that the code-editor uses it. It is nice that ACE does not appear to suffer from the Chrome redraw bug. I may switch for that reason alone.

Day #535

No comments:

Post a Comment