Prompt with List Issue with more than 49 Items

Hi Everyone!

I created a "Prompt with List" Macro with 111 items. In the list action is "Always Show All Entries" on. I can see all items correctly. But the macro works only up to item 49. When I press item 50 or above, nothing happens. I thought there could be an error in the macro and made another test macro with 64 items and one action per entry, but this executes also only item 1 to 49. Is this a known problem and how can I fix this?

I'll attach the test macro.

Many Thanks!

Ronny
Numbers.kmmacros (267.9 KB)

After selecting any option past 49, the engine log shows that 50 macros were executed, at which point all macros are cancelled. It works using the Switch/Case action though, which will be easier to manage generally.

The problem isn't Prompt With List, it's with the 50+ nested Ifs. If you open the log, you'll see your macro stopping when you pick a high number:

2024-12-19 13:13:12 More than 50 simultaneous macros - aborting everything

Each nested If statement appears to be a new macro as far as the KM Engine is concerned. I didn't know that was true, but this macro makes it pretty apparent.

Instead of nesting If statements, you could use a Case statement with one condition for each result. "Case: 1= say 1, 2= say 2, etc." But that's still more complex than required; this entire macro, at least, can be one action after the prompt:

Numbers revised.kmmacros (2.9 KB)

Heck, you don't even need the shell:

Keyboard Maestro Actions.kmactions (1.2 KB)

Keyboard Maestro Export

-rob.

I thin the problem is probably that you have nested 50 actions together. The Prompt action works, and returns values above 50.

You don't need to nest 50 actions. There are (many) other ways to solve your problem. For example, this will speak the numbers up to the maximum:

1 Like

OK, I know that it is not necessary to nest actions to speak a number, and I think I should show you a part of the original macro. For me the problem is more difficult.

I have a really huge project. I use my mac with VoiceOver, because I'm blind. And with Keyboard Maestro I try to make a synthesizer accessible.

There is a list of folders with presets, where I have to click the mouse. Even when I use a variable to set the position for the mouse click I have also to nest all these actions.
and there are other conditions when a mouse click is needed to execute or not, which must be set in other variables. And this must happen for each of these folders.
I'll upload a part of the macro with some of the actions, because the original is very large. If you have another idea instead of nesting the actions, I would very appreciate.

Expansions.kmmacros (2.6 MB)

Whenever you have nested "If..." actions where you are testing the same "thing" in different ways, use "Switch/Case" instead. Not only does it avoid the "maximum macros" problem, it's a lot easier to read.

So your:

...etc would be:

In case those images aren't the best for you, an (attempted!) text representation:

Nested "If"s:

If “AVGMacros” is “Factory2”
   Execute the Following Actions:
      “Factory2” stuff
   Otherwise
      If "AVGMacros" is "Artist Series Nyhdroe"
         Execute the Following Actions:
            "Artist Series Nyhdroe" stuff
         Otherwise
            If "AVGMacros" is “#FairVenger CMII”
               Execute the Following Actions:
                  "#FairVenger CMII" stuff
               Otherwise
                  If "AVGMacros" is “8 Bit Era”
                     Execute the Following Actions:
                        "8 Bit Era" stuff
                     Otherwise
                        If "AVGMacros" is “16 Bit Era”
                           Execute the Following Actions:
                              Do "16 Bit Era" stuff
                           Otherwise...

"Switch/Case":

		Switch of Variable “AVGMacros”
		If it is “Factory2”, Execute the Following Actions:
		Do "Factory2" stuff
		 
		If it is “Artist Series Nyhdroe”, Execute the Following Actions:
		Do "Artist Series Nyhdroe" stuff
		 
		If it is “#FairVenger CMII”, Execute the Following Actions:
		Do "#FairVenger CMII" stuff
		 
		If it is “8 Bit Era”, Execute the Following Actions:
		Do "8 Bit Era" stuff
		 
		If it is “16 Bit Era”, Execute the Following Actions:
		Do "16 Bit Era" stuff
2 Likes

It would be so nice is Switch/Case supported the same set of conditionals as If/Then—I often have to fall back to If/Then because I need to test something that's only available in If/Then. I believe this came up as a feature request a while back, and Peter said it sounded like a generally good idea, but of course I can't find that thread now.

-rob.

4 Likes

Agreed! I too often find myself reverting to an if-statement when a switch would objectively be better and easier because of the switch action's limited condition testing.

Many Thanks, the Switch/Case action was unknown for me, but it seems like it's working.

I have another question. When I want to reach Items 65 to 108 I have to execute a scroll down action. And when I want to have one of the first 64 items I have to scroll up to click on the right item.
I put these scroll actions in every of the switch/case actions. Now I am able to select Item 23 and later item 80 for example. And than item 5 or another.
But is it necessary to put these scroll actions into every action or is there a way to check whether I clicked an item from the first 64 or from the last entries and do this with one action outside the switch/case actions?

...and

I haven't found that -- but then I prefer "If... Then... Else" and rarely nest enough that there's a problem. I should probably use "Switch/Case" more, but the times I think to do so are exactly the times its conditions are appropriate.

I don't actually need or want all of them, but some would be very useful: script condition, typed string, window conditions...

-rob.

Those, yes, plus found image are big ones for me as well. But I could see using key, ocr, macro/group, and menu conditions coming in very handy, too.

Most of them can be spoofed by setting a variable first then testing the variable in the "Switch/Case".

And for those that haven't tried it -- you can roll your own, more powerful, Switch/Case using "If" actions in a one-time "Repeat". Not only do you get access to all the "If" actions conditions and the ability to test different "things" in every "If" -- you can also mimic the "Case" logic of other languages, eg JavaScript, where you can match a case and continue to try and match later cases.

Example, where I've put "Display"s in the "otherwise" section so you can see they aren't executed -- normally I'd use "Do nothing" comments to show they are deliberately empty:

If:Case Demo.kmmacros (13.7 KB)

Image

3 Likes

Hello,

Many Thanks for your help, I have now switched not only this one macro but also many other macros from "If Then Else" to "Switch/Case," and I’m quite satisfied because the macros have become much more compact and smaller as a result. However, I still have the problem that, in cases where one macro needs to trigger another, the 50 macros limit is repeatedly reached, and my interface stops working.

I’ve read a lot in the forum about this issue and the corresponding message, but I can’t find a solution to prevent it in my case.

All my macros consist of "Prompt with List" actions, where I have to select an entry. For some entries, a new macro will be triggered, while for others, actions are executed within the same macro.

I’m attaching five macros to show how I’ve built them. By now, I understand that something about this setup must be wrong, but I can’t figure out the correct solution.

Specifically, my concern is about the "Execute a Macro" actions within a "Repeat" action. And there are many cases like this. Even the "Main Menu" macro is a "Repeat" action. If I select the entry "Header" from the list, I want the "Header" macro to be executed, and the "Main Menu" macro to be canceled immediately. That’s why I built it this way and thought it would work:

Execute Macro "Main Menu"
Pause for 0.1 Sec
Cancel this Macro.

But it doesn’t work, and I also understand why it doesn’t work. The "Header" macro is executed and shows its first action. However, the actions of the "Main Menu" macro, such as the pause and "Cancel this Macro," are not executed even though the macro should still be running.

And when I return from the "Header" list to the "Main Menu," a new instance of the macro is executed, but the "Header" macro is still running. As a result, more macros are now active than I want.

I really want that, whenever a new macro is executed, the previous macro is canceled. Could you please help me and provide tips on how I can restructure the macros? I don’t want to change the setting that limits the 50 macros.

And I don't want to have all in one macro, because it would be very large and I want to have several keyboard shortcuts to enter this interface.

Thank you very much!

Ronny
VPS Avenger Control Snippet.kmmacros (528.1 KB)

I took a peek at your macro, and noticed that the last action in your macro named "Expansions" is an Execute Macro action calling itself. This approach will often lead to the 50 macro limit. You probably need to rewrite this macro so that it doesn't call itself.

One way to probably solve this approach is to simply place all these actions in an infinite loop, like this:

But if you do that, you need to be careful to add this statement:

anywhere that the macro would have otherwise exited without repeating itself. In your case, that would be for the first clause in your Switch action.

If you took this approach, the macro would re-run itself without that recursion approach. But I didn't study your whole macro, just this recursive part of it.

Thank you for your response.

The fact that the expansion macro calls itself at the end of the "Otherwise" block in the action with the variable AVGXPView is a different problem. However, this happens only rarely because these actions should only be executed if the variable is not 8.

I cannot put the entire macro in a loop because, at this point, the loop should not restart when the variable is 8.

I am hitting the 50 macros limit because I need to execute new macros across the different menus, but the previous macros do not terminate properly. Unfortunately, I cannot take a screenshot of a specific part of the screen because I am visually impaired. That’s why I have posted the entire macros.

Additionally, the actions "Cancel this Macro" or "Cancel just this Macro" do not work after executing another macro, as I already mentioned in my previous post.

Perhaps you could take a look at the "Main Menu" macro, particularly the Switch action. For example, when the variable "AVGMacros" is "Header," the "Header" macro should be executed, and the "Main Menu" macro should be terminated. If there were a solution for this without hitting the 50 macros limit, I would greatly appreciate it.

Thank you again for your assistance!

Ronny

That is why I told you to add a "Cancel" action in that part of your code. This will prevent the macro from restarting when the variable is 8.

My previous idea would solve your problem, but if you want another solution, here it is. I do the following all the time when I need blocks of code to be executed without filling up the call stack. Basically, you create a variable, which I usually call "State", that can change while the macro runs. Whenever the variable changes, it retries the loop and goes to the appropriate code. In effect, this is like a GOTO statement.

Either of these solutions will prevent the 50-deep execution limit. You just have to decide which approach to use and change your macro to use one of these new styles.

I apologize, but I’m having some difficulty understanding this, especially when explanations are shown with images. Although I can use OCR software to read the text from images, the results are often very inaccurate. For example, I didn’t fully grasp the explanation about the "Cancel" action within the loop.

Additionally, when someone executes the "Expansions" macro and the variable is not 8, I actually want the macro to restart after setting to 8 from the beginning and display the list from the "XPs" action. However, it should not loop after that. That’s why I had used the "Execute Macro" action at the end.

Unfortunately, I don’t quite understand the calculation condition in the "While" action either. What should I enter into the text field where the number 1 is shown when adding the condition? Do I need to use a variable here as well?

For both solutions, do I understand correctly that I would need to combine all macros into one large macro? How can I keep my keyboard shortcuts in this case? Currently, I have 43 macros, many of which contain a significant amount of content, and I will likely add more in the future. That would result in one massive and highly complex macro, which could become very hard to manage. Or am I misunderstanding something fundamentally here?

I’m certainly not yet a Keyboard Maestro expert, but I really want to learn all of this, and I appreciate every bit of help.

Kind regards,

Ronny

Okay, sorry. Let me upload the macro instead. Here it is. I modified it to do something a little bit more useful so it might be more clear. This implements a little puzzle I learned as a kid. If a number is odd, you multiply it by 3 and add one, but if it's even, you divide by 2. Eventually it will return to 1 (this hasn't actually been proven by mathematicians yet, but seems to be the case.) Just start the macro and it will pick a random number and speak the sequence that it calculates. It should be fun to listen to. This macro stores the "state" of the calculation in a variable called "State" which can contain either the word "Even", "Odd", "Unknown" or "Quit".

This method can be quite useful. I use it nearly every day to solve problems. It avoids recursion. And I think it will solve your problem. If you don't like this new method, we can discuss the first method that I suggested.

Group Action (v11.0.3)

Group.kmactions (7.8 KB)

1 Like

Ok, the first method I understood. The Expansion macro now works as expected. I'll take a look of your new macro today evening. But how is the first method usable with more than one macro?

Many thanks again!