How to create a macro that renames current selected macro? [SOLVED]

I have a macro that creates a script from my currently selected KM macro that is then available when I use Raycast. On all of those macros that are converted to Raycast scripts I add "(available via Raycast)" at the end of the macro's name like this:
image

On my macro that creates the script I would like it to start by checking if the macro's name contains that text at the end and if not, rename the macro and then continue running the macro to create the script.

You can use AppleScript to rename a macro. To rename the currently selected (or the first if multiple):

tell application "Keyboard Maestro"
	set theMacro to first item of (get selectedMacros)
	if name of macro id theMacro does not end with "(available via Raycast)" then
		set name of macro id theMacro to (name of macro id theMacro & " (available via Raycast)")
		return 1
	else
		return 0
	end if
end tell

Difficult to be sure without seeing your macro, but you can probably just drop that in as an AppleScript action. If you set that action to "Save results to a variable"

...you can then test the result -- if it is "1" then you renamed the macro and should continue running the script, if it is "0" it was already named so needn't be processed.

Do beware in case renaming your macro affects the rest of your processing macro!

1 Like

Thank you so much. That worked like a charm.
I just added it to the beginning of the macro that creates the script, so there's no need to save it as a variable.

Looking at the script, and me being a newbie when it comes to AS, it still amazes me that sometimes the script mimics how we speak. Very interesting language.

As another newbie to AppleScript, I find this aspect of it to be a mixed blessing. It helps me figure out what's going on when I read a script, but it can totally mess me up when trying to figure out how to actually say what I want the script to do.

1 Like

I very much agree AppleScript can be very difficult that way.
For example you would think you could just change "first" to "every" and it would work fine from reading it (or "all items").

set theMacro to first item of (get selectedMacros)

set theMacro to every item of (get selectedMacros)

For what it is worth if you wanted to change every selected macro you can do it like this.

(Add Text at End for All Selected Macros)
tell application "Keyboard Maestro"
  set selectedMacrosList to get selectedMacros
  repeat with theMacro in selectedMacrosList
    set macroName to name of macro id theMacro
    if macroName does not end with "(available via Raycast)" then
      set name of macro id theMacro to (macroName & " (available via Raycast)")
    end if
  end repeat
end tell

If you wanted to toggle that from every selected macro you could do it like this.

(Toggle Text at End for All Selected Macros)
tell application "Keyboard Maestro"
  set selectedMacrosList to get selectedMacros
  repeat with theMacro in selectedMacrosList
    set macroName to name of macro id theMacro
    set searchText to " (available via Raycast)"
    
    if macroName ends with searchText then
      -- Remove the text if it is present
      set name of macro id theMacro to text 1 thru ((length of macroName) - (length of searchText)) of macroName
    else
      -- Add the text if it is not present
      set name of macro id theMacro to (macroName & searchText)
    end if
  end repeat
end tell

And to round it out if you wanted the text at the begnining of the macro names.

(Toggle Text at Start for All Selected Macros)
tell application "Keyboard Maestro"
  set selectedMacrosList to get selectedMacros
  set searchText to "(available via Raycast) " -- Now at the beginning
  
  repeat with theMacro in selectedMacrosList
    set macroName to name of macro id theMacro
    
    if macroName starts with searchText then
      -- Remove the text if it is already at the beginning
      set name of macro id theMacro to text ((length of searchText) + 1) thru -1 of macroName
    else
      -- Add the text at the beginning if it’s not already there
      set name of macro id theMacro to (searchText & macroName)
    end if
  end repeat
end tell

A of couple macros that you can use your own text via a user prompt to the start and end several macros.

(With User Prompt)

**AAA - Automation - Keyboard Maestro Macros (v11.0.3)

**AAA - Automation - Keyboard Maestro Macros.kmmacros (62 KB)


And here you can replace any text you want in the selected macros.

(Search and Replace)

Replace Text in Selected Macros

Text Replacement - Replace Text for All Selected Macros with Prompt Macro (v11.0.3)

Text Replacement - Replace Text for All Selected Macros with Prompt.kmmacros (32 KB)


Okay you have me on a roll, I thought I was done after the first two macros. It got me thinking I often sort my macros with the hidden numbers. This macro will add numbers to the start of the selected macros in Keyboard Maestro editor so if you don't want them to show up alphabetically in the conflict pallet you can sort by some other methode like date created, date modified, or date used to then quickly add numbers for them to show up in that order in the conflict pallet (I absolutely love Keyboard Maestro's conflict pallet so much better than how you had to set that up back in the day in QuicKeys, thank you Peter!)

(Add Sequential Numbering at the Start of Each Macro in Keyboard Maestro Current Sort Order)

Add Numbers In Current Sort Order

Text Replacement - Add Sequential Numbering at the Start of Each Macro in Keyboard Maestro Current Sort Order.kmmacros (30 KB)


This one was a bit more of a bear but what I prefer and do quite often for the conflict pallet. I like to use the numbers rather than the letters if I can to quickly get to a macro on the conflict pallet. This macro makes that pretty quick to make. Also note that there is logic in the numbering if there is less than 11 selected.

(Add Numbers to Name 0 for 10th if Only 10)

Zero for Tenth if Only 10

Text Replacement - Add Sequential Numbering at the Start of Each Macro in Keyboard Maestro Current Sort Order and Add Numbers in Conflict Pallet Display Name (If Just 10 the 10th is "0").kmmacros (32 KB)


If you don't like the 10th one being a zero if there is only 10 then here you go it will always add them. Also note that there is logic in the numbering if there is less than 10 selected.

(Add a Number in the Name and Start 10 and Not 0 For 10th)

Add a Number in the Name and Start 10 and Not 0 For 10th

Text Replacement - Add Sequential Numbering at the Start of Each Macro in Keyboard Maestro Current Sort Order and Add Numbers in Conflict Pallet Display Name.kmmacros (32 KB)


This macro allows you to remove numbers at the start of selected macros if you want to start over and renumber them in a different order. Use it in conjunction with "Add Sequential Numbering at the start of Each Macro"

Remove Sequential Numbering at the Start of Each Macro in Keyboard Maestro Macro

02)Text Replacement - (2) Remove Sequential Numbering at the Start of Each Macro in Keyboard Maestro.kmmacros (30 KB)

If you have new macros you have made like this one and want to quickly insert another action in the macro pallet quickly this is a great way to do it. Maybe when I am done I will compile all of these into one download.

Increment or Decrement All Numbers in Selected Macros By One

Increase All Numbers in Selected Macros By 1

**AAA - Automation - Keyboard Maestro Macros.kmmacros (63 KB)

If you want to keep your numbers safe if you have a sequential list and just add text to the start.

Toggle Text at Start for All Selected Macros with Prompt (Sequential Number Safe)

Toggle Text at Start for All Selected Macros with Prompt (Sequential Number Safe)

12)Text Replacement - (12) Toggle Text at Start for All Selected Macros with Prompt (Sequential Number Safe).kmmacros (32 KB)

Thanks for your AppleScript post @Nige_S

A programmer friend of mine described AppleScript as a "read-only language," and similarly, JavaScript as a "write-only language," due to the variety of ways to do things, many of them not necessarily clear when looking at the words.

:slight_smile:

-rob.

1 Like

I don't understand what you're not understanding here.

get selectedMacros returns a list. every item returns a list. So it is, quite literally, "set the variable theMacro to the list of every item of the list of selected macros".

Perhaps literals show it better:

set theList to {1, 2, 3}
set anotherList to every item of theList
return anotherList
--> {1,2,3}

IMO, the best way to get from "what I want" to an AppleScript is to write out "what I want" as pseudocode -- but I fully accept that may be because I write pseudocode like AppleScript!

I think I was just more agreeing with @August that you might just read the text and think you can simply change a word like I did and you will get the results you want. You live and breath in this stuff so it might just be second nature to you at this point. Thank you for your explantaion, that was kind of you to take the time to do that.

That actually was helpful to see the literals though, so thanks for that. My appoligies I wasn't more clear.

You can (within reason) and, just as with English or whatever, the word you choose changes the meaning -- the result you get. There are also "grammar rules" -- in this case, plurality.

first item gets a single item. You can change first to other words and get what you'd expect from "natural language". Using letters this time, so you can see there's no funny business:

set theList to {"a", "b", "c"}
first item of theList
--> "a"
last item of theList
--> "c"
middle item of theList
--> "b"
second item of theList
--> "b"

every item is plural, just like it would be if someone stopped you at the shop and asked you to list every item in your trolley. That's why you get a list back (AS's version of an array), and all you are doing is making a copy.

@griffman's programmer friend is kind-of right. AppleScript is a readable language, and most people can get at least a general sense of what an AS does (although better scripters than me often use "advanced" constructs that can obfuscate). And, as with any language, the more you actively read the better you're able to write.

Thank you for all of that and the explanation that does make sense.

Speaking of English, I have learned a couple of new words today from you. For this post, "obfuscate," and for another, "necroing." :grin:

Does anyone know how to rename macro groups? It doesn't look like you can get the names of the selected macro groups, though I have been able to do this with selected macros.

Replace Text for All Selected Macros Groups with Prompt Macro

04)Text Replacement - (4) Replace Text for All Selected Macros Groups with Prompt.kmmacros (32 KB)

This

tell application "Keyboard Maestro"
	set selectedGroups to (selected of macro group)
end tell

...doesn't work. Try it in Script Editor and you'll get an error.

selected is a property of a Macro Group, not a list of the currently selected Groups. So if you want to go this route you'll need to get "every macro group for which the selected property is true", or:

tell application "Keyboard Maestro"
	set selectedGroups to (every macro group whose selected is true)
end tell

(Also neatly demonstrating the "englishness" of AS, going almost directly from pseudocode to code :wink: )

Note the difference between that and

tell application "Keyboard Maestro"
	set selectedGroups to selectedMacros
end tell

The first will return the selected Groups even when a macro is selected in the UI, but does so by checking the properties of every Group in KM to find matches -- and it returns a list of references. The second directly returns either selected Groups or selected macros, depending on the active selection, without a search -- and returns a list of UUIDs.

1 Like

Thanks for the explantation, I have been able to round out the macros with a do to all and do to selected. Much appreceated, this will speed things up nicely for me in the future. Hopefully helpful to someone else also.

Any ideas what I am doing wrong here with this AppleScript? The picture hopefully shows what I want before it runs and what I am after when it is done.

Pad Every Number in Parenthesis with a Zero Macro

04)WIP Text Replacement - (05) Pad Every Number in Parenthesis with a Zero.kmmacros (43 KB)

tell application "Keyboard Maestro"
  set selectedMacrosList to get selectedMacros
  
  repeat with theMacro in selectedMacrosList
    set macroName to name of macro id theMacro
    set newMacroName to my addLeadingZeroToSingleDigitNumbers(macroName)
    
    -- Update macro name if changed
    if newMacroName is not macroName then
      set name of macro id theMacro to newMacroName
    end if
  end repeat
end tell

-- Function to add leading zero to single-digit numbers in parentheses
on addLeadingZeroToSingleDigitNumbers(originalText)
  set newText to originalText
  set AppleScript's text item delimiters to "("
  set textParts to text items of newText
  set newTextItems to {}
  
  repeat with part in textParts
    -- Check if this part contains a closing parenthesis
    if ")" is in part then
      set AppleScript's text item delimiters to ")"
      set innerParts to text items of part
      -- Ensure we have at least one number
      set num to item 1 of innerParts
      -- Initialize rest to an empty string
      set rest to ""
      
      -- Handle cases where there might be text after ")"
      if (count of innerParts) > 1 then
        set rest to item 2 of innerParts
      end if
      
      -- Check if num is a single-digit number (1-9)
      if num is in {"1", "2", "3", "4", "5", "6", "7", "8", "9"} then
        set num to "0" & num -- Add leading zero
      end if
      
      -- Reassemble the modified part
      set end of newTextItems to "(" & num & ")" & rest
    else
      -- If there's no closing parenthesis, keep it unchanged
      set end of newTextItems to part
    end if
  end repeat
  
  -- Reconstruct the full text
  set AppleScript's text item delimiters to ""
  set newText to newTextItems as string
  set AppleScript's text item delimiters to {""} -- Reset
  
  return newText
end addLeadingZeroToSingleDigitNumbers

Update: I sereously need to ask these questions sooner because I seem to try for hours at times for something and then find the answer shortly after I ask.

The following works.

tell application "Keyboard Maestro"
  -- Check for selected macros or groups
  set selectedMacrosList to get selectedMacros
  set selectedGroups to (every macro group whose selected is true)
  
  -- If macros are selected, process those
  if selectedMacrosList is not {} then
    repeat with theMacro in selectedMacrosList
      set macroName to name of macro id theMacro
      
      -- Use shell command to add leading zeros to single digits in parentheses
      set cmd to "echo " & quoted form of macroName & " | perl -pe 's/\\((\\d)\\)/(0$1)/g'"
      try
        set newMacroName to do shell script cmd
        if newMacroName ≠ macroName then
          set name of macro id theMacro to newMacroName
        end if
      end try
    end repeat
  else if selectedGroups is not {} then
    -- If groups are selected, process those
    repeat with theGroup in selectedGroups
      set groupName to name of theGroup
      
      -- Use shell command to add leading zeros to single digits in parentheses
      set cmd to "echo " & quoted form of groupName & " | perl -pe 's/\\((\\d)\\)/(0$1)/g'"
      try
        set newGroupName to do shell script cmd
        if newGroupName ≠ groupName then
          set name of theGroup to newGroupName
        end if
      end try
    end repeat
  end if
end tell

I can confirm this: That is indeed how it often works. :grin:

One issue is that you aren't looking at the tools available to you. If you want to write a generic "padding" routine you could shell out and use perl or similar or, to save the cost of that, you could play with text item delimiters. But...

  • You're AppleScripting KM -- obviously, that means KM is available
  • KM Engine's AppleScript dictionary includes the search verb
search v : Search a string for a string and replace occurances with another string, returning the resulting string.
search text : the input string.
for text : the search string string.
replace text : the replacement string.
[regex boolean] : using regular expressions (default false).
...

Notice that it allows us to use regex -- not available in vanilla AS. So we can easily find, and capture, any single digit enclosed in parentheses: \((\d)\) -- \( for the opening parentheses (escaped as per normal regex rules), ( to start the capture group, \d for one digit, ) to close the capture group, \) for the closing parentheses.

It gets a bit funky because the regex escape \ is also the AS escape character in strings, so you have to escape the escapes... But try this in Script Editor:

set oldName to "(1) Some (02) Text 3) to (4 Alter (5)"

tell application "Keyboard Maestro Engine"
	set newName to search oldName for "\\((\\d)\\)" replace "(0$1)" with regex
end tell

return newName

--> "(01) Some (02) Text 3) to (4 Alter (05)"

So, ignoring all the stuff about is anything selected and if so what -- which you seem to have nailed -- and just demoing on a Macro Group name:

tell application "Keyboard Maestro"
	repeat with eachMacro in (get selection)
		set theName to name of eachMacro
		tell application "Keyboard Maestro Engine"
			set theName to search theName for "\\((\\d)\\)" replace "(0$1)" with regex
		end tell
		set name of eachMacro to theName
	end repeat
end tell

...turns this:

image

...into this:

image

1 Like

Haha, it's good to know I am not the only one.

Wow, that is much more concise and faster; very impressed. Good to know how to call on Keyboard Maestro's RegEx in AppleScript rather than using Shell. It is kind of interesting the methods needed to employ RegEx in AppleScript. I like the calling on Keyboard Maestro for that. Thanks for the much better AppleScript. I have added that first AppleScript to my reference macros for the future. Now let's just hope I remember to check it.

I was curious, so I threw both into ChatGPT, and it gave this comparison. Very well done!

So, I was hesitant to ask and spent a couple of hours on this. It seems like from everything I could tell that I can't return if the selection is macros or macro groups. I tried to consolidate the macros to change the name based on whether a macro was selected or a macro group was selected, and the closest thing I could get was to rename the macro, but it also always returns that a macro group is selected when you select macros so the macro group would get renamed as well. If you have any idea how to do that, I would love to know. I tried everything I could think of, and searched for quite some time.

The macros have built are fine. I just don't like that. There's so many of them if I can consolidate rename select macro group and rename selected macros.

I'm sure you can see the obvious mistake. Anything using a call to KM is going to have much worse "cross-macOS compatibility" -- at least until we can persuade every Mac user to buy a copy of KM :wink:

The item will have a class, eg:

tell application "Keyboard Maestro"
	class of item 1 of (get selection)
end tell
--> macro group
1 Like

Or persuade Apple to make Peter an offer he can't refuse. (A carrot offer, not a stick offer.)

I should have pointed that out, I thought it was pretty funny and made me laugh that AI also felt like Keyboard Maestro should be standard on every macOS.

Thank you for this, I will play around with it and see what I can get working for selected Macros or Macro groups and renaming them with one macro instead of two.