Variables for timeouts, and more ideas for error handling

I would like to have the timeout values on certain actions (e.g., Execute Macro, Execute Applescript, While) be modifiable. In other words, I want my program to be able to specify the timeouts using a variable. I don't think this is possible but I have to ask because sometimes I'm wrong.

If KM is ever modified to support variables for timeouts, I wish it would go further and support an action that looked more like this: (since I'm not too good at photo-editing this is a text representation of an ideal KM action where "^v" represents a two-headed arrow to allow for changes to parameters)

These actions will timeout after [ 5 ] [^v] minutes [^v]
on any exception execute the following actions:
finally, always execute these actions:

In the example above the number 5 is in a box which supports Calculations including variables. This would also create much improved error handling, which is all part of the purpose of timeouts. On a related matter, the Execute Macro action should have the following new flag: (so that execution does not return)

Due to the lack of a "without returning here" flag in the "Execute a Macro" action, I use the following action to achieve the same goal. Let me explain it... if you use this action to launch a macro then the macro which will be executed after this will be whichever macro is named in the variable "NextMacro". It works but there is a downside, which is that you can never rename your macros unless you also manually rename the corresponding strings every time you assign the name as a string to NextMacro. It's an inconvenience, but so is the lack of a Branch (without returning) action. I probably call this macro 1000 times per day.

You can, of course, delete the yellow "Speak" action if you don't want to hear the names of the macros as they are executed. But I like hearing them (I have it set to speak "quickly.")

Here is a simple case of three macros which is the kind of case I run into all the time. Without a branch action, each time a macro calls another one it builds up a stack of return addresses. But the tasks I need to solve have indefinite length so the Execute Macro action probably won't work for me. As a result the Branch macro above helps me to encode this.

And here's an example of what Macro 1 might actually look like in this case:

Then I simply have to start one of the three macros (Macro 1 or 2 or 3) and if all three macros set the NextMacro variable they will run indefinitely.

I used to have a different solution to this problem, which I might post below.

The previous way I used to solve this problem, since the SWITCH action was created, was as follows:


Usually I would have a state numbered 999 which would exit the loop. In that case the while condition could probably be "State<900".

Please let me know if there's a better way to achieve all this. I am eager to be found wrong if I can learn from it.

This diagram represents a more typical algorithm for me than the three macro scenario above: (the primary reason for all these arrows is error handling)

I have to write code that does this. It's not my fault, that's the way my algorithms solve the problems that I face. So I either use the SWITCH-IN-A-LOOP approach or the BRANCH-VIA-APPLESCRIPT approach. I'm not really complaining, both approaches solve my problem. Sometimes it takes more than the basic WHILE/IF/REPEAT actions to solve my problems.

Both of these solutions have problems. The BRANCH-VIA-APPLESCRIPT solution means I lose KM's good ability to rename macros instantly and easily (although I wish KM could do the same for variables). The SWITCH-IN-A-LOOP approach is a drag on the editor: it slows down the editor to the point where it's barely useable when I have nested and/or sequential SWITCH actions.

I'm not really sure what the right solution is. I suspect Peter is loathe to introduce a BRANCH/GOTO mechanism because that's "not good programming." I think it would be possible to create an enhanced SWITCH action that essentially supports the SWITCH action example above. But I don't think he'll do that. My main purpose in these posts is to find out if anyone can achieve my goals without resorting to Applescript and without the inefficiencies of big SWITCH actions. I need to find a better solution.

I don’t know what you mean by that, but it sounds a lot like the asynchronous option in the action…?

Why not use the Macro’s UUID instead of the name then?

If you want to loop, use a looping action (While true for example).

I’m pretty sure Dijkstra proved that is not the case in the 80s. But in any event, if you want to drive a state machine, then the Switch in a loop is the best solution.

For your example, you basically have a State variable which is 1-7, starts at 1, and a While loop and a Switch loop, which might be:

  • Switch on variable State
    • 1: Execute Macro M1
    • 2: Execute Macro M2
    • otherwise Break From Loop

And each macro can do whatever it likes and then set the State variable appropriately. If the code is not very complex, then you can put it directly in the Switch action instead of the Execute Macro action.

If you want to allow for adjusting the sequence of actions more easily, then use named states rather than just numbers.

Alternatively, use a programming language instead of Keyboard Maestro actions.

It is highly unlikely I will implement any kind of Label/Goto actions.

1 Like

You suggested I use the asynchronous option in the Execute Macro action. Funny, I never thought that if I did that and followed it immediately by a Cancel Just This Macro action, then I think that would achieve the same thing. That idea had never occurred to me. E.g.,

So that's an equivalent to the Branch idea that I was proposing. Brilliant. This is a very close to a GOTO/LABEL action, especially if you use a parameter that includes the state for the next Macro to start in.

Then you asked "Why not use the Macro’s UUID instead of the name then?" The answer is that I'm a lousy programmer who can't think of everything. Thanks for that excellent tip. That's why these forums are so great. (Maybe I should have used the handle Dopey for this website instead of Sleepy.)

Lastly, you asked me to consider using a state variable approach. That's what I did in the example above, and it's how I usually solve these problems, and it functions correctly, but the performance (in the KM Editor) is poor in many cases, which is likely because I typically have 10-20 states in a loop, and then more state loops after that, often they are nested. Eg, if I try to expand a block it often takes 3 seconds from the time I click until the Editor opens the block.

Although I can't be certain, I suspect it's because the KM Editor pauses a lot to "recompile" after each edit. Is that correct? Is there a way I can turn off the auto-compile feature temporarily? This is my biggest technical problem with the KM Editor. The editor freezes a lot, sometimes even losing my keystrokes, because it's busy recompiling. So for example if I run this code:

...there is usually a two second gap between the first and second beep. I think that's because of the auto-recompile feature of the Editor which freezes the engine. In fact I don't even have to change the code for the freeze to occur, all I have to do is expand/contract an action, without changing anything, and it still freezes. There is so much freezing that even if I'm typing text in a window, the editor often freezes while I'm typing.

Make no mistake, I love KM, but the thing at the top of my wish-list for it is to give me more control over the auto-recompile timer. This is all relevant to this thread because I think it's a factor why the SWITCH-IN-A-LOOP approach is unsatisfactory.