Almost finished integrating UCL with Dynamo-Browse. As stated earlier, the goal is to use UCL for both the command and scripting language. Today, the goal was closer, with a development version of Dynamo-Browse no longer using old extension scripting language, and now scanning and evaluating UCL-based extensions on launch time.

This required some changes in how UCL evaluated script files. There’s a new ucl.WithSubEnv() option that can be passed into inst.Eval() to instruct the evaluator to fork the environment prior to evaluating the script:

f, _ := os.ReadFile("my-file.ucl")

inst := ucl.New()
inst.Eval(ctx, bytes.NewReader(r), ucl.WithSubEnv())

Under the hood, this forks the top-level environment frame and marks it as the frame to store all procs and global variables for the evaluated file. This effectively makes it a separate namespace, separating it from all other scripts and preventing cross-contamination when scripts share the same symbol.

I’m hoping that this will eventually be the basis for UCL modules, but for now, this is use within Dynamo-Browse to isolate each UCL extension. The downside of this is that it’s no longer possible to add new commands simply using the proc keyword. I think this may end up being a good thing though, as extensions will probably not be interested in exposing internal functions defined just for their own use.

To compensate for this, there is now a new command — ui:command — which allows the script author to expose a function as a command. In fact, what it does is save the command in the root environment frame, effectively making it work the old way proc did, and acting like a poor-mans extension export.

Now with all the extension loading in place, it’s time for the inaugural UCL extension. Here it is:

# Gets the partition key of the currently selected row, and adds it
# to the pasteboard. Bound to the 'U' key.

ui:command copy-pk {
    # Get the partition key value from the currently selected item
    $pkKey = @table.Keys.PK
    $pkValue = @item.($pkKey)

    # Place it in the pasteboard
    pb:put $pkValue

    echo "$pkKey copied to clipboard"
}

ui:bind "U" { copy-pk }

All the features are not quite implemented yet, but I think it’s good enough to start using it as part of my normal workflow. That’s usually the best way to find the rough edges.