Working on the editor - Iterating quickly

Hello,

I’m trying to fine-tune the UI of the sound component and i’m experimenting with the SoundNode and its properties. I’m using value, set, dynamic error clauses etc. to improve the UX. I’m using Cursive in intelliJ as a dev tool.

My workflow is kind of dumb. I make changes in intelliJ, and start the application with ‘lein run’ from the IDE. I see the new behavior (or get an exception) and keep iterating in the IDE making changes in the source code and restarting the app.

My iteration takes long and is far from optimal.

Some changes can be implemented by encapsulating them in functions and redefining them using the repl. No need to restart then. But when it comes to the node clauses, and their syntax of parameters this is not possible.

Do you have anything to suggest ? Any quicker workflow, any shortcuts, any best practices to optimize this ?

I also tried the ‘trampoline’ option. Is this the debugger for Cursive ? Do breakpoints and inspecting of variables work there ?

Also, is there any more documentation regarding editor development besides doc/defnode.md ? That could save some from trying to understand by trial and error.

Thanks

1 Like

I use Cursive as well. You should be able to “redefine” an edited defnode using the Send Topmost Form to REPL command (right-click somewhere inside the defnode and choose Send ‘(g/defnode…)’ to REPL. You’ll need to also do this for all the (g/defnk ...) you’ve modified before you re-evaluate the defnode, or their changes won’t be incorporated into the new node definition.

One thing you might be running into is that node outputs might be cached. In that case the output will just return the cached value and your updated g/fnk won’t be executed. To force the output to evaluate, you’ll need to clear the system cache with a call to:

(g/clear-system-cache!)

The trampoline is a different way of starting a Clojure process. You need to enable trampoline in order to attach the Cursive debugger. I don’t really use the debugger myself, but you might like it.

I prefer to interact with the running editor through the REPL by evaluating node outputs with (g/node-value 12345 :my-property), calling functions, etc. Sometimes I like to edit a node or function to store an intermediate value in an atom I temporarily define in the same file. I perform some action that forces the node output or function to evaluate and then I can deref the atom and inspect it in the repl using the built-in collection query functions like filter, group-by, etc.

There’s an utility module named dev.clj which you can require to pull in some helpful debugging functions that let you get the node-id of the selected object, active resource, etc:

(require 'dev)

;; Return a list of the queryable outputs from the selected node.
(let [selected-node-id (first (dev/selection))]
  (dev/node-labels selected-node-id))
=>
#{[:id String :property]
  [:image-resource Resource :output]
  [:size Vec2 :property]}

;; If you want to evaluate a cached output, you should make sure the value is not already cached, or your updated `g/fnk` won't be run.
(g/clear-system-cache!)

;; Query an output on the selected node.
(let [selected-node-id (first (dev/selection))]
  (g/node-value selected-node-id :image-resource))
=> {:FileResource "/images/city.png"}

Have a look at dev.clj and the various methods of querying the graph in dynamo/graph.clj. Here are the ones I tend to use a lot:

(g/node-value)
(g/node-type*)
(g/sources-of)
(g/targets-of)
(g/clear-system-cache!)
(g/set-property!)
(g/now)

Yes, documentation is a bit lacking still. I recommend reading the systems overview to get some background on the concepts, but most of the documentation is in the code itself, I’m afraid.

3 Likes

Wow, this really boosts things up! :grinning:

Yes, documentation is a bit lacking still. I recommend reading the systems overview to get some background on the concepts, but most of the documentation is in the code itself, I’m afraid.

Right, i went through it once or twice. There is a lot of theory there to take in. Some practical tips like the ones above were missing.

In any case, your post really broke things down (i.e. helped understand the mechanisms involved ) and suggested a very optimized workflow.

Thanks

3 Likes