Consider “show palette of macros” as failed when dismissed without selection?

I have a “launcher” macro that shows a palette of macros, then performs some cleanup work common to all of the macros it can run. (It uses a semaphore to wait for the selected macro to finish before continuing on with the cleanup work.) In the event that I don't want to follow through with the launcher — maybe I accidentally invoked it, say — and I dismiss the palette without selecting one of its macros, is there a way to also cancel the rest of the launcher macro? I'd prefer not to use global variables in this case — ideally just considering a dismissed palette as having failed, and then enabling “failure aborts macro” on the palette action. But this doesn't seem to be an option?

There are people much smarter than me on this site, and might give you a much better answer, but I'm going to try to answer anyway.

I don't use palettes, but I checked your assertion, and I agree there is no way to detect if a palette failed or not. I also agree it would make some sense to have the action return a failure value in the case nothing was selected. I also agree that using global variables could potentially solve this, but it's not desirable as that would get tedious/messy. (Although you really only need one global variable to solve this.)

Let's assume that this action won't/can't be upgraded to detect an absence of a selection. What then?

  1. You could the Prompt for User Input action instead. I do this all the time to let the user select macros. I create a button for each macro that I want the user to be able to trigger. Then I detect which button was pressed and call the appropriate macro. If the user cancels the Prompt action, or times out, I can detect that too.
  2. You could manually generate a list of macros, then put that list into some pull down menu, such as (but not limited to) the Prompt for User Input action. It would look something like this. Notice how there is a list of macros the user can choose from (Macro1, Macro2, Macro3, etc.)

  1. You could switch to a Custom HTML Window action, which you could customize to look an awful lot like a palette. In fact, you might be able to make it look EXACTLY like a palette.

A palette doesn't "fail" as such, and doesn't return any result to the macro that invoked it.

Easiest solution would be to separate your macro into "launcher" and "cleanup" macros, and have your other macros asynchronously execute "cleanup" as their final action. That would let you get rid of the semaphore, too.

Otherwise, it might depend on how you are doing the semaphore -- I've a feeling there may be some "interesting" timing issues there, if you're setting the lock on the called macro before setting it on the launcher.

The other way would be to ask "is cleanup required?" rather than "did a macro run?" If cleanup is common to all of the macros, that implies that there is/are something(s) you can check to see if it is required. So just put your entire cleanup routine in an "If.." that runs after the semaphore releases.

Yeah, I add a pause in the launcher to give the launched macro time to run and start its own semaphore. Not ideal but it works.

You could try something like this, to minimise the hard-coded pause. It'll make the macro wait until the palette is either used to run a macro or dismissed, then wait another beat to let the other macro set the semaphore (you might have to increase that pause):

image

That would give you a better chance of logging the time immediately before the semaphore action and immediately after and getting the difference.

On this laptop it takes 2 milliseconds to execute the "Semaphore Lock" action, realise there's no blocking macro, and continue. Any called macro that locks that same semaphore then takes more than 2/10ths of a second to complete is easily spotted -- and I suspect that anything that requires "cleanup" will take longer than that. Putting that all together and you get something like:

image

All things timing-related are vulnerable to outside influences, though. While this method may work for you I'd consider one of the other options (the launched macros calling "cleanup" themselves, or a state check to see if cleanup is required) instead to avoid potential problems.