Execute macro by variable name

Hi Keyboard Maestros,

I’m working on moving my Text Expander snippets to Keyboard Maestro. I can reproduce lot of the functionality pretty easily, but there is one Text Expander feature I’m struggling to reproduce in Keyboard Maestro.

All the TE-replacement actions are triggered by typing some unique string, like “;snipA”. In the basic use case, I have an action to paste in some replacement text, like “EXAMPLE SNIPPET TEXT!” But in some of the more complex use cases, I have a snippet that refers to another snippet. This looks something like: “;snipB” -> “Recursive snippet: %snippet:;snipA%”. The “%snippet:(…)%” is a keyword in TE that means to first replace in the text of whatever snippet(s) is(are) named there, then paste in the combined text after expanding all the nested snippets.

It seems like I could do this by executing one KM macro from within another. The problem I’m having is that I can’t execute a KM macro without knowing the name in advance.

I could just go through all of my (hundreds of) Text Expander snippets, find all the “%snippet:(…)%” strings, convert them into “Execute macro” actions referring to specific macros by name, and be done with it. But I would rather automate the problem once and have it work forever, even for new macros. Is there any way for me to pull a bit of text out of a variable, and use that text to execute a specific macro?

P.S. I thought going out to AppleScript might be a solution—for example:
tell application "Keyboard Maestro Engine"
do script ";snipA"
end tell
But I couldn’t figure out how to execute an AppleScript action with a variable. Is that possible?

You can use Keyboard Maestro's URI functionality, like this:

"MacroName" can be a variable.

If you need to pass a parameter, do this:

"SomeValue" (which can also be a variable), will be in the macro's "%TriggerValue% token.

If the name of your macro, or the parameter, might contain invalid URL characters, you can do this first:

One caveat, and it’s probably obvious, but the macro name has to be unique.

You can also pass the “UUID” of the macro, and that eliminates the need for the macro name to be unique. But I doubt it applies in your situation. Just mentioning it to be thorough.

@DanThomas, thanks for your advice.

I haven’t been able to make the kmtrigger:// url action work to do what I want. When I try to execute a macro from within KM using the Open URL action, it doesn’t execute. (I placed a “Pause Debugger” action at the beginning and can verify that it never triggered.) On the other hand, when I open the “kmtrigger://macro=SomeMacroName” URL in Safari, then the macro does execute.

Even if I do get the Open URL action to execute a macro, I don’t know how to use the value that will be produced. I would want to capture the text produced by the invocation of the nested macro, then use that to modify the text of the first macro (i.e. remove the “%snippet:foo%” string and replace it with the value that I got by executing the macro named “foo”).

Ah, I understand (and I should have thought of that).

I have the answer for you - just give me a few to put it together.

What version of KM are you using?

Let me double-check to make sure I understand, before I go any further.

Basically, you will

  1. Construct the name of a macro you want to execute.
  2. Execute the macro “by name”.
  3. The macro will return a result, probably be setting some variable.
  4. Then you’ll use that variable in the rest of your code.

Right?

Oh, and what version of OS/X do you have?

I’m using KM 7.2, OS X 10.11.5.

The steps you’ve given look correct, but only in the case where a macro is being called from another macro. To be more clear, I’ll give two use cases. In both, note the different behavior of Macro B.

  1. I want to trigger Macro A. It triggers on the text “;macroA”. Its action is to evaluate the text “My text is: %snippet:;macroB%”. It has some logic to figure out the name “;macroB” from that “%snippet:…%” string, and follows the steps you’ve given above to get the value of Macro B. It replaces “%snippet:;macroB%” with that value. Then once all “%snippet:…%” strings are gone, its final action is to paste the final value.
  2. I want to invoke Macro B directly, by typing the trigger string “;macroB”.

In the first case, Macro B’s action is to set its value to a named variable, which would be used by Macro A. In the second case, Macro B pastes its value.

I’m thinking of breaking each TE snippet into two KM macros: one that triggers on a unique set of keystrokes, and another that stores a variable value. The first macro would call the second and paste the value in, whereas the second only sets the variable value (and perhaps also parses the variable for “%snippet:…%” strings and calls other macros to resolve those). In this way, I can preserve the behavior I want—each unique set of keystrokes will trigger a value to be pasted—while still allowing other snippets to provide values without every one of them trying to paste its value in where it isn’t needed directly.

Let me post what I’ve got right now, which will work. I’m probably going to make a plugin for it, because it’s a natural for that. But in the meantime, this should do the trick. Give me a few to make it presentable.

Here you go:

I'll probably make this into a plugin, so it's easy to pass a parameter to the executed macro, but this sould work for now.

This looks very useful, thanks!

I will need to tweak it before I can get the workflow I’m thinking of. I’m new at KM, so that will take a while. But this gives me a good start. Thanks agin.

Feel free to ask for modifications, even if it’s only for your use. I don’t mind.

And if you just want to do it yourself, that’s cool also!