Using Variables Prepend and Append

KM 9.0.2 has new Prepend and Append variables, Cool​:+1:t2: I haven't used variables Not Cool :-1:t2:. This looks like a spot to jump in :astonished:!

I've set up a bunch-o-marcos to Prepend/Append the numbers 1-20 that I use on file names to sequence them within folders when they are sorted by name. They are simply UI actions that types return, up or down arrows, numbers, etc. Gets the job done nicely. Seems like these new variables would do the job more eloquently.

I know you have to declare a variable before using it and some characters are reserved and can't be used and that's about it. Not enough to get anything done.

Currently I have around forty macros (~20 to prepend and ~20 to append) which makes for a long list to scan and pick from.

For a first toe in the water I'd like to replace these UI driven macros with variables to do the same thing.

What would be nice but is way too scripty, which if written for me wouldn't likely help me learn so it goes on the not now list, would be for the macro to evaluate the file names in the current folder and add a prepend or append in sequence with the existing files. That way it could be a single macro to get the job done. I suppose a folder action that did that for any file added would be the best way to go but this is just thinking out loud and not something to follow up on anytime soon.

Thanks in advance for any using variables 101 support :smile:.

Good for you for wanting to jump in deeper!

I'm trying to figure out the best way to help you with this. There's so many different things that you could do.

Let me try this, to see where we're at. This example doesn't do what you need, not yet. But it's probably the best way to do what you want (once it's complete), so I thought I'd start with this.

Look at this and see if you can figure out what it does. By the way, I'm using "Append Variable" like you mentioned.

Oh, and if you make this macro yourself (which is a good idea), it probably won't produce any result unless you select some files in a Finder window first.

2 Likes

You are very noble for wanting to learn and for not having answers handed to you on a platter. But we don't expect knighthood-level nobility here, so you can always ask for help. Based on what you described, it sounds very likely that a single macro could do the job.

DT provided you with a tip that might help you get started, but the way I'm interpreting your question I think you're doing something different with your macros. Are you willing to show one of your macros?

2 Likes

Thanks Dan!

I made, tested, and see what it does. Somehow this acquired the POSIX path to the file and the Display Text action displayed that path in a dialog that popped up.

I looked up (https://en.wikibooks.org/wiki/AppleScript_Programming/Aliases_and_paths) to be clear about what kind of path is being acquired as I’ve seen lots of references for POSIX pathways with a few references to HFS pathways.

“Notice that in HFS path names, a colon ":", is used as a separator, and in POSIX path names, a forward slash "/" is used as a separator. The other major difference is that in HFS path names, the path name begins with the name of the volume and in POSIX path names, the startup volume doesn't need to be named, only other volumes need to be named.”

Slashes w/o volume reference=POSIX :white_check_mark:

The included pic below is my guessing at what’s happening to clearly display what I don’t understand so you can hopefully fill in the needed missing pieces.

1 Like

Excellent homework! And I'm thrilled with your questions, because it shows me we started in the right place. :smile:

[EDIT] I've just finished typing this, and it makes be realize how may topics this covers. And some of these topics will either totally make sense, or they'll blow your mind. And it's OK if they blow your mind - you won't be the first person to have trouble understanding these concepts.

So be patient with yourself, because if you can end up really understand these concepts, then you've actually passed the biggest hurdle you'll have to going forward.

Paths

Good work on HFS vs. POSIX paths. Fortunately, as far as I know, you only need to deal with POSIX paths, which are very similar to Windows paths, except the Mac uses slashes, and Windows uses backslashes. So in KM, we just usually talk about them being "paths".

In Finder, if you right-click on a file, then hold down the Option key, the menu changes and it has an item to copy the file as a pathname, and you get a POSIX path. Most people don't even know about HFS paths.

Variables

You never have to "define" them first, like you do with lots of programming languages. Just start using one. Of course, if you want it to contain a value, then you need to put something in it. However:

"Normal" KM variables keep their values even when the macro finishes running. If you go to "Keyboard Maestro->Preferences" and click on the "Variables" tab, you'll probably see some "normal" (aka "global") variables there.

You can name variables almost anything you want. Check out the Wiki for the rules.

But: Variables that start with "Local" only exist while the macro is running. At the start of the macro, they're empty. And they automatically get deleted when the macro ends. That's why I used variable names that start with "Local". Well, I actually use "Local_" (with an underscore), but that's just a personal preference.

Variables that start with "Instance" are basically the same as "Local", but for now the difference isn't relevant, until you start working with what we like to call "sub-macros".

So: Use variable names that start with "Local" until you have a reason not to.

Your questions:

Local_Path

Aside from the "Local" as I mentioned above, it's just a name that made sense to me.

As I mentioned earlier, you don't have to define variables beforehand, so this isn't technically a case of me defining the variable. But since it gets a new value each time through the loop, I could understand why you might think of it as "defining a variable", but again, you don't need to define them.

Local_SelectedPaths:

I chose this name because it's where I'm putting all the paths you had selected in Finder.

Append Variable action:

Whatever I put in the text box will be appended to the end of the variable. So you could read that as "Append what's in the text box to the variable Local_SelectedPaths".

Try this: Add this "Prompt for User Input" action:

Every time the loop repeats (make sure you've selected more than one file in Finder), you can see the value changing.

If you click the "Gear" icon in the "Append Variable" action, you can change it to "Prepend" or "Set Variable". The former puts the text in front of anything already in the variable, and "Set Variable" replaces whatever is in the variable with the data in the text box. Try it to see what happens.

%Variable%Local_Path%

This is how you get the value from the variable, when you're in a text box. You ask why the % in the middle, and my answer is, because that's what the Wiki or Help says to do. :smile:

This is a concept that's hard for some people to grasp, so let me know if this ends up making sense or not.

"This suggest that..."

Right!

"How did the local path get acquired..."

I used the action "For each Path in Finder Selection".

"For each [variable name] in these collections:

A "collection" is exactly that. A collection of things. This action "iterates" through each item in the collection. Each time it loops, the variable "Local_Path" contains the next item in the collection.

"The Finder's selection"

In this case, the "collection" is a collection of each file selected in Finder. There's a bunch of "collections" you can chose from.

"execute the following actions"

This is what gets executed for each item in the collection. In this case, it's for the path of each selected file in Finder.


I'm sure you have more questions. Mess around with this and see what you can figure out. You can't hurt anything, unless you add a "Delete File" action, or something like that. :open_mouth:

Let me know how you're doing.

4 Likes

@BernSh, I think @DanThomas has answered all of your questions, but I want to focus on one question because it is such a fundamental part of KM:

First, there is no such thing as a "special" variable, or variable name.
Anywhere a KM Action requires a KM Variable, you can enter any name you like (even though often KM will provide a default name), as long as it conforms to a simple rule:

Variable Naming Rule

  • Variable names must start with a letter, and then can contain letters, numbers, spaces, or underscores.
  • Variable names are case insensitive, but their case is remembered.
  • Variable names should not include a function or operator name with spaces around it
    *(eg “ MOD ” , so “A MOD B” would not be a valid variable, although “MODULE” would be fine).

See Variables in the KM Wiki for details.

Please read the above article carefully, and take note of the Variable Scopes:
(there is no such thing as a "normal" variable)

  • Global
  • Local
  • Instance

In general, it is best to use Local Variables unless you have a good reason to use one of the other types. I like to use "Local__" (with two underscores) to denote "Local" variable because if you need to display this Variable in a Prompt, then the "Local__" will NOT be shown.

1 Like

Thanks @DanThomas your post and explanation cleared up multiple questions for me after reading through the Wiki and multiple threads. I have usually used %Variable% when setting a variable but only just yesterday discovered I didn't need to do that to set the variable, I took it out of default values in user input dialog boxes only to see that it didn't give the value so your clarification makes a lot of sense that it is only needed to pull values from a variable.

In the attached image %Variable% is not ever needed if I understand right though it doesn't change the results at all.

image

Always the same as this.

image

That is correct - BUT since KM has things called tokens, for example %SafariURL%, leaving out the %Variable% means it can be difficult to easily distinguish between variables and tokens.

So - if you created a variable called %HTMLLResult% you might then easily confuse it with KM's token called %HTMLResult%.

Most of the experienced KM users now recommend that you never leave out %Variable% so that then there is no chance of confusing

%HTMLResult% with %Variable%HTMLLResult%

It may seem a small thing but when your macros get complicated it can save hours of troubleshooting!!

Thank you that is just what I was looking for and why I asked. I will put them all back. I will read into tokens more, I have come across them multiple times but not wrapped my head around them.

To be certain in the example above if you created a variable with the name %HTMLResult% or %SafariURL% would it call on the token or the variable? My guess would be first the token and then if a variable exists with the same name it would call on that which is why it is confusing.

Reading about Tokens now.

https://wiki.keyboardmaestro.com/manual/Tokens?s[]=tokens

That would be my guess, too, but to be honest I’ve never tried it so I don’t know and as I’m away from my Mac I can’t try it out. You could try it yourself or perhaps wait for someone who knows for sure to chime in.

Okay it looks like that is the case that Keyboard Maestro uses the token first if you don't specify. That is logical since it seems you never define a token with %token%.

Testing Which is Has Priority Tokens or Variables When Not Specified.kmmacros (1.8 KB)

This is also another good reason I will use lower camel case for all my variables per @ccstone recent suggestion. It looks like all tokens use upper camel case. Thanks a bunch for the clarification and help.

I also just tested that tokens have to use camel case and they do. What is interesting is that the variable doesn't need to match the case. I even removed all my global variables and ran this with lower camel case and the token still didn't read. I just wanted to be sure that the global variable wasn't taking precedence.

Testing if Tokens Must Use Upper Camel Case (They Do).kmmacros (1.8 KB)

KM’s tokens are built-in and their names are case-sensitive. This is another reason to never drop %Variable% because if you use %safariURL% hoping to access the KM token in actual fact you will be referencing a variable whose value will be empty initially which of course will stop your macro giving you the intended behaviour. You might not notice the problem unless you develop the habit of having %Variable% in front of all your variables.

Furthermore, when you get to using local and instance variables you need to ensure that their names begin with Local and Instance respectively (case sensitive).

1 Like

Hey @skillet,

I'm one of those that @tiffle mentions.

Never, never, NEVER leave off the %Variable% prefix of a tokenized variable.

Peter made a mistake when he allowed %myVariable% to alias %Variable%myVariable%.

This has confused users for years, and I would like to see him fix it – but the convention has been around too long and would likely break too many things if changed.

See. You shouldn't have to guess or test to find this out...

Having a rigid convention for what is a variable and what is a text-token allows the user to tell at a glance which is which and saves immense confusion in construction and debugging.

Depending upon what you're doing it may be a good idea to customize your global variables for a given macro.

So, you have a macro “Parse Google Chrome Selection” – your global variables might be:

g_pgcs_MyVariableName (“g_” for global)

Or you can assume the global, since neither “local” nor “instance” are used.

pgcs_MyVariableName

This convention makes all of your macro's global variable sort together in the Keyboard Maestro Editor's Preferences ⇢ Variable Panel, and that can be very useful when debugging.

I think it was @JMichaelTX who came up with the DND_YourVariableName prefix for DO NOT DELETE.

And this can be very handy when scriptomatically purging unneeded variables, as I do with some frequency.

I have some variables that are pinned in my script by name, and then a class of variables that are DND_, and of course the class of ENV_ variables that are not to be deleted.

<end of soapbox>

-Chris

1 Like

Thanks @ccstone that is helpful and appreciated that you weighed in. I was still leaning towards not adding %Variable% since I am going to always use lower camel case and tokens always use upper camel case but I will trust you guys and make sure they are always in there. I didn't realize that not having %Variable% was actually an alias and might potentially slow things down if there is a lot of them in a macro like I have.

I am trying to figure out ENV_ that is new to me as well. Create a PATH Environment Variable for Keyboard Maestro and Add /usr/local/bin to the Default Path - #2 by ccstone

It seems odd that tokens aren't prefixed with %Token% %Token%FrontBrowserURL%

I am doing this more often as well and it seems like good practice to make your macros so they create the global variable and not get stuck on trying to find a variable that doesn't exist. I realize that won't help if your macro is trying to recall a previously stored value from a macro that was run at another time or day. Plus Keyboard Maestro warns you what variable was missing you you can always manually create it. I guess DND_ is for things that needs the stored Global value to be there otherwise I would imagine it doesn't much matter.

I love the advice and suggestions they are so helpful and no doubt will save me a lot of heartache!

When you're perusing code you'd be surprised how the eye can be fooled by something like this:

%thisIsAnExample%
%ThisIsNotAnExample%

I generally use lower camel case myself, but it depends.

local_ThisIsAnExample
instance_ThisIsAnExample
vip_ThisIsAnExample

In cases like this and when I prefix variable names for identification I usually leave the meat of the variable name in upper camel case.

-Chris

1 Like

You are absolutely right, I'm making it a habit to include %Variable% in my variables. Thankfully it shouldn't be too hard since I didn't know you could go without it until this week. Thanks for your other examples, always nice to see what experienced coders do.

1 Like