Skip to content

jurjanpaul/codemirror6-parinfer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Parinfer in CodeMirror 6 demo

Combines Parinfer with CodeMirror 6 using Scittle, building on Scittle's CodeMirror example.

Getting there, but this is still very much a work in progress, nowhere near a published library.

Try it at the demo page, which also uses Nextjournal's Clojure syntax support for CodeMirror 6.

TODO

  • smartMode Parinfer
  • Highlight any errors (step 4 in Adding Parinfer to an Editor)
    • Fix undo/redo
      • Understand and fix race condition in case backspace and/or Ctrl-Z is kept pressed in.
    • Leave other effects alone
  • Take special care of selections
  • Pin all dependencies (lesson learned after breaking change, but with obvious drawbacks)
  • Mark parenTrails (for completeness only; I can live without)
  • Refactor (constantly of course)
  • Examine interaction with other CodeMirror extensions
  • Make into a published JS library
    • Options to configure/toggle
  • Optimise?

Motivation

If I ever hope to upgrade the Away from Preferred Editor ClojureScript Playground from CodeMirror 5 to CodeMirror 6, I need Parinfer integration, which nobody seems to have made available for CodeMirror 6 yet. (This is noteworthy because Parinfer was originally developed on CodeMirror and version 6, a complete rewrite, has been out for a number of years now.)

But even if that upgrade never happens, I hope that this may be a small contribution/inspiration to keeping Parinfer a viable option for editing Clojure/Lisp across as many different editor(component)s as possible, because I heavily depend on its integration in other editors. 🙂

(Clojure developers are encouraged to do structural editing with Paredit. By all means, go for it! I know I’m in a tiny minority, but making edits with these elaborate key combinations does not work for me, so far. Also, a simple iPhone keyboard does not come with the Ctrl and Alt keys that Paredit requires.)

Honestly though: Parinfer has a simple API, so this should not be rocket science. CodeMirror 6 though seems/seemed rather complex compared to the CodeMirror 5 API...

Experience so far

  • Looked at Shaun Lebron's original parinfer-codemirror.js code and will study it more, as well as other Parinfer integrations, but decided that CodeMirror 6 is different enough that a fresh start makes sense.
  • Interesting that transactionFilter is the hook needed to 'add' synchronous Parinfer modifications to a user triggered state transaction. (I overlooked it at first, because filtering means something else in the contexts that I am used to.)
  • The documentation for transactionFilter clearly states that it is recommended to avoid accessing Transaction.state in a filter, but it seems unavoidable when creating a new transaction for the Parinfer changes and to apply diagnostics in case of error.
  • I had learned from this CodeMirror discussion thread that it would probably be a good idea to diff the Parinfer output with its input, if only to keep the edit history's memory usage down. I started using the diff-match-patch library for this, but later found CodeMirror's own diff function which I am now using (needs less work converting diffs and keeps the number of external dependencies down).
  • Marking Parinfer errors in such a way that they can be undone and redone proved trickier than I had expected. I got it to work with a StateField, StateEffect and invertedEffects, but perhaps I am still missing something simple and obvious.
  • All in all, a lot of expensive transformations need to happen for each key press... Even so, the result feels fast enough, even with a large code base on a phone.
  • I wonder if the same result may after all be achieved with less expensive steps, but I'll take (relatively) 'slow' over asynchronous postprocessing any day, having experienced how poorly that works out when an editor provides no alternative.

Releases

No releases published

Packages

No packages published