How to modify .GlobalPreferences.plist file?

Solution 1:

In order to toggle the state of Text Substitutions by swapping the ~/Library/Preferences/.GlobalPreferences.plist file, you would need to have a way to update the cached copy of it in memory. If you are an Objective-C programmer and have Xcode you could roll-your-own app to update the file and what's cached in memory. Sans that, here is a method using a third-party command line utility, shortcuts, and a shell script that works for me.

The bash shell script I've written uses the shortcuts binary executable to backup, delete and restore the Text Substitutions. The backup and restore are simple and straight forward compared to deleting the Text Substitutions as shortcuts can only delete one shortcut at a time. It's relatively quick. I have 200+ items in my Replace | With list and the script takes ~4 seconds to delete them, and a fraction of a second to restore them.

This was tested under macOS Catalina and macOS Big Sur with Language & Region settings in System Preferences set to English (US) — Primary and worked for me without issue1.

  • 1 Assumes necessary and appropriate setting in System Preferences > Security & Privacy > Privacy have been set/addressed as needed.

Note: First make a manual backup of your Text Substitutions by going to System Preferences > Keyboard > Text, pressing ⌘A to highlight all entries of Replace | With list, then click-hold with the mouse, then drag and drop to the Desktop, or any folder of a Finder window.

This will create a file named Text Substitutions.plist that can be dragged and dropped onto the Replace | With list in System Preferences > Keyboard > Text to manually restore.

The example shell script code in conjunction with the shortcuts command line utility does it own backup and restores from its backup, but always make the manual backup described above just to have if ever needed.


Install shortcuts by one of the methods mentioned in the link.

I downloaded the source code, reviewed and verified there was nothing ominous in the code, then built it using Xcode.

It's also available thru Homebrew, in Terminal brew install rodionovd/taps/shortcuts, or download as a pre-built binary.


Note: The following instructions and example shell script code are for use as an executable shell script in Terminal, and or can be used in a Run Shell Script action in an Automator Service/Quick Action and assigned a keyboard shortcut in: System Preferences > Keyboard > Shortcuts > Services

I'd suggest testing as an executable shell script first to ensure that it works for you, then use the example shell script code in an Automator Service/Quick Action.

In Terminal, run the following compound command:

      Assumes the pwd is your HOME directory.

f=trw; touch "$f"; open -e "$f"; chmod +x "$f"

      Note: trw = Toggle Replace With (Had to name it something.)

In the opened trw document copy and paste the example shell script code into it, then save and close it.

Back in Terminal:

./trw

Will toggle the state of the Text Substitutions.

Note: After testing, move trw to a directory defined in the PATH to be available without typing: ./


Example shell script code:

#!/bin/bash

# set -e
# set -x 

shortcuts="/usr/local/bin/shortcuts"
automator=false # true or false


message() {
    [ "${1}" == "xmissing" ] && msg=" The 'shortcuts' executable is missing!"
    [ "${1}" == "already" ] && msg=" The text substitutions deletion is already in progress!"
    [ "${1}" == "backedup" ] && msg=" The text substitutions have been backed up."
    [ "${1}" == "nobackup" ] && msg=" No text substitutions to backup or restore!"
    [ "${1}" == "restored" ] && msg=" The text substitutions have been restored."
    [ "${1}" == "deleting" ] && msg=" The text substitutions deletion is in progress..."
    [ "${1}" == "finished" ] && msg=" The text substitutions deletion has completed."
    [ $automator == false ] && printf '%s\n' "${msg}"
    [ $automator == true ] && printf '%s\n' "$(date -j) ${msg}" >> message.txt
    [ $automator == true ] && [ -n "${2}" ] && \
    osascript -e "display notification \"${msg}\" with title \"Toggle Replace With\""
}

backupdir="$HOME/Library/Application Support/com.$USER.shortcuts"
[ ! -d "${backupdir}" ] && mkdir -p "${backupdir}"
cd "${backupdir}" || exit
backup="${backupdir}/Text_Substitutions.plist"
lockdir="/private/tmp/com.$USER.shortcuts"
[ ! -e "${lockdir}" ] && mkdir -p "${lockdir}"
cd "${lockdir}" || exit

if [ ! -x "${shortcuts}" ]; then
    message "xmissing"
    [ $automator == true ] && message "xmissing" "notification"
    exit    
fi

if [ -e ".lock" ]; then
    message "already"
    [ $automator == true ] && message "already" "notification"
    exit
fi

contents="$(defaults read -g NSUserDictionaryReplacementItems)"
empty='(
)'

if [ ! -e "${backup}" ] && [ "${contents}" != "${empty}" ]; then
    "${shortcuts}" read --as-plist | tee "${backup%.*}.$(date '+%s').plist" > "${backup}"
    message "backedup"
elif [ -e "${backup}" ] && [ "${contents}" != "${empty}" ]; then
    "${shortcuts}" read --as-plist | tee "${backup%.*}.$(date '+%s').plist" > "${backup}"
    message "backedup"
elif [ ! -e "${backup}" ] && [ "${contents}" == "${empty}" ]; then
    message "nobackup"
    [ $automator == true ] && message "nobackup" "notification"
    exit
fi

if [ "${contents}" == "${empty}" ]; then
    "${shortcuts}" import "${backup}"
    message "restored"
    [ $automator == true ] && message "restored" "notification"
else
    touch ".lock"
    message "deleting"
    [ $automator == true ] && message "deleting" "notification"
    while IFS= read -r line; do
        "${shortcuts}" delete "${line}"
    done <<< "$("$shortcuts" read | awk 'sub(/^"/, "", $2) sub(/"$/, "", $2) $1 ~ /^[0-9]+:/ { print $2 }')"
    sleep 1
    rm ".lock"
    message "finished"
    [ $automator == true ] && message "finished" "notification"
fi


Notes:

As coded, the example shell script code assume the shortcuts executable is located at /usr/local/bin/shortcuts, change as applicable. It is coded like this as /usr/local/bin/ is not in the PATH passed to a Run Shell Script action in an Automator Service/Quick Action.

The first time the shell script is run it creates a backup of the Text Substitutions to restore from, so it is imperative that there actually be some text substitutions to backup! A current backup is made each time prior to deleting them from the ~/Library/Preferences/.GlobalPreferences.plist file and is restored from the last backup.

The reason a third-party application is being used is in this use case it does something that the macOS default utilities cannot do, which is dynamically update the changes to the system. In other words, the defaults command as well as the /usr/libexec/PlistBuddy command in this use case does not update the system to the changes and has the same issue as swapping out the ~/Library/Preferences/.GlobalPreferences.plist file.

When using the example shell script code in a Run Shell Script action in an Automator Service/Quick Action, you need to set automator=true in the line after, e.g., shortcuts="/usr/local/bin/shortcuts"

Backups are saved to:

$HOME/Library/Application Support/com.$USER.shortcuts/Text_Substitutions.plist

The example shell script code when run as an executable shell script outputs messages to stdout and you see them as you go, however, when used in a Run Shell Script action in an Automator Service/Quick Action messages are displayed in Notification Center and also log to:

/private/tmp/com.$USER.shortcuts/message.txt

I will try you add comments to the code and or add additional notes here in the next couple of days.


enter image description here



Disclaimer Note: The example shell script code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any additional error handling as may be appropriate, needed or wanted.

Solution 2:

TextView windows that use macOS's Text Replacement usually provide a menu item to toggle Text Substitution off and on.

Edit > Substitutions > Text Replacement

enter image description here

You can set a keyboard shortcut for this menu item in System Preferences > Keyboard > Shortcuts.

enter image description here

(Here I've done it just for TextEdit, but you can do it for All Applications if you want.)

Toggling the key command gives me the following, when I type omw:

enter image description here

This achieves your goal of switching the replacement status without the complicated effort of maintaining and switching two complete preference files.