Automating the Editor

Scripts that work on Divooka Compute's editor itself: the open documents, their graphs, nodes and wires, what is selected, where the canvas looks, running a document, and the status line. Divooka Compute ships three samples, each written three times - in C#, in Lua and in Python - and the three do the same thing. They are examples: press Ctrl+Shift+E for New from examples, choose Editor Automation, pick one and press Open a copy.

Sample What it does
GridLayout Lays the selected nodes out in a grid: in the order they read, top to bottom then left to right, as near square as their count allows, each cell as big as the biggest node.
PrintAfterSelection After each selected statement of a Routine, puts a Print Line that prints what the statement gave - and, for a node with nothing after it, prints the editor's reason.
RunFolder Runs every document in the folder Documents beside the script, one after another, without opening them, and says how each went.

Running a script

Open the script in Divooka Compute - Ctrl+O, or the Workspace panel. A script's toolbar has Run and Automate Editor where a document's has Run and the Interpreted/Compiled switch:

  • Automate Editor runs the script inside the editor, with Editor to work on. These samples are for it. Everything a run changes is one step of each document's history, so one Ctrl+Z takes the whole run back, and a run that fails or is stopped leaves every document as it was.
  • Run (F5) runs the script on its own, as a terminal would - pure for C#, luna for Lua, spy for Python - in the script's folder. Editor is not there; what it prints and what it reads are the dock's.

While a script runs, the toolbar's Run reads Stop (Shift+F5), and a line typed into the dock's input row is what the script reads.

Breakpoints. A press on the gutter left of a line's number, or F9 with the caret on the line, sets a breakpoint, and either kind of run stops there: the line is marked, the dock's Locals list the variables and the Call stack the functions the script is in. F5 goes on, F10 steps over a line, F11 into a function, Shift+F11 out of it. F11 with nothing running starts Automate Editor stopped at the script's first line.

Python packages. With a Python script in front, the toolbar's package button opens its environment: a folder of installed packages the script runs with, chosen for the script or for its workspace folder. New environment makes one, Install installs a package into it by name, by requirement (numpy==2.1) or from a wheel file, and the × beside a package uninstalls it. Both Run and Automate Editor import from the environment the script is in.

C# references. A C# file - a script, or one a document references - can begin with Import(...) and Include(...) lines: Import(Newtonsoft.Json@13.0.3), Import("Lib/Tools.dll"), Import("Library.dvk"), Include("Helpers.cs"). A document referencing such a file lists what it imports and includes under it in its References, in a colour of their own.

A document that works on the editor

A document can do what a script does. One built from the Editor Automation toolbox's nodes - documents, graphs, nodes, the selection, the view and the editor - has its own Automate Editor on its toolbar. Pressing it runs the document against the documents you have open, starting with the one you were on before: everything it changes is one undo step, nothing it did stays if it fails or you stop it, and its breakpoints work as on any document. Run, a compiled run and Publish refuse such a document, naming the node that needs Automate Editor. New from examples has two to try: Editor Automation › Greet After Begin, which works on Editor Automation › Steps.

Trying the samples

  • GridLayout. Open a document and select the nodes to arrange - Ctrl+A for all of them. Open GridLayout.py (or the .cs, or the .lua) and press Automate Editor. The nodes move into a grid, the console says how many columns, and one Ctrl+Z puts them back.
  • PrintAfterSelection. Open a document whose entry is a Routine, select its statements with Ctrl+A, open PrintAfterSelection.py and press Automate Editor. A Print Line goes in after each statement that has a next one; press F5 on the document to see what each prints.
  • RunFolder. Make a folder called Documents beside the script and put documents in it, then open RunFolder.py and press Automate Editor. Each document runs in turn, the status line saying which, and the console says how each went and how many ran to the end. New from examples has a ready-made folder to try it on: Editor Automation › Run Folder.

What a script works with

The same members in every language. C# calls graph.AddNode("Add", 0, 0), Lua graph:AddNode("Add", 0, 0) - a method with a colon, a property with a dot - and Python graph.AddNode("Add", 0, 0). A list - the selection, a graph's nodes - is an array in C#, a table numbered from 1 in Lua, and a sequence in Python; what is null in C# is nil in Lua and None in Python. A relative path is read from the script's folder.

Editor - the one name every script is given.

ScriptPath, ScriptFolder the running script's file, and its folder
Documents the open documents, in the order of their tabs
ActiveDocument the document in front - or, with the script's own text in front, the one in front before it; nothing when none is open
Open(path) open a document, or find it open, and bring it forward
FindDocuments(folder) the .dvk and .dvj documents in a folder and the folders in it, in order
Run(path), Run(path, mode) run a document from its file without opening it - "Interpreted" (the default) or "Compiled" - wait, and say how it went
Status(text) say something on the status line

A document

Name, Path, HasChanges its file's name (or its title, never saved), its file, whether it has unsaved changes
Graphs, ActiveGraph, EntryGraph, FindGraph(name) its graphs; the one on its canvas; the one a run starts from
Selection, Select(node), Select(nodes), ClearSelection() what is selected on its canvas, in the order it was selected, and selecting - showing the nodes' graph first
View where its canvas looks
Assets, AddAsset(file), AddAsset(file, assetPath), RemoveAsset(assetPath), SaveAsset(assetPath, file) its asset library: what it holds, by path (/sun.png); a file embedded; an asset taken out; an asset written to a file
Activate(), Save(), Run() bring its tab forward; save it; run it as its Run button would, in its mode, with its changes, results drawn on its canvas

A graph

Document, Id, Name, Kind where it is, and what kind: "Routine", "Flows", "Function", ...
Nodes, Wires, FindNode(titleOrName), FindNode(id), FindNodes(titleOrName) what it holds; a node by its title as the canvas writes it in English, the name it was given, or its identity
AddNode(name, x, y), AddNode(name, x, y, functional) place a node by the name the node library shows - in English, in the editor's language, or its code's name - as Ctrl+Space places it; in a Routine, functional places a value node off the execution path
Connect(from, to) wire an output to an input, in either order; an input's earlier wire is replaced
Remove(node), Remove(nodes), Tidy(), Show() remove nodes and their wires, as Delete does; lay it out as Tidy does; show it on the canvas

A node

Graph, Id, Title, Name, X, Y, Width, Height where it is and how big it is drawn (0 while it is not drawn)
Inputs, Outputs, Input(title), Input(index), Output(title), Output(index) its pins, top to bottom: on a statement, what runs before and after it, then its values
IsStatement, Value whether something runs before and after it; a value node's value - a Number's, a Text's - as its box shows it, set as typing into it
MoveTo(x, y), MoveBy(dx, dy), Remove()
InsertAfter(name) place a statement right of this one and thread it into the execution path behind it - whatever ran after this one runs after the new one

A pin - Node, IsInput, Index, Title, Type ("Double"), IsFlow (what runs next, rather than a value), Wires, Connected (the pins at the other ends), Value (what is typed into an input; nothing empties it), Connect(other), Disconnect().

A wire - Graph, From, To, Remove().

The view - Zoom (1 is actual size; settable), X, Y (the middle of the view), CenterOn(x, y), Fit(), Reveal(node).

A run's result - Name, Succeeded, Failure, Seconds, Mode, Output (what it printed, a line at a time), and as text one line: Main.dvk: finished in 0.42 s, or Main.dvk: failed - why.

What the editor refuses is an error the script can catch - an exception in C# and in Python, a Lua error that pcall catches - its message saying why: No node called 'Prnt Line' can go in Main (Routine); the nearest are 'Print Line', .... Stop is not one: nothing in a script can catch it.

The languages

  • C# is Divooka Pure's: statements at the top level, Import(...) of a workload, a package, a document or a NuGet package, and Include(...) of another file.
  • Lua is Lua 5.2, the standard library included; require finds a module beside the script first, and os.exit ends the script, not the editor.
  • Python is SteelPython's Python 3.12, its standard library and Divooka's packages importable; a module beside the script imports first, and sys.exit() ends the script, not the editor.

A script Automate Editor runs is in the editor's own process: what it does to the process - leaving a thread running, ending the process - it does to the editor. A script meant to run on its own is what Run is for.