Native macOS Text Replacement [adding records]

Insert - Text Replacement.kmmacros (21.6 KB)

Hi Guys,

I Would like to skip the user interface when I insert a text to replace. In other words, I'd like to accelerate the processes, because, as you can see on this image, I add lot of words there, very often.

20

Basically, when I type a word wrong, I select it and activate the macro that asks me to correct this word to insert in the text substitution of the system preferences.

Would anyone have a suggestion to shorten or speed up this macro, like via AppleScript, add directly into plist file, whatever.

Thanks :grin:

Are you using the native macOS text replacements because you need the iOS sync?

If not, then my first recommendation is to try Tyipnator, which currently is on discount ($5) at Bundlehunt.

A KM macro for the macOS text replacements is certainly doable, but probably not without UI scripting.

1 Like

Yes, Tom, I need integration with iOS. :grimacing:

As a starter, here a quick script that lets you create a new entry in the macOS text replacements:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application id "com.apple.systempreferences"
  reveal anchor "Text" of pane id "com.apple.preference.keyboard"
  activate
end tell

tell application id "com.apple.systemevents"
  tell application process "System Preferences"
    tell window "Keyboard"
      tell tab group 1
        tell group 1
          tell button 1
            click
          end tell
        end tell
      end tell
    end tell
  end tell
end tell

You can run the script from KM (Execute AppleScript action) or Script Editor, or whatever.

Obviously, there is still work to do (e.g. we have to bring the selected word into the field), but it should give you a rough idea how it can be done.

I don’t have much time at the moment, but probably later today I can complete the script/macro.

I tried your script and it speeded up my macro. As you said, I had to do some adjustments out of applescript. Thanks, Tom!

Yes, as a rule of thumb, I would use actions like Click at Coordinates or Find Image only if there really is no other way.

Here a more complete version:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

set theWord to the clipboard as text

tell application id "com.apple.systempreferences"
  reveal anchor "Text" of pane id "com.apple.preference.keyboard"
  activate
end tell

tell application id "com.apple.systemevents"
  tell application process "System Preferences"
    tell window "Keyboard"
      tell tab group 1
        tell group 1
          tell button 1
            click
            --delay 0.5
          end tell
        end tell
        tell scroll area 1
          tell table 1
            tell row -1
              tell UI element 1
                tell text field 1
                  set value to theWord
                  --confirm
                end tell
              end tell
              tell UI element 2
                tell text field 1
                  set value to theWord
                  set focused to true
                end tell
              end tell
            end tell
          end tell
        end tell
      end tell
    end tell
  end tell
end tell

And as macro:


Selection to macOS Text Replacement <6E45 200226T164835>.kmmacros (3.1 KB)

  1. Make sure macro and macro group are enabled
  2. Set the desired hotkey trigger
  3. Select a word in any text app (no need to copy)
  4. Launch macro via hotkey
    • A new entry with the selected word should be created in macOS Text Replacements
    • The Replacement field should be prepopulated with the same word and focused for editing
  5. Edit the Replacement word and press Return

Of course, you can change the input method to your needs (I have seen you have used a User Prompt action in your original macro). The word must just be on the system clipboard, when the script starts.

If the script doesn’t work for you, then we probably have to add some delays in the script.

Tested from within TextEdit on macOS 10.15.3, KM 9.0.5.


Edit/Update:

  • Removed an unnecessary confirm
2 Likes

wowww... amazing! Thank you very much, Tom!

I'm trying to do something very similar to what @alex.sanches was doing last February. I want to use an AppleScript to update a specific Text Replacement that contains the current date that I'll use across multiple (iOS) devices spanning the Apple ecosystem. I have leveraged the script that @Tom shared with a slight twist to update a Keyboard/Text Replacement on my Mac and allow it to propagate - I'll use Keyboard Maestro to scheduled the updates for just after midnight.

This script makes the change on a positional basis (i.e., it updates the value field of the first name:value key pair, but I can't get the change to stick. When System Preferences closes, the value reverts back to what it was before I ran the script.

Does anybody have a suggestion for how I can "save" the System Preferences/General/Keyboard/Text Replacement modification?

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

-- get the current date into today
set today to short date string of (current date)
set [_month, _day, _year] to [month, day, year] of date today

-- format today so it will look like YYYY-MM-DD
set _day to _day * 1 --> 3
set _day to text -1 thru -2 of ("0" & _day) --> "03"
set _month to _month * 1 --> 3
set _month to text -1 thru -2 of ("0" & _month) --> "03"
set _year to _year * 1 --> 5
set _year to text -1 thru -4 of ("0" & _year)
set the text item delimiters to "-"
set today to {_year, _month, _day} as string
set fullDateToday to today as string

-- swap out the "With" text field in the first value row of System Preferences/Keyboard/Text
tell application id "com.apple.systempreferences"
	reveal anchor "Text" of pane id "com.apple.preference.keyboard"
	activate
end tell

tell application id "com.apple.systemevents"
	tell application process "System Preferences"
		tell window "Keyboard"
			tell tab group 1
				tell scroll area 1
					tell table 1
						tell row 1
							tell UI element 2
								set value of text field 1 to today as text
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
	end tell
end tell

I plan to refactor and do a more deliberate match of names & variables after I get the MVP going. Thanks in advance for any direction you can give me on how to make the change stick.

John G

I figured it out and it's working like a champ with Keyboard Maestro. My AppleScript is probably pretty rough, but it's doing the trick as a minimum viable product - I'll tweak it as I go. Posting here in case it helps anybody else.

PS - the trick to making the changes stick was to treat it a bit more like I was sitting in the user's chair and including the following code (shout out to the AppleScript-Users mailing list):

set focused to true
keystroke today -- today is a variable that contains a formatted date
keystroke return

Here's the final AppleScript:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

-- get the current date into today
set today to short date string of (current date)
set [_month, _day, _year] to [month, day, year] of date today

-- format today so it will look like YYYY-MM-DD
set _day to _day * 1 --> 3
set _day to text -1 thru -2 of ("0" & _day) --> "03"
set _month to _month * 1 --> 3
set _month to text -1 thru -2 of ("0" & _month) --> "03"
set _year to _year * 1 --> 5
set _year to text -1 thru -4 of ("0" & _year)
set the text item delimiters to "-"
set today to {_year, _month, _day} as string
set fullDateToday to today as string

-- swap out the "With" text field in the first value row of System Preferences/Keyboard/Text
tell application id "com.apple.systempreferences"
	reveal anchor "Text" of pane id "com.apple.preference.keyboard"
	activate
end tell

tell application "System Events" to quit
set myRow to 1
set allSnippets to {}
set mySnippets to {}
set myShortcut to ""
set myReplacement to ""
tell application id "com.apple.systemevents"
	tell application process "System Preferences"
		tell window "Keyboard"
			tell tab group 1
				tell scroll area 1
					tell table 1
						set rc to count of rows
						-- display dialog "row count is " & rc as string
						repeat until myRow > rc
							set mySnippets to mySnippets & {row:{myRow}}
							tell row myRow
								tell UI element 1
									tell text field 1
										set focused to true
										delay 1
										tell application "System Events" to quit
										tell application "System Events" to keystroke "c" using {command down}
										delay 0.1
										-- display dialog "clipboard is " & (the clipboard)
										set myShortcut to the clipboard
										delay 0.1
										tell application "System Events" to quit
										set mySnippets to mySnippets & {shortcut:{myShortcut}}
										-- display dialog "row: " & row of mySnippets & ", shortcut: " & shortcut of mySnippets
										-- if myShortcut = "2021-06-20" then
										set focus to {}
									end tell
								end tell
								-- breakpoint between uiel 1 and 2 of each row
								tell UI element 2
									tell text field 1
										set focused to true
										tell application "System Events" to quit
										tell application "System Events" to keystroke "c" using {command down}
										delay 0.1
										-- display dialog "clipboard is " & (the clipboard)
										set myReplacement to the clipboard
										delay 0.1
										tell application "System Events" to quit
										-- display dialog "myReplacement is " & myReplacement
										set mySnippets to mySnippets & {replacement:{myReplacement}}
										-- display dialog "row: " & row of mySnippets & ", shortcut: " & shortcut of mySnippets & ", replacement: " & replacement of mySnippets
										set allSnippets to allSnippets & {mySnippets}
										set mySnippets to {}
										set myRow to (myRow + 1)
										-- display dialog "myRow is " & myRow
										set focus to {}
									end tell
								end tell
							end tell
						end repeat
					end tell
				end tell
			end tell
		end tell
	end tell
	set iter to 1
	set today_row to 0
	repeat until iter > rc
		-- display dialog shortcut of item {iter} of allSnippets
		if (shortcut of item {iter} of allSnippets) starts with "jgdate" then
			set today_row to (row of item {iter} of allSnippets)
		end if
		set iter to (iter + 1)
	end repeat
	-- display dialog today_row
	-- display dialog (replacement where (shortcut = "jgdate")) of allSnippets
	tell application process "System Preferences"
		tell window "Keyboard"
			tell tab group 1
				tell scroll area 1
					tell table 1
						tell row {today_row}
							tell UI element 2
								tell text field 1
									set focused to true
									keystroke today
									keystroke return
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
	end tell
end tell

-- quit System Preferences
tell application "System Events"
	get name of every process whose name is "System Preferences"
	if result is not {} then
		tell application "System Preferences"
			quit
		end tell
	else
		tell application "System Preferences"
			activate
		end tell
	end if
end tell

1 Like

I want to have an immediate replacement, i.e. even if in a word, and without having to type space. Is that possible?

In other words you want the word to be corrected without having to type a space first? AFAIK the native text replacement feature doesn’t support that.

If you’re not married to a native feature though there is Typinator that was already mentioned. It can expand a word even before hitting the space bar (among many, many other things).

2 Likes