Customising Inline Tree Nodes

Nov 8, 2024

In the previous EAP release, I added support for showing REPL evaluation results inline in the editor, in an interface called the Seeker. If you haven't seen that blog post yet, go read that first, since this won't make much sense without it.

When showing a complex form in the Seeker, the form is displayed as a tree of nodes. The root node represents the data structure being displayed, and its child nodes represent the child elements in the data structure. In the latest EAP release, you can now customise how these nodes are presented, and make them interactive. This allows you to create lightweight UIs for your data, right in your editor.

This article complements the tutorials which you can work through in your editor if you're a Cursive user. If you can, the tutorials are recommended over reading this since they're interactive, and show a couple of real-world use cases.

When you evaluate a form in the Clojure REPL, the result of that evaluation is returned to the REPL client as a Clojure form. You can create custom nodes which change how that form is displayed in the inline viewer using tagged literals. Here's an example:

(tagged-literal 'cursive/node {:presentation [{:text  "Hello world"
                                               :color :red}]})

If you evaluate this form in the REPL, you'll get a tagged literal back, which will look like this if printed out:

#cursive/node {:presentation [{:text  "Hello world"
                               :color :red}]}

Notice that the tagged literal consists of the tag (cursive/node) and a data structure, in this case a map. This literal will be intercepted by the Cursive REPL client, and it will create a simple node in the inline tree which looks like this:

This is just a single node with no children, so it's not expandable. Here's an example of a more complex node:

Notice that here we also passed a :children element in the map, which contains a vector of child nodes, so the Seeker appears and our node is now expandable and explorable. In this example, the child nodes are all custom nodes, but they can also just be standard data too, so we can mix and match custom nodes with standard data as we need to:

As you can see, the styling of the nodes can be customised, see the tutorials and the documentation for details.

You can also add actions to nodes, such as navigation:

You can create nodes which will open URLs in a web browser:

Finally, you can create nodes which will eval code in the REPL:

There's really far too much in this feature to explain it all in a blog post. Please check out the tutorials and the documentation for full details, and examples using real-world use cases.

There you'll see examples of how to get nicely formatted Malli errors inline:

And an example of how to create an inline menu for Scope Capture:

I'm really interested to see how everyone uses this feature. If there are things you need, please let me know. And if you create some great support for a library you use, please consider contributing to the inline-nodes repository, so other users can take advantage of what you've built too.


Cursive 1.14.0-eap2 Cursive 1.14.0-eap3