Closed mkremins closed 9 years ago
Pretty hard task to do properly: http://marijnhaverbeke.nl/blog/browser-input-reading.html
I think maybe integrating CodeMirror as an embedded editor for texts could be better time investment in the long run.
Commit bece21fa68ba2c52bb575fe6ea4574913c6444e9 gives us bare-minimum implementations of bullet points 1, 2, and 4 in the OP. I'm cautiously optimistic about 3 because a single-character selection (effectively how the caret is currently implemented) is in some ways just a special case of a full multi-character text range.
@darwin I'll definitely take a look at CodeMirror and see if integrating it makes sense. If you have experience with it, could you comment on the extent to which CM "takes over" keyboard events that occur while a CM editor is focused? Flense's model of actions as functions on immutable data seems to work best when all keyboard events are handled by a single listener at the top level of the DOM rather than in several different places in the leaves of the render tree; <textarea>
didn't behave well under these conditions and this ended up being one of the major reasons we switched away from it.
@mkremins I'm new to clojure, cljs and react+om. I got some experience with some previous version of CM, when I integrated it in a firebug plugin[1]. Marijn - the developer of CM has some LISP roots and his code is very well designed and maintained. But maybe CM is too big and general to be integrated.
Today I spent some time reading your code in flense repositories. And I must admit that I very much like the design and the way how you were able to build pretty complex editor on top of react. I completely agree that building text editor component in the same style, which would seamlessly fit into the whole design, would be preferable. I'm just afraid that building CM-grade text editor in browser environment from scratch is a lot of work. But maybe I'm wrong, maybe you can support just webkit-based engines and this would leave many edge cases out. Also that editor component does not have to be perfect from day-1 and you can incrementally improve it when problems arise maybe with inspiration from CM or Atom implementations.
Well, hopefully I don't actually need to implement anything near a CM-grade text editor in terms of flexibility and power :) The longest "string-like things" I've ever encountered in Clojure source code have been function docstrings; in fact, I'm pretty sure that I've never seen any string except a docstring span more than one or two lines. The upshot of this is that we can likely get away with using a fairly unsophisticated text editor component for stringlike forms. At any rate, I certainly don't expect that we'd need to implement anything as complicated as syntax highlighting or multiple cursors.
Commit 6b86cf0b23eb53c4f19585697a0a41bb2b694e42 makes the text editing caret for stringlike nodes look and feel more like the <textarea>
caret: a blinking grey line that appears between characters, with insertions occurring after the line and deletions occurring before it. The next step will be to implement range selections and make the existing text-editing operations play well with ranges, at which point we'll be more or less up to where we were before ripping out <textarea>
in terms of functionality.
Commit db21977a0eb446522b96bb005b66bf8beb761d75 does most of the heavy lifting necessary to implement range selections. The remaining work involves figuring out exactly how the user is expected to interact with range selections and implementing the desired UX.
Clicking and dragging to select a swept-over area of text is the most obvious way to create a range selection, but implementing this will be kind of complicated. It may be simpler for now to just implement standard text-editing keyboard shortcuts that manipulate the caret and selection range.
alt
+ left
/right
: move the caret word-by-word rather than character-by-charactershift
+ left
/right
: expand or shrink the range by one charactershift
+ alt
+ left
/right
: expand or shrink the range by one wordCommits efdd06cbd36739a92723e30de8bd93cb02a4f01c, ce77c04942f66bc2a0c9681e17cad54da4c64bb3, and b3183172e364378923cdb86e0bf51b5874a8a0ba implement the desired actions. Closing this and opening a separate issue for drag-to-select-text.
In particular: