Automating (and Scheduling) System Keyboard Text Replacements

If I understand your problem I do not think you need to update anything on a schedule.
You just need to use the date token like this.

Insert date Macro (v9.2)

Insert date.kmmacros (1.5 KB)

Thanks, Jimmy - but I'm not trying to create an expansion on macOS; I'm trying to create one that syncs to iOS (via the system text expansion) and works there, too - and the date is refreshed each day via a scheduled macro.

It mostly works (though the sync to other devices still isn't very reliable) but it doesn't work properly when the screen is locked.

1 Like

Okay. Read it to quickly.

No problem - I know it probably seems like I'm over-complicating things. I just thought it'd be a cool idea to be able to automate text expansions on iOS using KM on the Mac ... but it doesn't seem to be quite that simple!

Hi @coordinated You have probably tried this already - but you can use the inbuilt IOS Shortcuts App to get someway there. It can put the current date on the Clipboard in ISO format:

image

Then you can use Siri to run this Shortcut by saying "Date ISO". You do have to paste the result as I don't think the Shortcuts App can paste (which is odd).

Oh, thanks, but I've got one of those, too :laughing:
I was just playing to see whether I could make this work :nerd_face:

Yes, I thought you probably would have - but just thought I'd mention it.

It feels like IOS should have ability to insert today's date as an inbuilt function. Maybe one day it will. Like you, I really like the inbuilt Text Expansion in Mac and IOS - especially now that if syncs really well.

Funny you should mention the syncing now working well. It does seem much better these days - and updates across my devices almost instantly, but in playing around with the AppleScript/UI scripting I've realised how quirky some of the syncing is - at least when scripted.

Attempting to update an existing shortcut by selecting it (using UI Scripting) and over-typing it doesn't always work - and it feels like the previous/iCloud version overrides it.

I've updated the AppleScript in my macro so that it now removes all matching shortcuts/expansions and adds a new one in its place. That seems to work much more robustly. I am going and figuring :man_shrugging:

2 Likes

If you're doing any sort of UI/GUI manipulation, either with AppleScript or Keyboard Maestro, then yes, it does need to be unlocked to work.

You could use a pause until in Keyboard Maestro macro to wait until "the calculation" "SCREENSAVER()" returns "false" and then the macro would wait until the next time the screen is unlocked. (See The Wiki for more details.)

Alternatively, if your Mac is in a secure location, you could turn off the password requirement to wake from sleep or screensaver, if you understand and accept the associated potential risks.

I have an older Mac that I do this with. It basically just does a few simple automations, but they require the Mac to be "ok" so I turned off the screensaver password. I also have turned off iCloud Keychain on that Mac, and it does not have access to anything I consider "vital" so if someone did manage to access it, I don't think they would get access to anything meaningful. (Most everything is in 1Password anyway, which remains separately encrypted.)

(Considering that would require physical access to a computer in my home, someone using it would indicate I could have bigger issues to worry about.)

But each person would have to make their own risk assessment and determine their own comfort level.

Thanks, TJ. I'd already started adding more logic to my "Daily tasks" macro so that it could do just that. I'd got as far as starting with an "if idle" trigger, and then added extra "if/then" logic for "is it during working hours?" and "has this already been run today?" - but I wasn't aware of the SCREENSAVER function, and will now add that, too :+1:t2:

I definitely don't feel comfortable disabling security, so this needs to run when I'm using the Mac ... but it's just idle enough not to be annoying!

Updated version of the macro. I've reverted to updating the text substitution rather than removing and re-adding, as I was seeing some odd behaviour and the wrong row being removed.

It now works pretty well, though I'm not convinced that the iCloud sync is triggered every time the substitution text changes.

Update keyboard text expansion.kmmacros (24.7 KB)

And, finally, a proper post with images of the macros - though most of the logic is hidden in the AppleScript...

The macro that does the work:

Update keyboard text expansion.kmmacros (25 KB)

And an example which calls it (designed to be run every day):

Set keyboard shortcut yy- to today's date.kmmacros (1.5 KB)

And my "Daily tasks" macro has now been moved to a separate post.

1 Like

Could you please give more explanation for this? Or any links for this feature? Thank you!

Hi, Henry

The macro is relying on the built-in keyboard text substitution feature of macOS and the iCloud sync that is used to keep the substitutions in sync across platforms.

The AppleScript inside the main macro ("Update keyboard text expansion") scans the table of shortcuts/substitutions looking for a particular shortcut and updates its "replace with" value - or adds a new one shortcut it was not found. It's a general purpose macro - and it designed to be called from another one with parameters...

The second macro ("Set keyboard shortcut yy-") does just that - and tells the main macro to look for the shortcut "yy-" and replace it with today's date.

Please note that the AppleScript uses UI Scripting which may not work other versions of macOS. I've only been able to test it on macOS 11.4.

Does that help? Sorry if it wasn't clear from the original description.

Best wishes,
Steve

1 Like

Another minor change, this time to the AppleScript. Apparently, typing the text over the top of the previous one doesn't always update the field properly, so the previous text is now deleted first.

Update keyboard text expansion.kmmacros (25 KB)

I'm hoping this is the final change to the AppleScript :roll_eyes:

(Sorry for the clutter! Please let me know if I should remove the old versions from the posts above. I wasn't sure whether it was helpful to leave old copies around so that people could see the evolution...)

It now uses an AppleScript 'where' clause to find the substitution (rather than iterate over the table), and selects the row (as well as focusing on the 'With' value), and also bounces the cursor to trigger a scroll to that row ... all of which seem to have improved reliability (previously, the update was sometimes rejected/ignored).

It's 2021 and I didn't expect to still be writing (and learning a lot more about) AppleScript and UI scripting, but here we are :laughing:

Update keyboard text expansion.kmmacros (25 KB)

2 Likes

@coordinated - thank you very much for that macro, it is a great idea and i'll begin applying that mindset some more! :smiley:

It works like a charm with macOS 11.2.3 and iOS 15 (beta 2)

Thanks, Jens - that's kind of you. Do let me know if you think of any ways to improve it (or the associated Daily tasks script). My AppleScript's quite rusty and old fashioned, but I've borrowed ideas from other people to try and improve it...

@coordinated I made some minor changes to your already amazing macro to turn it into a subroutine. Thank you so much for all of your hard work figuring this out.

Update keyboard text expansion subroutine.kmmacros (28.5 KB)

Changes

  • Updated the “Check that both parameters were supplied” step to verify that the Local__replacementString is empty. I think this might be a bug fix.
  • Changed the shortcutString, replacementString, and matchesFound to be local variables (renamed them to be prefixed with Local__. This required minor changes to be made to the AppleScript (search for “kmInst” to see them).
  • Added delay 0.5 before getting the “Keyboard” window to avoid getting an AppleScript error if the Preferences Pane is already open.
  • Added logging to compliment the notifications
  • Changed to be a subroutine with parameters (Local__shortcutString and Local__replacementString) and removed the TriggerValue parsing
  • Updated documentation
1 Like