KM8 [Possible Bug Report?] Using the Variables Collection in For Each


@peternlewis I was hoping to use the new variables collection to check different variables for a 0 or 1 value in order to more efficiently help with this macro, as opposed to manually repeating an If/Then action, and I noticed that it's the only collection in For Each that has a colon but doesn't have any fields for further specifying what you want:

I'm not sure if this is a bug and there's supposed to be an entry field after "The variables:" for narrowing down which variables you want it to check, or if the colon is a typo and this collection is meant only for iterating through every variable, with no way of narrowing the variables down. Personally, I'm hoping it's the former, as having a way to narrow down which variables are checked in this collection seems more useful to me than it being an all-or-nothing deal, but either way, this seems like something you might want to fix or clarify.

There should not be a colon. It includes all the variables. You can limit which ones you’re interested any way you like with an enclosed If Then Else action.

Noted, and excellent point. Thanks for the clarification!

1 Like

I'm afraid I'm having trouble getting this collection to work. If I try this:

It works as expected, assembling a list of all my variable names into NamesToPaste. However, if I try to restrict it to variables that only have "1" for their value (i.e. those that have been checked in a Prompt for User Input action) like this:

then the NameToPaste variable is empty, seeming to indicate that none of the variables matched the If Then Else test even though I can confirm in the Variables pane in preferences that there are exactly two variables which should match (i.e. that they have a value of 1). I'm probably just overlooking something obvious again, but could I trouble you to point out where I'm going wrong?

Here's the full macro I've got so far to make it easier to test yourself if necessary:

Paste Names via Checklist (Automated).kmmacros (5.1 KB)

get name of variable NameVariable

Will just return NameVariable.

And the first Execute AppleScript is equivalent to:

Assuming you are trying to list the values of the variables.

The second one fails because you are testing the variable "is 1", so that will list all the variables whose name is "1" (which is nothing, ever, since that is not a valid variable name).

Try something like this:

Keyboard Maestro Actions.kmactions (3.5 KB)

1 Like

Thanks a lot for providing a working example, Peter! Unfortunately, I’m now confused about KM variables, or at least about the way they interact with these different actions. It’s too late in my day for me to explain sufficiently right now, but I’ll try to do so soon in the hopes that I can clarify where my mental model (and ideally, other KM users’ similar mental models) is at odds with the way KM currently works, in the ultimate interest of hopefully making these actions more accessible.

If you want to use AppleScript, you can do the entire job there with basically one statement:

set kmNameList to name of every variable whose name starts with kmPrefix and value is ptyKMValue

Here’s the complete script.

AppleScript To Get List of Variable Names with Prefix and Value

property ptyScriptName : "Get List of KM Variable Names with Prefix and Value"
property ptyScriptVer : "1.0"
property ptyScriptDate : "2017-10-12"
property ptyScriptAuthor : "JMichaelTX"

  • Returns a list of KM Variable Names that:
      • Start with specified Prefix
      • Have a value of "1"

AUTHOR:    JMichaelTX

  • Local__ItemPrefix -- the prefix of the variable names
  • KM 8.0.3+
  • macOS 10.11.6+
property ptyKMValue : "1" -- required value of all KM Variables

set kmInst to system attribute "KMINSTANCE"

tell application "Keyboard Maestro Engine"
  set kmPrefix to getvariable "Local__ItemPrefix" instance kmInst
  set kmNameList to name of every variable whose name starts with kmPrefix and value is ptyKMValue
end tell

set AppleScript's text item delimiters to linefeed
return kmNameList as text

See complete macro here.

1 Like

Okay, so the long and short of it is: my mental model of how For Each works with the variables collection was inaccurate. When I used the If/Then action with it, I thought that it was testing each variable's value, but it turns out it is actually testing each variable's name. So when I tried this:

I thought I was testing each variable's value, like this:

but as @peternlewis said, it failed because I was actually testing each variable's name.
What I was lacking, which he correctly sussed out, was a way to test both the variable's name and value at the same time, something it seems can only be done in For Each with Filter with Value of Named Variable (which is not something I'd ever needed before and had no idea existed, let alone knew how to use). It still isn't intuitive to me that the variables collection in For Each tests each variable by name rather than by value, but at least I understand now how it works (or at least, I understand it better than I did before :sweat_smile:).

@peternlewis, might I suggest that the wiki's Variables Collection page be updated to explain this, since I imagine I won't be the only user who thinks that variables are being tested by value rather than name? Right now the wiki page only says "The Variables collection (v8+) lists all the Keyboard Maestro variables." which, in my opinion, does not clearly enough explain that it is strictly the variable's name that is being tested, and definitely doesn't explain how one might go about testing both a variable's name and value, or even just a variable's value, at the same time. Feel free to use anything from this thread for explanatory purposes if it helps!

Thanks for sharing this! I originally just resorted to AppleScript in my non-working version of the macro as a way of getting a variable’s name rather than its value (because I didn’t understand that For Each was already testing variable names), but this is a much more elegant solution. I’m still very much an AppleScript beginner, and the whose clause is not yet something my mind readily comes up with as a solution for use cases like this, so I really appreciate the reminder and lesson!

1 Like