April 9, 2016 at 11:55 PM by Dr. Drang
A few days ago, I wrote about how the new version of TextExpander doesn’t have any compelling features for me and that I’d probably start migrating my snippets from TextExpander to Keyboard Maestro. This post describes a macro I wrote that performs some of that migration.
Before I get into the macro itself, I want to point out that I’ve been thinking about moving from TextExpander to Keyboard Maestro for a couple of years—pretty much ever since I bought Keyboard Maestro. And while Smile’s price increase and its switch to Snippets as a Service™ has unquestionably been the tipping point for my decision to finally make the change, it isn’t a decision I’ve made in a fit of anger. It’s just that the balance of pros and cons that kept me using TextExpander well after I could have switched to Keyboard Maestro has now tipped in Keyboard Maestro’s favor.
But just because it’s tipped for me doesn’t mean it’s tipped for you. I’m already a very comfortable Keyboard Maestro user, so making new snippets in it instead of TextExpander will be an easy transition for me. That might not be the case for you. You might be better off sticking with TextExpander and paying the extra vig. Or going with Typinator or TypeIt4Me, both of which work more like TextExpander has up until this new version.
Enough unwanted advice. Let’s get into the macro.
My first thought was that I could use Python’s
plistlib module to turn an exported TextExpander library into a Keyboard Maestro library for importing. But while TextExpander’s plist format is very simple and easy to understand, Keyboard Maestro’s is distinctly more complex. Because Keyboard Maestro is a more powerful tool, its plist format is a more deeply nested system of
arrays. Figuring out how write its format was going to take way more time than a single-use script was worth.
So I took another approach: a Keyboard Maestro macro that copies the relevant information out of TextExpander and pastes it into Keyboard Maestro. This is a brute force approach, one that I’m not especially proud of. It’s limited to text-only snippets—although I suspect I’ll be able to use it as a template for macros that import AppleScript and shell script snippets—and needs a bit of setup before it can run. But it does run.
Two macros are in a library you can download. The main macro imports a single snippet from TextExpander into Keyboard Maestro. The other is a simple looping macro that runs the first one a specified number of times to import several snippets. Let’s talk about the main one first.
To set yourself up to run the main macro, you’ll have to do a few things:
Open TextExpander and select the snippet you want to import. Here, I’ve opened my folder of Keyboard symbol snippets and have selected the first in the list.
Make sure the snippet itself is highlighted in blue on the left side of the window. The macro tabs back and forth to select different parts of the snippet, and it only works if it starts in the right place.
- Open the Keyboard Maestro Editor and open or create a new folder for your imported snippets.
This is the tricky part. Make sure that the Actions panel is set so that theAction is chosen from the Category. You might need to create a new dummy macro (which you can then delete) to get this set up.
One last thing: you’ll have to make sure the middle of the title bar of the TextExpander window is visible even when the Keyboard Maestro application is active. You’ve no doubt noticed that the TextExpander application doesn’t behave like other Mac apps. It doesn’t appear in the Dock or in the Tab Switcher. Because of that, the only way I could get the importing macro to switch between Keyboard Maestro and TextExpander was to simulate a click in the middle of the name of the TextExpander title bar, and that only works if the middle portion of the title bar is visible.
Update 4/10/16 9:41 AM
Ed Cormany pointed out that the TextExpander title bar doesn’t have to be visible if I change one of its preferences. I normally have the “Hide TextExpander icon in Dock” option turned on; but if I turn it off, TextExpander acts like a normal app, and I can use Keyboard Maestro’s Action to switch to TextExpander instead of the simulated clicks I had been using.
This is a much more robust way to do the application switching, so I’ve changed the macro accrodingly. The preference can, of course, be changed back after the importing is done.
With this setup finished, you’ll be ready to run either the single-snippet importer or the multi-snippet importer. Almost. You’ll probably want to edit the single-snippet importer in a couple of places, because your snippet naming system is unlikely to match mine.
For many years, I used a semicolon to prefix all of my TextExpander abbreviations. Last year, in an attempt to get myself using TextExpander more on my iPhone, I switched to a “jj” prefix and synced snippets between the two platforms. The attempt failed. I still don’t use TextExpander on my phone, which is one of the reasons I feel comfortable switching to Keyboard Maestro. Since the new Keyboard Maestro snippets will be used on the Mac only, there’s no reason to keep the “jj” prefix, so part of the single-snippet importing macro changes the trigger text back to having a semicolon prefix.
The upshot of all this is that you’ll have to make edits in a couple of spots in the single-snippet importing macro. Here’s a screenshot of the macro, with red lines next to the areas you’ll want to edit to fit your situation.
The macro copies the abbreviation from TextExpander and pastes it in as the name of the new macro in Keyboard Maestro. Because all my TextExpander snippets start with “jj,” and I don’t want that in the name, the macro deletes the first two characters. That’s what the first red-lined set of actions do.
Next, the macro uses the abbreviation (still on the clipboard) for the Keyboard Maestro trigger text. Again, I want the trigger text to start with a semicolon instead of “jj,” so the macro deletes the first two characters and puts a semicolon in their place. That’s what the second red-lined set of actions do.
If you don’t use any sort of prefix for your TextExpander abbreviations, you can just delete all the red-lined actions. If you use a single-character prefix that you want to maintain in your Keyboard Maestro snippets, you can delete one of the Forward Delete actions in the first set of red-lined actions and delete the second set entirely. If you have a more complex situation, you’re on your own.1
The multiple-snippet importing macro is just what you’d expect it to be: a repeat loop that calls the single-snippet importing macro a given number of times.
As you can see, I have it set to run 16 times, but you can change that to fit however many snippets you need to import. I count the number of snippets in each TextExpander folder and change the number accordingly. Sixteen happens to be the number of snippets I have in my Keyboard folder in TextExpander. Here’s what that set of snippets imported to in Keyboard Maestro looks like:
This method of importing is slow, mainly because of all the Pause actions I put in to make sure the click targets were ready. The sixteen snippets shown above took two minutes to import. Some of the sluggishness is due to my running this on a 2010 MacBook Air, not exactly a speed demon these days. You might be able to eliminate or reduce the delay in some of the Pauses. Even if you don’t, it’s much faster and more accurate than trying to make all these snippet macros by hand.
Finally, I should mention that Keyboard Maestro’s developer, Peter Lewis, warns against filling it with too many snippets. If you’re one of those people who has thousands of TextExpander snippets, importing them all into Keyboard Maestro is likely to slow down the Keyboard Maestro Editor considerably. I’m not sure how many snippets I have, but I’m sure it’s only 100–200 at most, and many of them are abandoned snippets that I won’t be importing anyway. I won’t be taxing Keyboard Maestro.
Of course, some of my most important snippets are AppleScript and shell script snippets. I don’t have importers for those yet, but now that I have this one made, I expect those will be pretty easy to write. I’ll let you know how they turn out.
Why don’t I just write a macro that works for everyone? Because to me automation is all about personalization. I don’t write scripts and macros for everyone. I write them for me and explain how they work so you can customize them to fit your situation. ↩