9

There are a few users here that use the same replacement text between several machines. We'd like to be able to sync up the replacement table between the systems.

Right now the manual way of doing this consists of selecting all items from System Preferences -> Keyboard -> Text entries on the table below this tab and then drag them out to Finder. Here's the table I'm talking about: example

This creates a plist that can then be shared and dragged back onto this table for importation.

I suspect that there's a way to manually capture the plist or a portion of this configuration wherever it exists and then simply set up a sync script that keeps us all in sync every day.

EDIT: For what it's worth, I did a little digging and found that these values are stored in ~/Library/Preferences/.GlobalPreferences.plist. If you look you'll see these stored in the NSUserDictionaryReplacementItems key.

I found that you can pull out these keys with the following command: /usr/libexec/PlistBuddy -c "Print :NSUserDictionaryReplacementItems" ~/Library/Preferences/.GlobalPreferences.plist

So now it's going to be a matter of storing these and reinserting them into another system's plist key.

Any ideas on how to do this manually from the shell so as to be able to automate?

2
  • 2
    Not really answering the question, but maybe addressing the underlying need: iCloud sync of text replacements should be fixed in iOS 11 and MacOS 10.13 High Sierra. daringfireball.net/linked/2017/09/27/…
    – ddaa
    Commented Oct 23, 2017 at 10:10
  • Thanks, yes, I should have noted that myself. This is helped (although I would still like to do it). Funny enough it seems to have come as a response from a feature request that I made to Apple. LOL. I'll give you an up vote, although I would still like to leave this around as not yet answered for an actual answer if it exists...
    – ylluminate
    Commented Oct 27, 2017 at 18:04

4 Answers 4

10

There is an unofficial command line tool, which does exactly what you want, its called shortcuts. As mentioned on GitHub, you can install it via homebrew

brew install rodionovd/taps/shortcuts

and then list your current replacements via

shortcuts read

and add new ones via

shortcuts import <input.plist>
shortcuts create <shortcut> <new phrase>
shortcuts update <shortcut> <phrase>
shortcuts delete <shortcut>

for details, see the documentation.

1
2

Simply press ⌘ Command A (select all) on the text replacement entries, drag them to desktop, send that file in email, drag and drop it back to the text replacement in the settings on the new MacBook, done.

0

Some of the .plist files I have on my system no longer appear to be editable XML files. But the command-line tool PlistBuddy which you mentioned in the question can help manage these files, too.

I found a couple of tutorials for how to use it:

Just to be on the safe side, I copied my .GlobalPreferences.plist before attempting to modify it.

This tool has an interactive mode. The following demonstrates a brief session - the lines with Command: are the prompts from PlistBuddy, and the rest of that line is a command I typed in.

bash:tripleee$ /usr/libexec/PlistBuddy ~/Library/Preferences/.GlobalPreferences.plist
Command: Print :NSUserDictionaryReplacementItems
Array {
    Dict {
        replace = omw
        with = On my way!
        on = 1
    }
Command: Add :NSUserDictionaryReplacementItems:1:replace string hello
Command: Add :NSUserDictionaryReplacementItems:1:with string goodbye 
Command: Add :NSUserDictionaryReplacementItems:1:on integer 1 
Command: Print :NSUserDictionaryReplacementItems
Array {
    Dict {
        replace = omw
        with = On my way!
        on = 1
    }
    Dict {
        replace = hello
        on = 1
        with = goodbye
    }
}
Command: exit

(The arrays are apparently zero-based; it will complain if you try to add into a position that is already occupied, though you can use set to change an existing value.)

You want to save if you are happy with the results, otherwise just exit and start over.

There is an import command but my impression is that it only supports reading a string into a single value. There is also a merge command but it requires another .plist file if I'm reading this correctly.

For a nontrivial import, I would create a simple shell script like this.

#!/bin/sh

/usr/libexec/PlistBuddy ~/Library/Preferences/.GlobalPreferences.plist <<\____done
delete :NSUserDictionaryReplacementItems
add :NSUserDictionaryReplacementItems array
add :NSUserDictionaryReplacementItems:0:replace string moo
add :NSUserDictionaryReplacementItems:0:with string bar
add :NSUserDictionaryReplacementItems:0:on integer 1
add :NSUserDictionaryReplacementItems:1:replace string baz
add :NSUserDictionaryReplacementItems:1:with string quux
add :NSUserDictionaryReplacementItems:1:on integer 1
add :NSUserDictionaryReplacementItems:2:replace string ick
add :NSUserDictionaryReplacementItems:2:with string don\'t
add :NSUserDictionaryReplacementItems:2:on integer 1
print :NSUserDictionaryReplacementItems
___done

Notice that any single quotes in the replacement string have to be backslash-escaped. Similarly, any literal backslashes will need to be doubled. I don't know if there are other special characters; I didn't stumble into any in my testing. The maximum of the replacement string appears to be 459 characters. (Weirdly, you get "Unrecognized Command" if you exceed this.)

Save this in a text file like /tmp/uplist and run it with sh /tmp/uplist. (You can't use TextEdit for this; remarkably, it does not actually support writing plain text files.)

Notice that there is no save in this example; you will want to verify that it seems to do the correct thing before you replace the print command on the last line with just save and rerun the script.

When you run the script, it will unattractively print the Command: prompt as many times as you have commands in the file. You might want to add a redirection >/dev/null once you are satisfied that it works acceptably. Before you do that, check that there are no error messages mixed in there, especially if you have experimented with nontrivial changes.

Bewilderingly, the dict data type is output in whatever order the system decides; don't be upset if the on appears before the with in individual Dict entries.

macOS Force User Global Preferences Reread To Refresh GUI seems to indicate that the change will only take effect after a reboot.


I found that this preference now also seems to live in ~/Library/Containers/com.apple.Keyboard-Settings.extension/Data/tmp/Text Substitutions.plist, which is a plain XML file, but so far, I'm not sure which is the master and which is some kind of mirror location.

-1

If it helps, if all that you have is a non-bootable backup of the old system, simply grabbing the entries from the .GlobalPreferences.plist manually may not work, as the entries are formatted differently there. You may need to do some find and replace so that

        <dict>
        <key>on</key>
        <integer>1</integer>
        <key>replace</key>
        <string>shruggie</string>
        <key>with</key>
        <string>¯\_(ツ)_/¯</string>
    </dict>

becomes

        <dict>
        <key>shortcut</key>
        <string>shruggie</string>
        <key>phrase</key>
        <string>¯\_(ツ)_/¯</string>
    </dict>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .