How out of date is the Automation Tutorial?

Hi,

I am writing this in November 2022. I decided to try and learn the “new” Javascript automation by following this tutorial Omni Automation OmniOutliner macOS Tutorial: “Clean & Wax” . While the instructions all work I am confused by the additional information that the console displays when it prints a response to a command. Is there an explanation as to what this extra information means ?

For example, setting a variable such as text into the “topic” of a row will append “= $n” - I’m guessing that $n is a Outline document level variable but what does the following response to the command mean ?

Command : row2 = rootItem.addChild()

Response :
[object Item] {after: [object ItemPosition], ancestors: [], before: [object ItemPosition], beginning: [object ItemPosition], children: [], childrenAreSections: false, descendants: [], descendents: [], end: [object ItemPosition], followingSiblings: [], hasChildren: false, identifier: “hwAvgWtuBSo”, index: 1, leaves: [], level: 1, note: “”, outline: [object Outline], parent: [object Item], precedingSiblings: [[object Item]], sections: [], state: [object State: Unchecked], style: [object Style], topic: “”} = $3

Is this list just a helpful aide memoire of properties of row2 / $3 ?

S

I don’t understand your question.

P.D.: Could you post your example enclosing three triple backticks ?

Hi,

Does this screenshot help ?

The tutorial text just displays [object Item]

S

If you look into OO API, under Instance Properties, you can see that Item class has exactly a number of properties shown. The object you’ve just created has exactly those specific properties and the values for each of the properties are shown on the console.

The console has always worked that way, as far as I recall. Showing the object properties.

Not sure whether I have addressed your question.

Hi,
Thank you for your reply. I wrote my question based on my first attempt to get to grips with using Java script with Omni-Outliner. I found the tutorial on https://www.omni-automation.com/ and found that I was seeing different information to that displayed in the tutorial. A second example is switching the Omni console between light and dark modes, the tutorial describes a menu item that does not appear in the console that comes with Omni Outliner.

So yes in a way you have answered my question : the tutorial is slightly misleading.

I have come to Javascript automation having used Applescript for years. It is unfortunate that having completed the tutorial I am not in a position to start using javascript. The syntax which seems brief and precise is not the problem but a wider understanding of how to use the code I produce. With Applescript I can run the script from the desktop, a script editor and assign it to a button in the Omni-Outliner menu bar (top of the window) whereas the tutorial just leaves me hanging with a feeling of “so what ?”.

Reading posts on this forum has informed me that there are two types of script, one that uses a fast interface with Omni Apps and one that uses the slower Apple Events . That there are plug-ins and URLs, these are scripts may be encoded as URLs and lastly that in order to emulate the Applescript on a button or applet an Applescript wrapper has to be written to call/present the URL script. Phew!

I have no idea if any of the previous paragraph is correct but that is really the issue I have with automation with javascript in that the information of how to create javascripts is spread over many web pages and forums. What I really want is a tutorial or example that is slightly more complex than the ubiquitous “hello world”. How about a commented example script that runs from an Apple script that prompts for my name and favourite colour and writes this information into a new row (item?!) in the uppermost OO document using more than on column?

I had thought that I would try and rewrite some of my Applescripts using Java Script but it seems that its challenge even to learn what is required. AppleScript syntax is not obvious but there is a wide user base and plenty of information about how to use it with various applications. I do wonder if David Allen would use Javascript today if he were to recreate his GTD scripts for Omni Outliner.

Thanks for reading…
best wishes

Simon

I didn’t learn using that tutorial. Instead, I learnt the functional paradigm using Rob Trew’s prelude and, at the same time, I started experimenting with JavaScript For Automation. After a while, after Omni API came to the surface, I continue with that.

We could split this problem into sub-problems:

A prompt which asks for your favorite colour:

Code for pasting in OO Automation Console:

(() => {
    const main = () => {
        return userDialog(
            [new Form.Field.String(
                "textInput",
                "What's your favourite colour?",
                "")]
            )("User Input Test")(
            dialog => console.log(
                dialog.values.textInput
            )
        )
    };
    
    // © Rob Trew
    // userDialog :: [Form.Field] ->
    // String -> (values -> ()) -> Promise
    const userDialog = fields =>
        // General constructor for omniJS dialogs,
        // where f is a continuation function 
        // in which a dialog result
        // is bound to the function argument.
        // Accesing values with the following
        // incantation:
        // dialog => dialog.values
        prompt => f => fields.reduce(
            (form, field) => (
                form.addField(field),
                form
            ),

            // Seed value - a new blank form.
            new Form()
        )
        .show(prompt, 'OK')
        .then(f);

    return main();
})();

userDialog function was created by Rob Trew.

I would start with simpler examples, in your case. Simples tasks which doesn’t require user interaction.

Thanks for your post and the code which I shall play with today. Great to hear that Rod Trew is still using and writing about Omni applications, some of his applescripts are just amazing and its a shame that they are now only to be found on the archive of the old forum. Is the prelude something I can download and read ?

best wishes

Simon

Here:

Thanks for the link to Rob Trew’s paper. I had Googled for it but with no luck although I did discover some interesting posts by Mr. Trew on the Tinderbox Forum where I learned that Apple now describe Javascript as a peer of Applescript and that Applescript has probably been placed on care and maintenance (my description). So like it or not it seems that I am going to have to learn Javascript. {?}; Oh how I dislike all the punctuation of C like languages.

I’ll answer my own question : yes the tutorial is out of date, however, it is in a state of continuous review where the single author attempts to keep up with developments made by the Omni Group across all its applications. I am thankful that the site exists as it is an excellent resource as long as users, i.e. me understand that the screen shots may be from previous versions of the Omni Application we are using.

I have also managed to create my first, pointless plug-in which is listed below. I basically just tried what I had tried before and pressed the button at the top left of the console but this time Omnioutliner did not enter a loop of errors when I saved the updated script. So for anyone else who is struggling, here is a description of how I created my first working plugin having completed the tutorial.

a) Press the button ‘Add Action’ situated at top left of the console window. This will prompt for some fields to be populated e.g. Action Name, Organisation, Add to toolbar, text editor and lastly local or cloud storage. Enter some text but ensure that the ‘Add to toolbar’ is ticked. I selected BBEdit as my text editor as it provides syntax colouring of the script code.

b) Press the ‘Add’ button. This saves the new ‘action’ to the plugins folder. Once saved Omin Outliner will list the action in the Automation Menu and open the boiler plate script in your text editor.

c) Copy your working code from the console window and paste it below the comment line “// Add code to run …”

d) Save your masterpiece.

e) cross your fingers (not vital) and run the new action.

Here is my first action plugin

/*{
    "author": "Simon Knight",
    "targets": ["omnioutliner"],
    "type": "action",
    "identifier": "com.Skids.Toggle Display of Status",
    "version": "0.1",
    "description": "A plug-in that toggles the display of the status colum",
    "label": "Toggle Display of Status",
    "mediumLabel": "Toggle Display of Status",
    "longLabel": "Toggle Display of Status",
    "paletteLabel": "Toggle Display of Status",
}*/
(() => {
    var action = new PlugIn.Action(function(selection) {
        // Add code to run when the action is invoked
        
        	editor = document.editors[0]
	tree = document.outline
	StatusColVisible = editor.visibilityOfColumn(tree.statusColumn)
	
	console.log("Status Col set to : ", StatusColVisible);
	
	if (StatusColVisible) {
	   editor.setVisibilityOfColumn(tree.statusColumn, false);
	   } else {
	   editor.setVisibilityOfColumn(tree.statusColumn, true);}
	
        
        console.log("Invoked with selection", selection);
    });

    // If needed, uncomment, and add a function that returns true if the current selection is appropriate for the action.
    /*
    action.validate = function(selection){

    };
    */
        
    return action;
})();

I have no idea what is happening in the boiler plate code e.g. (() => { is just the way it has to be ;-). My portion of script is based on code from the tutorial: I’ve added a third variable that is boolean and set to the visibility of the status column, this property is described in the API reference that is accessed from the console. Next I added a new console log because I was not sure that I was using the boolean correctly as it seems boolean may be a value and it is also a class. (and no I don’t understand the significance either).

Yes its pointless as it just duplicates a built in operation but it works. Big thanks to unlocked2412 and to the author of the tutorial site Sol.

best wishes
Simon

A good investment of time, I think. These days it’s a really useful language.

Congratulations on your first script.

P.D.: I would advice using const (or perhaps let) for name declarations instead of var (or simply using the name).

Greetings all!

Coincidentally, this topic came up as the OmniOutliner tutorial for macOS was in the process of being revised! Here’s the updated OmniOutliner Automation Tutorial for macOS

Your feedback and suggestions are most welcome!