omniJS – Calling a simple macro from Script Editor etc

omniJS scripts can be launched in various ways on macOS, including from the existing Script Editor, Script Menus, and anything else which can launch an AppleScript / JavaScript for Automation (JXA) script.

Here is a an example of an omniJS script which reverses the order of all children of the first selected node, and which can be run from Script Editor, with the language tab at top left set to JavaScript. It contains an omniJS function reversedChildren() together with a JXA snippet which converts that function to an OO omniJS URL, and then opens that URL.

(Note that this draft script is written in (Sierra onwards) ES6 JavaScript. You should be able to convert it to (Yosemite onwards) ES5 JavaScript by pasting it into the Babel JS REPL.

    (() => {
        'use strict';
    
        // FUNCTION TO EVALUATE IN OMNIJS CONTEXT --------------------------------
    
        // reversedChildren :: OO () -> OO [String]
        const reversedChildren = () => {
            // GENERIC FUNCTION --------------------------------------------------
    
            // log :: a -> IO ()
            const log = (...args) =>
                console.log(
                    args
                    .map(JSON.stringify)
                    .join(' -> ')
                );
    
            // REVERSAL ----------------------------------------------------------
            const
                editor = document.editors[0],
                selnNodes = editor.selectedNodes,
                selnItem = selnNodes[0].object,
                childItems = selnItem.children,
                lng = childItems.length,
                outline = document.outline;
                
            const reversedTopics = (
                    // Any text-edit selection suspended to allow for GUI update
                    editor.select([]),
            
                    // The last shall be first (if they are different)
                    lng > 1 && outline.moveItems(
                        [childItems[lng - 1]],
                        childItems[0].before
                    ),
    
                    // and others come after what once followed them.
                    lng > 2 && (() => {
                        const
                            xs = selnItem.children, // (resampled)
                            [h, t] = [xs[0], xs.slice(1)];
                        return t.reduceRight( // reduceRight starts at end of list
                            (a, x) => (
                                outline.moveItems([x], a.after),
                                x // Accumulator (a) takes value of x for next iteration
                            ), h, t
                        );
                    })(),
                    
                    // Selection restored
                    editor.select(selnNodes),
                    
                    // Value for logging and returning to the Automation Console
                    selnItem.children.map(x => x.topic)
                );
            return (
                log(reversedTopics),
                reversedTopics
            );
        };
    
        // JXA CONTEXT  ----------------------------------------------------------
        const
            a = Application.currentApplication(),
            sa = (a.includeStandardAdditions = true, a);
    
        sa.openLocation(
            'omnioutliner:///omnijs-run?script=' +
            encodeURIComponent(
                '(' + reversedChildren.toString() + ')()'
            )
        );
    })();

Thanks for posting this!

SG

1 Like

And, of course, there’s a good number of examples on https://www.omni-automation.com/omnioutliner/index.html