Passing an argument from an external script

I’m new to Omni Automation and have been stumped by what I imagine is a ridiculously easy task, passing a script from an external app to Omnifocus with an argument.

So far, I’ve a script in Scriptable that presents recent and near future events. I can then tap on these to get a dialog if I want to create a task. And then it falls down.

My script opens Omnifocus, presents the script and the argument as I would expect, but when run it does not create an inbox item.

const script = `new Task(arg)`;
const taskText = 'Test inbox item' ; //This is usually populated from the dialog input
addInbox = new CallbackURL('omnifocus:///omnijs-run');
addInbox.addParameter('script', script);
addInbox.addParameter('arg', taskText);
addInbox.open();

When I output the callback URL, it looks like I would expect. But I can’t get it to work. If I populate the new Task(input) with a ‘string’ and omit the ‘arg’ parameter a task is created. So the problem appears to be that I lack the knowledge to get Omnifocus to use the argument.

I’ve tried various things I’ve found online, making the inputs strings, encoding them, etc. I’ve also tried various permutations of argument name. And even the odd thing on The Omni Automation website about parentheses. Nothing seems to make a difference.

I’m keen to use a script rather than the URL scheme, partly because I want to learn it, but also because I’d like to do other things that are more complex than just an inbox item.

Can anyone point out, as brutally as they like, the stupid thing I’m missing?

I have not run anything from Scriptable, so this could be different. If you use Shortcuts, you can pass in data with “arguement.input”.

If you want an example, let me know and I can give you one later.

1 Like

Thanks. I’m very keen to do it in Scriptable though, to learn my way around that and JavaScript a bit more.

Quite interesting to see the start of that script and the bracketing though, which prompted me to revisit my efforts on that. And the result was that I finally got it to work by taking The Omni Automation approach to bracketing and including a foreach loop.

I can’t help feeling it’s wrong, since I’m looping over something that will only ever be a single variable, but other than my nagging sense there’s a more elegant solution it doesn’t make any difference in practice.

Documentation regarding Shortcuts can be found here:

https://omni-automation.com/shortcuts/index.html

Here’sthe page on passing input:

https://omni-automation.com/shortcuts/script-action-input.html

That’s the site I had been using. What was puzzling me is why I couldn’t run a script on a single value, but the instructions on that link imply that Omnifocus needs an array, hence I have to iterate over the argument, even though it’s only a single item.

Ah. If you’re sure that the input will be a single string, don’t bother converting to an array. The example on the webpage is generalized to handle whatever situation the user has to deal with. If you’ve created a workflow that always inputs a single string, then adjust your script accordingly.

Hope that adds some clarity!

It’s all been helpful, thank you.

I’ve managed to get it working now. I think my problem was that I got hung up on new Text('A test item') working, but not new Text(argument).

I’ve not seen it anywhere, but am assuming that I have to pass an argument to a function to get the Omni script to pick it up.

I haven’t read any documentation on using URL callbacks to pass in functions, so I’m not sure exactly what the best practices are. I’m still not sure about multi-line functions, but I would use a template literal to build the string before passing it into omni-focus. That way, you don’t have to worry about how to pass in an input. However, I can see that passing in input data would be helpful in other cases.

const taskText = 'Test inbox item' ; //This is usually populated from the dialog input
const script = `var task = new Task("${taskText}",inbox.beginning)`;
console.log(script)
addInbox = new CallbackURL('omnifocus:///omnijs-run');
addInbox.addParameter('script', script);// 
// addInbox.addParameter('argument.input', taskText);
addInbox.open();

The name that becomes available for you to use inside the script is called argument, not arg.

You should pass a string, not a space-separated list of names. So, would be: '"Test inbox item"'.

Fixed script:

const script = `new Task(argument)`;
const taskText = '"Test inbox item"'; //This is usually populated from the dialog input
addInbox = new CallbackURL('omnifocus:///omnijs-run');
addInbox.addParameter('script', script);
addInbox.addParameter('arg', taskText);
addInbox.open();

For larger scripts, I would take some of the ideas Rob Trew left in this forums, and would personally prefer a template like:

(() => {
    "use strict";

    // omniJSContext :: IO ()
    const omniJSContext = () => {
        // main :: IO ()
        const main = () => {
            return new Task(argument);
        };

        // MAIN --
        return main();
    };

    // Scriptable Context -------
    const 
        addInbox = new CallbackURL("omnifocus:///omnijs-run"),
        input = JSON.stringify("Hello World");

    return (
        addInbox.addParameter("script", `(${omniJSContext})()`),
        addInbox.addParameter("arg", input),
        addInbox.open()
    )
})();
1 Like