Execute contents of group action, not whole macro. how?

Hi, I often reuse groups of macros. How can I run a 'group' inside a macro, so that I can reuse such groups and don't have to re-create them, but can reference them?

Feel like this must exist somewhere, but I can't find it. I also could not find anything by searching..

Thanks!

.To reference a group of actions

  1. Select it, and
  2. in the Keyboard Maestro main menu, choose Edit > Copy As > Copy UUID.

Launch the group by its UUID using a script action like:

( pasting your copied UUID to replace the UUID shown in that image)


UPDATE

Scratch that.

(The copied UUID is for the whole macro)

Instead, to run just a selected group, you need to use:

Edit > Copy As > Copy as XML

and then pass the whole XML source, between backtick quote characters, to the .doScript method as in:

Execute a group of actions by its copied XML.kmmacros (4 Ko)

Expand disclosure triangle to view JS source
Application("Keyboard Maestro Engine")
.doScript(`<?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>15982211</integer>
        <key>Actions</key>
        <array>
            <dict>
                <key>ActionUID</key>
                <integer>15982326</integer>
                <key>DeviceID</key>
                <string>SOUNDEFFECTS</string>
                <key>MacroActionType</key>
                <string>PlaySound</string>
                <key>Path</key>
                <string>/System/Library/Sounds/Glass.aiff</string>
                <key>TimeOutAbortsMacro</key>
                <true/>
            </dict>
            <dict>
                <key>ActionUID</key>
                <integer>15982593</integer>
                <key>DeviceID</key>
                <string>SOUNDEFFECTS</string>
                <key>MacroActionType</key>
                <string>PlaySound</string>
                <key>Path</key>
                <string>/System/Library/Sounds/Glass.aiff</string>
                <key>TimeOutAbortsMacro</key>
                <true/>
            </dict>
            <dict>
                <key>ActionUID</key>
                <integer>15982670</integer>
                <key>DeviceID</key>
                <string>SOUNDEFFECTS</string>
                <key>MacroActionType</key>
                <string>PlaySound</string>
                <key>Path</key>
                <string>/System/Library/Sounds/Glass.aiff</string>
                <key>TimeOutAbortsMacro</key>
                <true/>
            </dict>
        </array>
        <key>MacroActionType</key>
        <string>Group</string>
        <key>TimeOutAbortsMacro</key>
        <true/>
    </dict>
</array>
</plist>
`);

Thank you so much for this! Very interesting...
Yes, I meant group of actions within a macro.

Question: When I 'copy as XML', does it copy just the reference to the group of actions?

My intent is to have a set of 'template' action groups strored in some macros that I can reference anywhere else. This would allow me to change just one action group, instead of dozens every time (I organize my complex macros mostly through 'action groups'.

It copies, in XML terms, the whole definition of the sequence of actions within a group.

(There is no referential indirection – it's not an address or ID, just the full source text)

For an ID, you would have to aggregate your template elements as macros, rather than as action groups.

That would also enable you to make use of the

Execute a macro action

It may also be worth looking at Keyboard Maestro subroutines as reusable and composable construction blocks,

and at Copy As options like these:

1 Like

That was certainly my first thought.

Actually it was my only thought. :upside_down_face: So I learned something new from the rest of the discussion!

2 Likes

And you can use Dan Thomas' brilliant KMFAM Favorites utility to maintain your collection of favorite actions.

Or use the KM in-built Favorites category...

Personally, though, Subroutines get my vote.

2 Likes

To add to the excellent comments above -- what you use depends on how you want to "reference" these groups of actions.

A sub-routine is a "mini macro" you can use in other macros. The big benefit of using them is that you can make a change in the sub-routine and all the macros that use it immediately benefit from the change -- you don't have to make the same edit in 100 different places. The downside is that while you can "individualise" a sub-routine so that it behaves differently in different macros that can soon get pretty complicated.

You can also put a bunch of actions into a Group action then Favourite that Group. This is a "template" system, making it easy to add those actions to a macro in the Editor, and that macro's Group is independent of all others -- you can make changes in one without effecting others.

A good example of a sub-routine would be a checkout or invoice calculation -- pass in item costs and number purchased. Your sub-routine would then handle the dialogs for tax rate and shipping options and return a total price. You could use that in many macros, and when tax rates change you only have to make one update.

An example of a Favourited Group could be an "incrementing loop" routine where you are always going to want a variable, a loop, a test, an incrementer -- but what happens in the loop will vary macro to macro.

2 Likes

I like alternative solutions, so I'm going to place an alternative solution here. It's not for everyone.

There are times when I didn't want to write subroutines or external macros but I still wanted to avoid the need for copying the code into two separate places in the same macro.

So what I did was create an infinite loop with an internal switch statement that allowed each switch clause to specify which clause would be executed next. In a sense, each switch clause is a "label' and the last line in each switch clause was a "goto." That's not exactly good programming practice, but it allowed me to keep everything in one macro without duplicating my code in separate locations in the macro.

Here's a template to give you the idea, with some different ways to branch as examples. Before you start the loop, you have to set the value of NextStatement to a number from 1 to 5.

2 Likes

What a great conversation. The 'subroutines' gets closest to what I am looking for. I actually already use it, without calling it such. Now knowing from this convo that I cannot reference action groups directly, I can just 'wrap' them in their own macro each...one 'level' higher than what I hoped but guess it can work..