PS you will notice from the XML of a Simulate keystroke
action
(Try Edit > Copy As > Copy As XML
)
that the value stored is not the string name of a keystroke, but the hardware key code integer (not a character but a fixed position on the keyboard)
Similarly, any set of keystroke modifiers (like ^⌥⌘) is also encoded in the form of an integer.
Expand disclosure triangle to view XML Source
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>ActionUID</key>
<integer>9293683</integer>
<key>KeyCode</key>
<integer>15</integer>
<key>MacroActionType</key>
<string>SimulateKeystroke</string>
<key>Modifiers</key>
<integer>6400</integer>
<key>ReleaseAll</key>
<false/>
<key>TargetApplication</key>
<dict/>
<key>TargetingType</key>
<string>Front</string>
</dict>
</array>
</plist>
In the osascript
interface (AppleScript or JS) you can use such an XML (plist) string with the Keyboard Maestro Engine
's do script
method to perform the encoded action.
In other words, you can write a function with (KeyCode, Modifiers) :: (Integer, Integer)
parameters, interpolating the pair of integers that is passed to the function, as two integer strings, into the plist string, for use with do script
And I think you can obtain the mask integers (which need to be added up to obtain an integer code for a combined set of modifiers) like this (where AlphaShift
is Caps Lock):
Expand disclosure triangle to view JS Source
(() => {
"use strict";
ObjC.import("AppKit");
// ---------------------- TEST -----------------------
return [
"AlphaShift", "Shift", "Control",
"Alternate", "Command"
]
.map(k => {
const
maskName = `$.NS${k}KeyMask`,
maskValue = eval(`${maskName}`);
return `${k} -> ${maskValue} === 2**${Math.log2(maskValue)}`;
})
.join("\n");
})();
AlphaShift -> 65536 === 2**16
Shift -> 131072 === 2**17
Control -> 262144 === 2**18
Alternate -> 524288 === 2**19
Command -> 1048576 === 2**20