FEATURE REQUEST: A Massive Enhancement Request to make it easier developing Macros

Hello Peter (@peternlewis) :wave:

I recently stumbled across these Questions in my mind after reading elsewhere what a heavy impact a lot of Enable/Disable Macro/Macro Groups possibly could have when you have a lot of them acting.

  • why is there no Dedicated Activate Macro Action and no Condition that checks the Activated/Deactivated Status?!

It would be nice to have these features because it would have less impact on the Workflow when a lot of conditional switching between available Macros is going on as for example on my Macs for example. I tend to be alwaya sure thar only the Macros I am working with in the specific cext are enabled or ative for use. the same goes for the Macro Groups whats not needed is always disabled.

For example my Main Palette for KM that is triggered by a BetterTouchTool Gesture:

the Macro that displays me this Palette and the Containing Callers for Dedicated Tasks are not enabled until I use the BetterTouchTool Trigger to enable this Palette via AppleScript Code. Every Macro on this Palette also enables its dedicated SubMacro only when the Macro is triggered. The called SubMacro disables then before doing its work the Pacros of the Palette then the Palette and as a final the Palette caller.

I think that should give an example of my Workflow. Now - back to the Topic.

For Scripting it would also be nice if these features were available - speaking of an activate & deactivate as well as a toggle command for Macros and Macro Groups not only the currently available enabled and disabled commands. And commands to test for the activated, deactivated or toggled status.

Another great thing to have would be these Tokens for the Text Condition Statements:

  • Getting Information about Active or Inactive Macro Groups:

    • %ActivatedMacroGroups% ==> For Building a list of Active Macro Groups containing Name & UUID allowing fo custom Delimiter per Line

    • %ActivatedMacroGroupsByName% ==> Bding a List of Active Macro Groups only using theit Names

    • %ActivatedMacroGroupsByUUID% ==> Bding a List of Active Macro Groups only using theit UUIDs

    • %DeactivatedMacroGroups% ==> For Building a list of Inactive Macro Groups containing Name & UUID allowing fo custom Delimiter per Line

    • %DeactivatedMacroGroupsByName% ==> Bding a List of Inactive Macro Groups only using theit Names

    • %DeactivatedMacroGroupsByUUID% ==> Bding a List of Inactive Macro Groups only using theit UUIDs

  • Getting Infortion about Active or Inactive Macros:

    • %ActivatedMacros% ==> For Building a list of Active Macros containing Name & UUID allowing fo custom Delimiter per Line

    • %ActivatedMacrosByName% ==> Bding a List of Active Macros only using theit Names

    • %ActivatedMacrosByUUID% ==> Bding a List of Active Macros only using theit UUIDs

    • %ActivatedMacrosByNameInGroupNamed% ==> Bding a List of Active Macros only using theit Names of Provided Group Name

    • %ActivatedMacrosByUUIDInGroupNamed% ==> Bding a List of Active Macros only using theit UUIDs of Provided Group Name

    • %DeactivatedMacros% ==> For Building a list of Inactive Macros containing Name & UUID allowing fo custom Delimiter per Line

    • %DeactivatedMacrosByName% ==> Bding a List of Inactive Macros only using theit Names

    • %DeactivatedMacrosByUUID% ==> Bding a List of Inactive Macros only using theit UUIDs

    • %DeactivatedMacrosByNameInGroupNamed% ==> Bding a List of Inactive Macros only using theit Names of Provided Group Name

    • %DeactivatedMacrosByUUIDInGroupNamed% ==> Bding a List of Inactive Macros only using theit UUIDs of Provided Group Name

  • Getting Information about Enabled or Disabled Macro Groups:

    • %EnabledMacroGroups% ==> For Building a list of Enabled Macro Groups containing Name & UUID allowing fo custom Delimiter per Line

    • %EnabledMacroGroupsByName% ==> Bding a List of Enabled Macro Groups only using theit Names

    • %EnabledMacroGroupsByUUID% ==> Bding a List of Enabled Macro Groups only using theit UUIDs

    • %DisabledMacroGroups% ==> For Building a list of Disabled Macro Groups containing Name & UUID allowing fo custom Delimiter per Line

    • %DisabledMacroGroupsByName% ==> Bding a List of Disabled Macro Groups only using theit Names

    • %DisabledMacroGroupsByUUID% ==> Bding a List of Disabled Macro Groups only using theit UUIDs

  • Getting Infortion about Eabled or Disabled Macros:

    • %EnabledMacros% ==> For Building a list of Enabled Macros containing Name & UUID allowing fo custom Delimiter per Line

    • %EnabledMacrosByName% ==> Bding a List of Enabled Macros only using theit Names

    • %EnabledMacrosByUUID% ==> Bding a List of Enabled Macros only using theit UUIDs

    • %EnabledMacrosByNameInGroupNamed% ==> Bding a List of Enabled Macros only using theit Names of Provided Group Name

    • %EnabledMacrosByUUIDInGroupNamed% ==> Bding a List of Enabled Macros only using theit UUIDs of Provided Group Name

    • %EnabledMacrosByNameInGroupByUUID% ==> Bding a List of Enabled Macros only using theit Names of Provided Group UUID

    • %EnabledMacrosByUUIDInGroupByUUID% ==> Bding a List of Enabled Macros only using theit UUIDs of Provided Group UUID

    • %DisabledMacros% ==> For Building a list of Disabled Macros containing Name & UUID allowing fo custom Delimiter per Line

    • %DisabledMacrosByName% ==> Bding a List of Disabled Macros only using theit Names

    • %DisabledMacrosByUUID% ==> Bding a List of Disabled Macros only using theit UUIDs

    • %DisabledMacrosByNameInGroupNamed% ==> Bding a List of Disabled Macros only using theit Names of Provided Group Name

    • %DisabledMacrosByUUIDInGroupNamed% ==> Bding a List of Disabled Macros only using theit UUIDs of Provided Group Name

    • %DisabledMacrosByNameInGroupByUUID% ==> Bding a List of Disabled Macros only using theit Names of Provided Group UUID

    • %DisabledMacrosByUUIDInGroupByUUID% ==> Bding a List of Disabled Macros only using theit UUIDs of Provided Group UUID

  • Getting Information for Seecte Macros Or Macro Groups

  • %MacroGroupSelection% ==> Returns the Name & UUID & ToggleUUID of the selected Macro Group as an array of Elements including "Palette" if configured as Palette & "Menu" if configured to display its own Menu in the MenuBar

  • %MacroGroupSelections% ==> Returns the Same as %MacroGroupSelection% but as a List because it is to use with multiple Macro Groups selected

  • %MacroSelection% ==> Returna the selected Macro's Name & UUID as an array of objects

  • %MacroSelections% == Returns the same s %MacroSelection% but as a List because it is to use with multiple Macros selected

Also on my Whishlist would be a Macro Collection Condition and Macro Groups Collection Condition for the For Each Avtion that is designed to work with the massives List of the above Tokens.

Here a Token for Window management related tasks - useful for people who have more than one Editor Window open at a time

  • %KMWindowTitleForWindowIndex% ==> Returns the Tite of the Editor Window specified by its Index Number

Another Token Collection To help creating Unique Macro Names or help with other Tasks like Getting the Macro Group of a Macro - and even an enhancement for use with the New Two requested Collection Conditions:

  • %MacroUUIDsForName% ==> Tended to create a List of all Macros using their UUIDs matching exactly the Name provided or possible other parameters like contains the provided text

  • %MacroGroupsForMacroName% ==> Tended to create a List of all Groups using their Names matching exactly the Name provided or possible other parameters like contains the pvided text

  • %MacroGroupNameForMacroUUID% ==> Tended to give back the Group Name for one particular provided MacroUUID

  • %MacroGroupNamesForMacroUUIDs% ==> Tended to give back the Group Names for a List of provided MacroUUIDs but when more than one Match on a Group then display as an array of the provided UUID and the Group Name per line

  • %MacroGroupUUIDForName% ==> Gives Back the UUID of a provided Name or a String Match via Parameter

  • %MacroGroupUUIDsForName% ==> Gives Back the UUIDsin a List of a provided Name or a String Match via Parameter

  • %MacroGroupToggleUUIDForName% ==> Gives Back the ToggleUUID of a provided Name or a String Match via Parameter

  • %MacroGroupToggleUUIDsForName% ==> Gives Back the ToggleUUIDs in a List of a provided Name or a String Match via Parameter

Speaking of Functions there are some Keyboard Maestro related ones, too

  • an KMWINDOWINDEXFORWINDOWTITLE() Function: ==> Returns 1 for the Frontmost Editor Window or the only one if only one Window is open and no Title is defined

  • an KMEDITORWINDOWSCOUNT() Function: ==> Returns how many Editor Windows are open

  • a SELECTEDMACROGROUPSCOUNT() Function: ==> Returns how many Macro Groups are selected

  • a SELECTEDMACROSCOUNT() Funtion: ==> Returns how many Macros are selected

  • an ACTIVATEDMACROGROUPSCOUNT() Function: ==> Returns how many Macro Groups are activated

  • an DEACTIVATEDMACROGROUPSCOUNT() Function: ==> Returns how many Macro Groups are deactivated

  • an ACTIVATEDMACROSCOUNT() Function: ==> Returns how many Macros are activated

  • an DEACTIVATEDMACROSCOUNT() Function: ==> Returns how many Macros are deactivated

  • an ENABLEDMACROGROUPSCOUNT() Function: ==> Returns how many Macro Groups are enabed

  • an DISABLEDMACROGROUPSCOUNT() Function: ==> Returns how many Macro Groups are disabled

  • an ENABLEDMACROSCOUNT() Function: ==> Returns how many Macros are enabled

  • an DISABLEDMACROSCOUNT() Function: ==> Returns how many Macros are disabled

KM Has a Wonderful Feature Called Show or Hide deactivated Macro Groups.
On my Wish list is to have this also for Macros. But It would also be great to have an Action for that - which lets us choose which Groups and which Macros. The Action should have an option for All Macros, All Macro Groups, Selected Macros, Selected Macro Groups, and with String definition options. and as Main Options these three: Show, Hide & Toggle.

Not to forget the Macro Groups which are Disabled on Particular Macs when Syncing is enabled. I want to be able to hide themfrom the List, too

Maybe some Tokens to work with conditions:

  • %ShownDisabledMacroGroups% ==> For Displaying a List of All Shown Disabled Macro Groups

  • %ShownDisabledMacroGroupsOnMac% ==> For Displaying a List of All Shown Disabled Macro Groups on a Particular Mac providing the Name or UUID of the Mac

  • %HiddenDisabledMacroGroups% ==> For Displaying a List of All Hidden Disabled Macro Groups

  • %HiddenDisabledMacroGroupsOnMac% ==> For Displaying a List of All Hidden Disabled Macro Groups on a Particular Mac providing the Name or UUID of the Mac

For better use of all or at least many of the above requested features here is one thing that would be awsome to have:

  • A Text Field in these Actions

    • Enable Macro Group

    • Disable Macro Group

    • Toggle Macro Group

    • Enable Macro

    • Disable Macro

    • Show Macro Grouop

    • Hide Macro Group

    • Activate Macro Group

    • ( the above requested Activate Macro Action as well )

Since this Request is a pure Keyboard Maesto Editor based Request and maybe a lot of could eventually be scripted - even when simple or complex - I want to say something .... maybe there are a lot of users who want to have as less Scripting as possible in their Macros - may it be because of no interrest in scripting or they have no clue or what ever. This is one of the reasons I made the request of all these features above.

Another Reason is my Last Feature Request where you told me about complex UI and maybe some Features wouldn't be Implemented because of this fact.
With this Feature Request I'll want to show you that it would be Possible to use the Existing UI and the maybe bigest change could be if yadd the two reested Collection Conditions.

Speaking of scripting - besides what I restqed above or new commands. It would be nice if you could implement as much as possible of these Tokens and Funtions and maybe try to make some of the existing ones available for scripting if they arent.

I am waiting now for your feedback now because this Request is now more than 200 lines of text.

Greetings from Germany and have a great day

Tobias

I'm sorry I didn't quite follow the main point of your post… luckily it's not directed at me.

However, I do think it would be nice if Activate Macro Group had a text field so it could be done programmatically, as you mentioned at the end.

I know ways of doing similar, like with a switch action, but it would be nice for some workflows I have that involves toggling lots of macro groups.

Hey Oli (@olifrost):wave:

Thanks for your reply …

Many of the features are for allowing us to have better control over the Editor

Others are thought out to build loops for activating Macros and or Groups in bulk & also have the ability to build checking routines based on text conditioning without having to actually know a particular UUID or anything related.

It should us also allow to use less scripting what would be for some tasks very very difficult.

Have a great day

Greetings from Germany :de:

Tobias

I'm not sure if you are aware, but tokens need to be fast, because they are atomic. That means all other engine actions, including the running of other macros, cannot run while a token is being evaluated. If any of your suggested tokens take a long time to execute, that could add lag to any OTHER running macros. It may not be a big deal, but just to perform an interesting experiment, I ran a macro to test the execution time of all existing KM tokens. I'm selecting and displaying some items from the list below to let everyone see that the typical time it takes to run a token is 0.002 seconds. (Although that includes my time measurement actions, so the true time it takes is probably a lot less.) I can guess that some of your tokens would need a longer duration to calculate because they would require that the KM Engine run through a loop through all of the user's groups to do its evaluation. I have hundreds of groups so it may take a much longer time to execute your proposed tokens.

In the list below, the name of the token is displayed, followed by the number of seconds it took to run followed by its result to prove that the token was actually evaluated. I removed quite a few tokens from this list because they required arguments and I was too lazy to create arguments for every token that required one.

AccessedVariables=0.001987 > LocalTokens,LocalToken,LocalEvaluate,LocalEvaluate2,LocalStart,LocalEvaluate1
ActionResult=0.001985 > OK
AddressBook=0.001981 > Bad AddressBook Token
AlertButton=0.001991 >
AudioInputDevice=0.001943 > iMac Microphone
AudioInputDeviceUID=0.001965 > BuiltInMicrophoneDevice
AudioOutputDevice=0.001962 > iMac Speakers
AudioOutputDeviceUID=0.001993 > BuiltInSpeakerDevice
AudioSoundEffectsDevice=0.001973 > iMac Speakers
AudioSoundEffectsDeviceUID=0.001906 > BuiltInSpeakerDevice
ChromeBundleID=0.001955 > Unknown
ChromeURL=0.018952 > KMERROR:Internal AppleScript Execute Error (null)
CurrentApplication=0.00195 > Keyboard Maestro
CurrentMouse=0.001979 > 912,491
CurrentTrack=0.002058 > Music Not Running
ExecutingInstance=0.001986 > 30DE69B7-28EF-46C9-BE62-917089F4F5C0:D78CA823-90EB-4D1D-B19C-DDFC7A1C9FA2
FinderInsertionLocation=0.1996 > /Users/myname/Desktop
FrontBrowser=0.001992 > Safari
FrontBrowserBundleID=0.00199 > com.apple.Safari
FrontBrowserName=0.001988 > Safari
FrontBrowserPath=0.001991 > /System/Volumes/Preboot/Cryptexes/App/System/Applications/Safari.app
FrontBrowserURL=0.132872 > https://wiki.keyboardmaestro.com/Tokens
FrontBrowserWindowName=0.121114 > Tokens [Keyboard Maestro Wiki]
FrontWindowFrame=0.001936 > 753,25,1401,1132
FrontWindowName=0.001995 > Keyboard Maestro Editor — Z
FrontWindowPosition=0.001988 > 753,25
FrontWindowSize=0.001931 > 1401,1132
JSONFromDictionary=0.002 > {}
KeyboardLayout=0.001979 > Canadian
KeyboardMaestroLongVersion=0.001971 > Keyboard Maestro Engine 11.0.3, Copyright 2004-2024 Stairways Software Pty Ltd.
KeyboardMaestroVersion=0.001882 > 11.0.3
LastAbortedActionID=0.001975 > 16048761
LastApplication=0.008556 > Safari
LineFeed=0.001966 >
LongDate=0.001955 > Monday, September 9, 2024
LongSystemVersion=0.00204 > Version 14.6.1 (Build 23G93)
LongTime=0.002065 > 12:03:51
MacIPAddress=0.001921 > 10.1.1.2,192.168.2.31
MacName=0.002061 > MyName’s iMac
MailBCCRecipients=0.059867 >
MailCCRecipients=0.026944 >
MusicPlayerState=0.001995 > not running
NetworkLocation=0.001989 > Automatic
NumberDate=0.001997 > 2024-09-09
OptionReturn=0.001988 > ䷗
PromptButton=0.001982 >
RandomUUID=0.002032 > 36CD1EAA-DD15-4397-A4B6-551484CF24BF
SafariBundleID=0.001953 > com.apple.Safari
SafariLongVersion=0.001985 > 17.6, Copyright © 2003-2024 Apple Inc.
SafariName=0.001974 > Safari
SafariPath=0.001992 > /System/Volumes/Preboot/Cryptexes/App/System/Applications/Safari.app
SafariURL=0.131284 > https://wiki.keyboardmaestro.com/Tokens
SafariVersion=0.001916 > 17.6
SafariWindowName=0.130324 > Tokens [Keyboard Maestro Wiki]
ShortDate=0.002002 > September 9, 2024
ShortTime=0.001938 > 12:03
Space=0.001941 >
SystemClipboardFlavors=0.002024 > com.apple.traditional-mac-plain-text,com.stairways.keyboardmaestro.actionarray,public.utf16-plain-text,public.utf8-plain-text
SystemLongVersion=0.001983 > Version 14.6.1 (Build 23G93)
SystemVersion=0.001951 > 14.6.1
SystemVolume=0.137089 > 94
Tab=0.001991 >
Trigger=0.001964 > Trying
TriggerBase=0.001987 > Trying
TriggerClipboardFlavors=0.00205 > com.apple.traditional-mac-plain-text,com.stairways.keyboardmaestro.actionarray,public.utf16-plain-text,public.utf8-plain-text
TriggerValue=0.001927 >
UserHome=0.001953 > /Users/myname
UserLoginID=0.001938 > myname
UserName=0.001969 > MyName
VBAR=0.001952 > %VBAR%

To my surprise, a couple of these tokens actually did take a long time to run, like %SystemVolume%. If you have macros that are bothered by lag, you probably shouldn't be using these tokens.

It would be interesting to see if @PeterNLewis, with his access to internal engine coding, could tell us what the true execution time is for a typical token. (And perhaps for a couple of common KM actions, like the Set Variable to Text action.)

1 Like

Hello Airy (@Airy) :wave:

Thanks for your reply …

This run time for a token is quite impressive though - didn’t knew that but isn’t KM‘s whole system generally designed to run fast ?!

I mean the Engine is designed to run up to 1000 actions per second - if I remember it right…

Based on that and based on my little backstory above (the Palette example) combined with thousands of macros in mind let’s talk about some things I requested because it depends …

Let’s say %EnabledMacros% (a new requested token from above) takes 0.004 seconds to load a list of 6000 Enabled Macros in a total of 10000 - that would not be bad at all.

But here is the thing - if you have a long list of Macros to filter further for a specific string to narrow down that list the more it time it takes …

Based on that what is quicker

For each line in %EnabledMacros% with 6000 Macros

or

For each line in %EnabledMacros% with 600 Macros

I think the answer is obvious - you see it depends … the same thing for the List you’ve provided to depends what the token has to do … how much work the token has to do …

And of course to see some tokens I requested that were already integrated with KM 11 - and to see how fast they are compared to others - makes me somewhat a little proud of my self …

And as always it also depends which Mac the whole stuff is running on … we never should have that in mind …

Have a great day

Greetings from Germany :de:

Tobias

While you're waiting for an answer, Toggler Macro (v9.2) will display a custom popup list of macros showing their activation status, which can be flipped by selecting them.

I wrote it because I wanted finer control over a few automatic text transformation activated only in text applications. But I find creating groups that are organized by application type generally makes it unnecessary to toggle macro activation for me.

1 Like

I'm probably confused, because we see above that it takes 0.002 seconds for %CurrentMouse% to return the mouse's position, but you still think it would take 0.004 seconds for %EnabledMacros% to cycle through a list of 10,000 macros to get an answer? That seems odd since you say the Engine can run 1,000 actions per second. I can't follow your math here.

Do you understand my main point, which is that token evaluation must be uninterruptible? And do you follow that this forces all asynchronous macros to pause?

A macro is active if and only if its parent macro group is active.

So it does not make sense to Activate a Macro. You can only activate a macro group, which you can do with the Activate Macro Group action.

Similarly, you can test its activation with the Macro Group condition.

All of these are available (activate/deactivate/toggle for macro groups, enable/disable/toggle for macros and macro groups).

You can do all of that with AppleScript, either to the Keyboard Maestro Engine, using the getmacros command to get all of them, and the gethotkeys with getall to get all the active macros.

All as XML. And then you'll need to parse the XML.

You can get that sort of information with AppleScript to the Keyboard Maestro editor.

Same.

I'm afraid you'll need to get comfortable with AppleScript and/or XML parsing, as I have no plans to implement virtually any of those tokens (except maybe %ActiveMacroGroups% or ones relating to converting UUIDs to names).

Sorry.

The issue with this is the challenging UI for it for a feature that virtually no one will use, and that can be done via XML if someone is sufficiently motivated to want this feature.

Not really. It depends on the token. SystemVolume uses AppleScript, so the time taken is largely caused by having to deal with AppleScript and the lag involved in that communication.

As noted, tokens have to have immediately available results, so even AppleScript is a stretch (and indeed the system API complains that it shouldn't be called in a way that depends on an immediate response and I have to work around that in ugly ways). But that would not be an issue for anything related to providing macro information (name, uid, activation status, etc) since all that information is available to the Keyboard Maestro Engine. It's simply not worth the effort to do I'm afraid, not while there are other ways of doing it, and almost nobody is going to use them and they add complexity (in the form of more token options) that are likely to add confusion to most users who will never want to use the facilities.

5 Likes

Hello Peter (@peternlewis) :wave:

It’s sad that these Ideas never will be implemented - something like Enabling or Disabling of Macros and/or Groups in Bulk from a List of text would be possible with my Suggestions - without a single Line of Code or at least no complex code.

But you’re the boss and have made your decision.

I’ll accept your decision as it is - even though it is bad news to all non scriptwriters out there - since this Feature Request was dedicated especially to them for the most part.

About writing scripts - I am a person who actually loves it to learn coding so it’s no bummer at all to me.

Have a great day and a good time taking Keyboard Maestro to the next level.

Greetings from Germany :de:

Tobias

The good news is that there's a way to do all this stuff, and most of it has been covered on the forum. So, even if you don't know how to script it yourself, it's usually just a matter of a forum search and a macro download. If something isn't covered, you'll almost always get there pretty quickly with the help of a kind soul or two. That's why this is the best forum I've ever been a member of.

5 Likes