We built a structural editor for an OCaml-like language (Darklang). Our first version was very AST-based, with all movement using the AST. The feedback we got was that AST-based editing is hard to grok and that you need line-based editing too. So we re-implemented and now we have both (although we broke and are re-adding a bunch of the editor refactorings).
That makes sense - I'd assume restricting movement to just ast-based edits would be too constrained and would ultimately just limit the types of transformations users could perform (especially important when the syntax is wrong, or when making the AST temporarily invalid).
Have you had a look at the various Emacs plugins for editing lisp? Given the simplicity of the syntax, it would be fairly simple to make a lisp editor only performs AST-based transformations, however most lisp plugins support a mixture of both AST and line-based transformations. I find this approach to be very natural, allowing me to rely on the AST when I need it, and then being able to ignore it when I don't need it. My main motivation for gopcaml-mode was just to achieve a similar editing experience for OCaml code.
Yeah, I was mostly influenced by paredit, though I had looked at parinfer and a few others.
Question about your approach: what happens if the code is syntactically invalid? Dark prevents code from being syntactically invalid cause it's AST only, but for example ocamlformat just refuses to run if it can't parse the whole file.
At the moment, it just gracefully disables itself so the movement commands revert to calling the corresponding Tuareg and Merlin operations. This is mainly because I currently rely on the vanilla OCaml parser to build the AST which doesn't handle recovery from syntax errors.
In the future I plan to move over to the Merlin parser, which has partial support for syntactically invalid buffers (I believe it wraps invalid regions with another syntactic construct), so it should still be possible to move around in other parts of the buffer.
As an aside, as I mentioned on the OCaml forum, I haven’t found this to be a major issue as I find that most of the time when I’m moving around (i.e not inserting text), the code is usually syntactically correct - I’ve also bound M-RET to insert a type hole (??) to easily allow movement even when I haven’t completed a function definition, and overall this leads to quite a natural editing experience.
We built a structural editor for an OCaml-like language (Darklang). Our first version was very AST-based, with all movement using the AST. The feedback we got was that AST-based editing is hard to grok and that you need line-based editing too. So we re-implemented and now we have both (although we broke and are re-adding a bunch of the editor refactorings).