Adobe Automation – work in progress

A few months ago, I started work on new infrastructure to automate Adobe Creative apps (and other apps).

A quick update: work is still steadily progressing.

At the the moment, I have built a framework in pure C++ 11, called ‘Tightener’.

There are no external dependencies – all you need to compile it is a C++ 11 compiler and a standard C++ library.

Tightener has an embedded language, called TQL (Tightener Query Language), pronounced as ‘tickle’.

TQL is similar to JavaScript, but simplified. It has the basics: expressions, functions, scopes, cooperative multitasking….

Tightener provides support for ‘Tightener Nodes’ which are instances of Tightener that are embedded into some environment (a command-line console, a language interpreter, an application, a network stack…).

Tightener nodes running on the same computer can communicate with one another using pipes/shared memory.

I envision many nodes per computer. There is one ‘main’ node and number of satellite nodes embedded into various environments, providing services (e.g. Python, InDesign, Illustrator, node.js…)

Using the messaging mechanism, one Tightener node can ask another Tightener node to run a TQL script.

TQL provides support for some XPath-like queries into entity-attribute Object Models – think of it as ‘XPath for JSON’.

Most embedded Tightener nodes will be able to handle queries into some object model (e.g. a Tightener node embedded in InDesign will handle queries into the InDesign DOM), and hence allow other Tightener nodes to make queries on their behalf.

I am currently integrating Tightener into an InDesign plug-in, so the InDesign DOM will become an integral part of the InDesign Tightener node.

Once that is done, any other Tightener node on the same computer can send TQL scripts to the InDesign node to query or execute.

Next I’ll integrate Tightener into Python, so I can start showing proof-of-concept demos: open a Jupyter Notebook, and interactively construct an InDesign automation script.

TQL is not meant for full-fledged programming (though it is powerful enough to do that).

TQL’s main goal is to reduce the number of round trips between the controlling Tightener node and controlled Tightener node: there is latency between the controller and the controlled. If we can execute some coded logic on the controlled node, that helps reduce the number of round trips we need.

(In short: this is the same thing as why ExtendScript is much faster than AppleScript. AppleScript has some latency each time we ‘cross the fence’ between the controlling AppleScript and the controlled program. ExtendScript lives ‘inside the fence’ and grafts directly only the controlled program).

A remote Tightener node is more ‘like AppleScript’.

An embedded Tightener node is more ‘like ExtendScript’.

So we want any remote Tightener nodes to delegate some of their work to an embedded Tightener node whenever possible. Hence TQL.

TQL is currently fleshed out enough to run all kinds of scripts, but there is still a lot of unimplemented things on my ‘to do’ list – e.g. the ‘switch’ statement.

Tightener nodes are, by design, not network-aware.

Networking functionality has to be achieved by building separate ‘gateway nodes’ which are essentially one or the other network comms stack with a copy of Tightener embedded.

This approach is to avoid introducing unwanted dependencies into Tightener: I don’t want to have to upgrade Tightener each time a new version of OpenSSL is released.

Next steps:
– Finalize Tightener integration into InDesign
– Embed Tightener into Python
– Create a Tightener gateway node by combining Tightener with OpenSSL

I’ve started a public Github repo where I’ll put the Tightener documentation as I write things up.