MACRO: A list-based alternative to the Progress action

My MacroBackerUpper macro is quite involved, and can take a while to run, so I used a bunch of calls to the Progress action scattered about the code, each with a hardcoded number as an estimate of task completion.

While these worked fine, they're a major hassle if, as I have been doing, you rearrange your macro, take sections out, add new sections in, etc. A simple change can mean changing a number in almost every Progress action, scattered across 20+ separate macros. Ugh. And ugh again.

I wanted a better way to show progress, one that allowed me to rearrange and change the macro without having to make a bunch of adjustments in numerous places. After mulling it over for a while, I decided on a task list that would continuously show the progression through the tasks. Something like this:

Open the hidden section to see how it looks in action…

An animated GIF hides within…


How it works

The task list requires an instance variable that holds the list of tasks, and a subroutine helper macro that does the actual processing. Usage is incredibly simple, once you have the list in a variable: Just call the subroutine with a line of text from the task list.

The subroutine (via a grep command) finds the matching line number for the text in the list of tasks, then uses JavaScript to modify that row (and the next row) in the task list window. It also checks for the last row, as that needs special handling to finish things up properly.

Note that the Javascript you see here is 95% ChatGPT, which is a really amazing tool for someone like me. (The 5% is me putting in the Keyboard Maestro variable, and customizing the formatting :)).

The demo macro

The attached demo macro (a main macro and a subroutine) shows how the task list works.

__ Task List progress tracking Macros.kmmacros (11 KB)

Screenshot of demo macro

Screenshot of demo subroutine

How to use it

The demo macro is just a starting point, obviously. Here are a few tips on using this in your own macros, if you wish…

Set the window size by changing the two values in this function in the HTML variable:

function KMWindow() {
    return "420,380";

You can customize the appearance changes in the Javascript, and you could obviously do more than just color changes (font, font size, etc. I assume are all possible).

Once set up, how do you actually use it?

In your main macro, you need to copy everything from the main demo macro down to (but not including) the "For each" loop. Put it in a group for easy control, and somewhere near the start of your main macro. You also need to add the subroutine to your macro group.

Put your list of tasks into the instance_TheFullList variable in the first action. To make the grep step (as well as editing) easier, I store it as just a list of text. The next action then wraps each line in HTML code for a two-column table row. Column 1 is blank, to hold the checkmark, and column 2 is the task.

This is then inserted into the HTML code in the next step, which is the code that the Custom HTML Prompt action will display. The window is then centered and displayed, with all grayed-out items.

The rest of the demo macro just loops through the list with random delays and calls to the subroutine that does the work. Each call to the subroutine uses one of the tasks from the list, in order. In the subroutine, the matching row number for the received text is found in the table, and then edited to include the checkmark and change those cells to black. It also changes the current (next row) task to stand out visually.

Add a call to the subroutine wherever you need to show progress, and just insert the relevant line from the task list. You could duplicate the subroutine calls all in one batch, edit the text, then distribute to your other macros, or just add them as you need them.

What happens when things change?

If I move sections of the macro around, I just have to reorder the list of tasks to match the new order. If I delete a section, I just remove that task from the list. Add a new section? Add a task to the list and call the subroutine. And if I ever leave a subroutine call where it shouldn't be, it's obvious because the list suddenly won't be done in the right order.

This isn't a fully automatic solution, of course, but it's much simpler to keep current without having to manually edit dozens of Progress actions any time I edit the macro.



Dang it, I had only selected the one macro instead of both when posting originally. Both should now be in the download link.

Sorry about that!


This is very cool, Rob.

I made this little helper macro to get the names of all the subroutine calls:
Task list- Get list of tasks.kmmacros (2.2 KB) (See update below)

Macro image

With this, you can add or move around subroutine actions to your hearts content, then collect the list when you're done.

I have it currently displaying the results in a window for a quick spot check and manual copy/paste into the instance_TheFullList variable.
For the brave, this could be modified to automatically populate the variable, but that didn't seem worth the hassle to me.

1 Like

The helper macro I posted above only works if the subroutine calls are in the main block of the macro.

Here's an updated version that should find any nested calls as well:
Task list- Get list of tasks.kmmacros (2.1 KB)

Macro image

If anyone finds any other issues with this macro, please let me know!