Where to start

Hello, I’ve been using CodeMirror for at least six years and I’ve been following the development of cm6 with much enthusiasm. It really is a beauty. The thing is, because the design is rather innovative and nonstandard, my “traditional” coding skills kind of break down. In particular, once you have gone through the basic examples in the guide, it is really hard to figure out “what my options are” when coming to carry out a task. In OOP, we look at the classes we have available and their methods. In cm6’s gorgeous functional design, there are transactions and I need to find out what facets control what and which transactions carry the corresponding effect. From my experience, I can conclude that this is going to be a huge blocker for newcomers to adopt CodeMirror. Perhaps it would be a good idea to have a comprehensive list of:

  • All the facets that are available as part of the @codemirror/ packages
  • All the ways to create transactions. I know of a few (even EditorState.update was a bit hard to come by, and could only be found by scanning the API listing for the main classes, at which point I already knew that I needed to pass it to EditorView.dispatch so I was in the clear, but that was hard to find too, at the beginning) – but I keep seeing different ways to do so in posts.

I think in a transactional model, these are more important than the “javadoc”-style API lists, which users may come to for the synopsis of a particular methods, but do not assist discovery of functionality.

2 Likes

I agree that it is a steep learning curve but worth it. I was confused about this new concept of facets too until I discovered Marijn’s blog article titled Facets as Composable Extension Points. Which I think should be included in the regular documentation or have a link pointing to this blog article as it clears up so much.

1 Like

Oh it is definitely worth it! I am only proposing that perhaps a community effort can be organized to give a (more) gentle introduction to these concepts. The article is nice but is more on the design level, something that’s more technical may be more appealing to potential users.

1 Like

I am pleased to see that the examples section in the documentation is growing. It might be able to create an index section that summarizes all the transactions and facets used in the examples. I might try doing that when I have some time :slightly_smiling_face:

I have to agree - despite using CodeMirror for almost 9 years, grappling with CM6 still stumps me often. I feel like it needs multiple additional levels of documentation and a much wider range of examples to make sense. And I get that it didn’t make sense to build all of that out during the pre-release period when things were shifting rapidly.

But today, if someone lands on codemirror.net, should they start with the Architecture Overview? Or a random example? There’s just not that much in terms of basic onboarding. Even to people I’d say are very seasoned users and developers, it’s intimidating and there’s not enough of an onramp onto the tool.

You want beautiful, detailed and deep examples of how to accomplish things in cm6? Look at the source code of its packages! During my career, I’ve read a lot of code – reading the cm6 source code is exceptionally enlightening and enjoyable.

In my case, I traced through the code how several highlighting methods work – what APIs I need and how to use them. After seeing how the APIs are used in the code, the documentation makes a lot more sense – and, eventually, I succeeded in implementing my own features.

I suggest you take an extension that does something similar to what you are interested in (or something simpler) – and search the source code for the different APIs that are used there.

Here is a quote from a CodeMirror MOSS project report:

Working on concrete extensions was a good way to find out how well our abstractions work in practice. Though we did end up adjusting some things, on the whole the system was a pleasure to work with.

This echoes my experience: Codemirror abstractions are new — and beautiful. One great way to understand and appreciate them is to see them in action.

A very inspiring suggestion @Yaakov! So perhaps, as onboarding, we should refer users to some of these very packages. At least it will give the message, that when trying to interact with the editor, the path of least resistance is likely to be creating an extension (even if it’s just a StateField or ViewPlugin) – normally, newcomers associate extension authoring with advanced skills, but in cm6, this is often not the case. In fact, writing extensions is the most direct way to experiment with the editor.

@corwin-of-amber – I’m not sure what should be the canonical answer here. I believe that newcomers can be different from each other. The fact that they have no experience with CM6 yet doesn’t imply they have the same background.

For some newcomers, the path of least resistance may not be the path of fastest success. You may have come across Rich Hickey’s lecture Simple made easy. If not – you may like and appreciate it.

One deep observation of the lecture is that “simple” and “easy” are, in fact, two distinct concepts:

"Easy" is subjective and depends on where you come from and where you are right now. For example, when you have a lot of experience with OOP programming then any OOP-inspired design will be familiar and hence easy for you. A more functional design may be novel and maybe even confusing. But this is relative and can be changed – e.g. by learning.

By contrast, simple vs. complex is objective: Combining complex units implies a mental cost that cannot be removed (even when the complexity is hidden and appears only when you actually do something interesting with the complex units).

In our case, the design of CM6 is simple, elegant and original, novel. The time spend in familiarizing yourself with these ideas often pays off well in the future.

My suggestion is: Documenting, explaining and publicizing the CM6 design is worthwhile – and very appropriate for many newcomers (and also for more experienced users). Diving into the actual source code is an additional great option. Newcomers should be made aware of this option and of its benefits. They should be given motivation and inspiration to take the jump and learn something really special…

@corwin-of-amber – Here is a more practical take on your question: You ask for three distinct things:

  • Guidance where to start
  • Help to understand the system
  • Help to find what’s available

The Reference Manual and the System Guide both start off with a minimal editor configuration to start with. Maybe this is enough for the first request — possibly it would be great have more examples of applying configurations, from simple to more complex cases.

The second request – help to understand the system – needs documentation and time spent with the code. We discussed this above.

But maybe the third request — help to find what’s available — can be improved: With more summary views automatically extracted from the source, with hand-written, focused collections of the most helpful APIs and features for a specific purpose – and with some advice how to search the source code effectively.

Just want to note that the website is still a work in progress—it was set up to ‘sell’ the rewrite, and I’m planning to make it more of a generic overview of what the system does. But that’s going to take some more work, and I didn’t want to delay the release for it. In any case, there really is a lot of documentation already.

Glad that I find this post, otherwise I will never figure out what is a “facet” or “state field” on my own.

The document isn’t really that helpful. For example, the description of StateField is “Fields can store additional information in an editor state, and keep it in sync with the rest of the state.” But it just creates more questions:

  1. What kinds of additional information, and what are they for?
  2. How does it keep in sync with the rest of the state?
  3. Why does it need to be in sync?
  4. Why the rest of the state?
  5. What do you mean by “the rest of the state”?

The answer to these questions actually lies in the lengthy “System Guide”, which is actually a must read for everyone who uses this CM6 but that is not so obvious when you first land on https://codemirror.net/.

And after reading all these helpful links in this post, I still don’t know how to move the cursor to a specific offset. The example in “Selection” section in “System Guide” shows how to create an editor with pre-defined selections, but not updating them.

I have moderate experience in making Sublime, Visual Studio Code, Eclipse, and Jetbrains IDE plugins. Every one of them has an API like “moveCursorToOffset()” which is a one-liner and direct and self-explanatory. The new design of CM6 feels slightly over-designed to me. This reminds me of Eclipse. The devs of Eclipse really put a lot of efforts in designing the architecture to make the system modular, extensible and loosely-coupled. But the learning curve makes it a nightmare to make extensions. It is worse for CM because CM5 plugin is not compatible with CM6. This will further divide the struggling community and maybe eventually kills it.

There is definitely significant potential for frustration in the new design. From the helpful discussion above I think two immediate action items can be drawn:

  • In the API docs, add links to the source-level implementation. This is actually pretty standard in medium-large open-source projects and is invaluable to users. Having to keep browser tabs for docs and source impose additional cognitive load, as searching through the code base to find a method implementation temporally distances the activities of reading documentation and code, which is a strain on short-term memory.
  • Have a method-by-method migration guide from CodeMirror 5. Beyond helping users in actual migration, this can become useful by focusing the set of examples given in the documentation and grounding them in previously known concepts. Whether you have used CodeMirror 5 or some other editor API in the past, you probably know there is something like setCursor() — so making this easily discoverable could be great.

While the first item can only be done by @marijn, the second can be done by anyone. Perhaps a wiki can be set up? I think some of the users here know quite a lot about cm6 and we can all gain from their experience. (I also know some already and can contribute.)

Like this, which is linked prominently from the docs overview page? It seems that for some of these complaints, just actually spending some time with the docs would be have yielded more progress than coming here to post.

I truly apologize if these sounded like complaints. Instead they are constructive advices on how to attract more potential users and evolve the CodeMirror community in a better way.

And yes, of course I visited the migration guide. There was no claiming in the above that there is not a migration guide; I was suggesting to improve it by creating a table of (all?) existing CodeMirror 5 methods and their CodeMirror 6 counterpart. Indeed most of the information is already there. Perhaps a very minor reorganization or indexing will make a huge difference.

In general, the quantity of the documentation is adequate. No one can argue that CodeMirror 6 is under-documented. But more than one person found it hard to navigate it, so there is always room for improvement and development.

This resonates with my experience learning CM6 too. I would describe it something like this:

In addition to CM6, I’ve used a number of other libraries/frameworks for text editing, for UI, and etc. They often share similar ideas for how to structure code and expose levers for making your own editing experience. As a result, I’ve built up a number of code architectures/approaches to doing certain kinds of tasks with text editors that I can usually apply in some fashion, no matter the text editor library.

CM6 has created a number of new concepts around how it thinks about and structures the factors that make up text editing. Things like Facets, like a more functional/dispatch runloop, reconciling changes to multi-cursor selection support, etc. Even with my own decent background in web and functional programming, and even having read much of CM6’s source and Marijn’s writing, I sometimes find it challenging to represent the tasks I want to accomplish in the vocabulary and concepts that make up CM6.

I don’t think this means the documentation is at fault, nor does it mean CM6’s concepts are too challenging. In fact, I have learned a bunch from reading both. Instead, I think because these concepts represent a pretty big change from how text editor libraries used to work, I haven’t yet internalized how to think about the tasks I want to achieve using CM6’s concepts, and I don’t have a good mapping of how other libraries would translate their way of doing things to CM6.

My reading of this thread is that folks are trying to call attention to this, and suggest that the CM6 community begin thinking about patterns for ways of doing specific text editor tasks using CM6 as compared to previous ways of thinking about that task, so we can provide a path to onboarding potential users (including ourselves) to CM6 that requires less commitment than reading and understanding its architecture docs.

In some ways, it reminds me of React’s first years, as people readjusted from jQuery-style imperative chaining to a more functional way of thinking about UI.

3 Likes