With the default "Modern Syntax" option, Execute JavaScript for Automation objects provide a predefined kmvar
for easy access to KM Variable values.
You can choose, from the menu behind the small chevron to the left of the code field, which key:value pairs are included in kmvar
:
and then, in your script you can easily use the KM Variable values:
You can use Script Editor for sketching and testing JS snippets to use in Keyboard Maestro Execute JavaScript for Automation actions, but three things are worth keeping in mind:
- You are probably better off using Visual Studio Code, to get automatic code formatting etc (but Script Editor is a good enough start)
- To return a value from a KM action you have to explicitly prefix it with the
return
keyword (not needed in Script Editor) - You will not find the
kmvar
object automatically pre-defined for you in Script Editor
Lets ignore point 1.
and focus on 2.
and 3.
Expand the following disclosure triangles to read the details:
The `return` prefix is needed for the action, but not for Script Editor
Adding the return
keyword for the KM action, and removing it for Script Editor – this we probably just have to remember.
One way to handle it is to always wrap your Script Editor code in an "IIFE" – Immediately Invoked Function Expression – which is standard good practice anyway.
A minimum JS script without an IIFE might be:
const value = 2 + 2;
value;
But that hits problems the second time we run it. Declarations are remembered by the Script Editor JS Context between successive runs, and we will be told that you can't declare a constant twice.
We can fix that by using an IIFE-wrapped temporary name-space, which looks like:
(() => {
"use strict";
const value = 2 + 2;
return value;
})()
Notice that it requires a return
, or it will return no value to its context.
The use strict;
incantation just switches on more helpful error messages.
If we run the IIFE version above in Script Editor, we see a computed value appear in the result panel:
If we copy-paste that code directly into an Execute JavaScript for Automation action we need to prefix the whole script with return
, before KM sees a result:
But Keyboard Maestro is secretly wrapping our work in its own IIFE, so if we want we can now eliminate that for the action:
In practice, if I am moving back an forth between an action and a code editor like Script Editor, I find it easier to leave an explicit IIFE in place, and just:
- add a
return
when pasting into the action, and - delete the
return
when I paste back into the code editor
No `kmvar` object is automatically pre-defined in Script Editor
To test a script in Script Editor, before using it in a Keyboard Maestro Execute JavaScript for Automation, we would like to be able to use the simple kmvar.Application_name
and kmvar.activeLang
etc format.
A trick that I often find useful is to:
- temporarily declare a
kmvar
object (by copy-paste) at the top of the script in Script Editor or Visual Studio Code, - use it in testing, and then
- comment it out before pasting into the Keyboard Maestro action
To get a JSON (JavaScript Object Notation) copy of the kmvar object:
- Select the variables that you want in the small chevron menu to the left of the JXA code field in the KM action
- return the expression
JSON.stringify(kmvar, null, 2)
from the action.
(The null
means no special adjustments, and the 2 gives indents of two spaces)
This will produce a JSON copy of kmvar
which you can paste into your script – something like this:
{
"activeLang": "com.apple.inputmethod.SCIM.ITABC",
"Application_name": "Mail",
"backgroundColor": "[0.13330282270908356,0.13330282270908356,0.13330282270908356]"
}
prefixing it with const kmvar =
thus, perhaps, for Script Editor:
(() => {
"use strict";
const kmvar = {
"activeLang": "com.apple.inputmethod.SCIM.ITABC",
"Application_name": "Mail",
"backgroundColor": "[0.13330282270908356,0.13330282270908356,0.13330282270908356]"
};
return kmvar.activeLang;
})()
and correspondingly, for the KM Execute JavaScript for Automation action:
- prefixing the whole with
return
, and - commenting out the explicit declaration of
kmvar
return (() => {
"use strict";
// const kmvar = {
// "activeLang": "com.apple.inputmethod.SCIM.ITABC",
// "Application_name": "Mail",
// "backgroundColor": "[0.13330282270908356,0.13330282270908356,0.13330282270908356]"
// };
return kmvar.activeLang;
})()