So using your approach, how can I make sure that it always goes to the right group, in case I rename the group (e.g. _My New Tests), other than updating the LOCAL__XML variable, of course. If I want to "set and forget" that macro.
I'm thinking that maybe we can use AppleScript to first create a variable that gets the name of the group from the Group ID and then use that variable in the Local__XML variable?
Okay. If in future you rename the Group but want new Macros to go into that same Group you would just change the name of the Group in the prompt and the new Macro will still go into the same named group. You would not edit the XML again.
Yes, but again, I would like to "set and forget" that macro so basically I wouldn't even have that field for the Group name, because on my macro I will have some conditions that will automatically set the group based on the content. For example if the URL is set to something that starts with ~/ I know that this is a Finder path and it will go to a group called "Internal Links".
If it starts with https or http then it goes to a group called "External Links".
I'm aware that making this change only takes a few seconds, but if I can create a macro that will do all the work for me automatically based on the ID of the group, regardless of the name, why not?
So I guess that the AppleScript approach to gather the group's ID and save it as a variable seems like the only way?
Yes -- but why? Having two (or more) Groups with the same name is just making your life more difficult!
But let's say we're trying to make a macro for other people, who may well have duplicate group names. Assuming you could detect that problem and give them some way to choose which group they actually meant, I would
Change the group name in the XML template to something (almost certainly) unique
Import the macro
Move the macro from that uniquely named group to the target group
Delete the uniquely named group
So for a temp group call "My_Clever_Group_Name" (I'd actually use a spoofed UUID) the important bit of the AS would be:
tell application "Keyboard Maestro"
importMacros macroXML
move first macro of macro group "My_Clever_Group_Name" to macro group id "94B3E220-2AE1-4957-973A-8ADFC260E35D"
delete macro group "My_Clever_Group_Name"
end tell
How you'd get the target group when there are multiple groups of the same name will depend on how you are getting the initial data. If you're hard-coding the group then that's easy -- just replace the id in the above.
Of course. Don't forget that the Macro I uploaded was the most basic I could make it just to show the technique. You can customise it to do whatever you need.
This was just a test to see if KM would allow groups with the same name or not. I was trying to understand if having a certain name in the XML would make a difference or not, so for example if the XML is set to having the group name "Tests", but that group is not available anymore (if the ID was 1234, for example), but there's another "Tests" group with ID 5678, then the XML would be using the 5678 group as the destination, which is not desired. So yes, that was just a test. I don't have any groups with duplicate names.
That's why I think that having the XML set to using the right name and ID is ideal to avoid any potential issues. And I can just set and forget that macro, regardless of what name I give the group in the future.
Let's say I rename the group and forget to update the XML. Every time I create a new link it will be adding it to a new group with the old name, right? So now I have to go and move all those macros to the new group and delete the old group. If I am using KM to avoid extra work, then that approach is convoluted when I can have a macro that does all the work automatically based on the ID and the current name of the group based on that same ID. Hope it makes sense?
Yes, of course. And I'm always trying to find a way to minimize any extra clicks and work as much as I can, because it just adds up.
And your approach is not only super simple and useful, but it also showed me that there's so many possibilities when using XML, which can be used for other things.
I really appreciate you for that
tell application "Keyboard Maestro"
set newMacro to macro id "E3201D8B-D0BF-4214-A3B4-ED6039E49A7C"
end tell
I get this:
macro id E3201D8B-D0BF-4214-A3B4-ED6039E49A7C of macro group id FDC4407D-E1B2-4684-909A-CC0EC04C6423
I tried using macro group id, but then it doesn't work.
I can use the Search and Replace to just get the group ID, but I wonder if this is possible directly from the AS without adding the Search and Replace?
Maybe this is not the best approach, but it works, in case I can't do it directly with AS:
An action doesn't itself have a "group" identifier. An exported action does, so that it can be imported into a group with the same name as it was exported from (which makes sense for the intended use, if not for what we're doing here).
So if you are going @Zabobon's route and are worried about duplicate group names and/or future group name changes use my "temp group and move" method -- since the target group of the move statement is referenced by UUID it won't matter if you change the name later.
The joy of Zab's method, of course, is that you don't need to create your macro from scratch in the AS.
What are you actually trying to do? In the first snippet you're just setting a variable. Your editor outputs the result of the last statement it performed, so it is showing you the value you've just set newMacro to -- you can read that as "newMacro was set to the reference macro id... <etc>".
This has been a fascinating read; I've learned a bunch about Keyboard Maestro and duplicating macros programmatically that I didn't know going in—bookmarked!
With that said, this seems like a perfect problem to solve by using a SQLite database in Keyboard Maestro , as opposed to winding up with a hundreds or possibly thousands of macros, each containing just a couple commands, and the vast majority of which are identical.
The only downside I can think of right now is that you couldn't easily apply an icon to each macro, but it seems like the long-term management side would be much simpler—no need to worry about managing a huge number of macros, names and macro IDs are essentially irrelevant, and adding new functionality is as simple as adding a new record type to the database.
I may have to play around with this this weekend, just to see how it comes out :).
Always happy to know that my "weird" requests end up bringing some value to others haha
I don't know exactly what this means, because I'm not familiar with SQLite at all, but I don't mind having hundreds or even thousands of macros, as long as those are readily available when I press CMD+Space and start typing. I'm assuming that your solution would involve showing another window or something?
I believe that both approaches (AppleScript and the pure XML route have their pros and cons. With the XML it's pretty easy to add a specific icons to each type of link we create, so that's good. My only issue (which I totally understand if others don't see it that way) is that I really want to build a macro that allows me to just create it and never touch it again, even if for a few seconds to update a group name. That's why I was trying to get the group ID, so I could then get that group's name to update the XML in case the group name changes.
It would function in the same manner, basically. I'd see two hot keys, one of which creates a new entry, the other of which shows the list of everything you've ever created, selectable by typing. But as noted, the lack of icons is probably the main issue. Still, for me, it will be a good practice exercise, so I might see what I can come up with…and maybe I can figure out how to solve the icon issue, too :).
I doubt it'll replace your elegant solution, but I'm curious if I can make it work.
tell application "Keyboard Maestro"
set macroGroupID to (get name of macro group id "915AD2AD-5DE7-4775-82FF-DE02ED599FB3")
end tell
By doing this I can now have @Zabobon option while making sure that both the name and ID in the XML are correct. I will be working on it now and see if it works as expected
Ok, I'm happy to announce that the macro is done!
I would like to sincerely thank you all for your precious contribution, as usual.
I'm always learning a bit more along the way and that feels great!
Here's the semi-final version. Eventually I will be able to share the whole macro that includes the option to pick what kind of links it creates (internal or external) and maybe some other tweaks, but for now this is the base and it includes the Safari icon by default
I do have to pedantically point out that this doesn't solve one of the issues you raised -- having two groups with the same name. Yes, you've chosen a particular group name by UUID -- but the XML then tells KM to import into a group by name. Which of the two groups will KM choose?
My issue was not related to 2 groups having the exact same name.
I used that example of 2 identical names just to confirm that KM doesn't prevent us from having 2 or more groups with the same name, but I would never have that myself.
My main concern was always the fact that I can eventually rename the group and that would cause an issue with KM creating links in a group with the old name and forcing me to then move the macros to the new group manually and then deleting the group.
With my approach of saving the Group Name based on the ID and then updating the XML with the current Group Name, I'm 100% sure that regardless of the Group Name, it will always be updated. So the XML will always have the right UUID and the Group Name.
To answer your question, if someone uses this macro and has 2 or more groups with the same name, it seems that KM always imports to the topmost group. But again, this is not my personal case and if someone does in fact experience that, I'm sure they will notice it and make the necessary changes
At least for my workflow, this seems to be the best approach and I can definitely "set and forget" this macro once it's 100% done. I will share it then if someone else finds it useful.
Gotcha. And a good solution if you always want to import into that group.
If you want to have the option of using other groups you could always add another pop-up menu, defaulting to your usual group but listing all the groups as well. Something like the following changes should do it:
I'm actually trying to recreate Raycast's behavior where it knows that certain links are local / internal links for files and folders, and some are external to websites.
I will only have 2 groups, just to keep everything separated, even through Raycast puts everything together.
So my final macro will will automatically create the macro in the right group based on the beginning of the path so if a path starts with / or ~/ it means it's internal and will be sent here:
Otherwise, most likely will start with www, http or https, it will be sent here:
Adding more options with a dropdown menu would be unnecessary, at least for this workflow.
But I just learned something new that I can see myself using in other macros for sure and that is the option to use a variable's options as the dropdown menu. This can be extremely helpful when dealing with a list of options that is updated on a regular basis. Easier than typing all the options in that tiny text field.
How would I use that same AS you just used, but this time to add delimiters to a variable like this one, for example?
It would need a delimiter after the first 2 words, but not the last one, right?
The "raw" approach would be to use Search and Replace to replace all \n with |, but I'm sure it can be done via AS...?
I mean, either way I end up with an extra action, whether an AS or Search and Replace, but I'm curious if that is possible via AS?
Yes, A Few Favorites is not a way to access everything. It's for a few favorite things (a variety of them but just a few of each). The problem it solves is making it convenient to access routinely used apps, files, folders, email addresses, URLs.
It does make it easy to add to those lists. And does provide two interfaces. But it does play favorites.
For my particular workflow, if I really wanted a macro to be at the top of my list (which I never felt the need for that, because I just search for what I need at that particular moment), I would just add a character to the beginning of the macro's name, for example the = sign, because it doesn't even require any modifier. I do that sometimes for certain presets in Logic Pro.
But I never felt that need in KM or Raycast in 2 years or more of using both apps.
I'm sure other people's workflow may be different, of course, and having those tools is always better than having no tools
Yes -- if you have a "|" after the last one you'll end your prompt list with an "empty" item (not the end of the world, but a bit annoying).
S'n'R would be the sensible way when you have the items in a KM variable already -- no point wasting CPU cycles spinning up an AS instance in a KM macro for something that's easier to do in KM anyway! I did it in the AppleScript because:
We're already incurring the overhead of an AS script to get the macro group name
We don't have to mess around getting variables in to the AS
The results of get every macro group is an AppleScript list object, which needs to be cast to text before returning to KM
When you cast a list to text you can tell AS the delimiters to use between the list items (set AppleScript's text item delimiters...), making it easy to choose | and so produce the right format for KM
Oh, and AS doesn't have a simple S'n'R built in. This one's quite easy though -- make the text into a list and then cast the list back to text while using our | delimiters, like this: