The Smile Blog, With News, Tips, Photos and Other Stuff That Makes Us Smile

Fun with TextExpander and Scripting

Posted 07/17/2015 by Greg

TextExpander 5 adds support for JavaScript snippets, which can be run on all of your devices – Macs, iPads, and iPhones. Here is a sample script which rounds the current date to the nearest 5 minute interval:

// Rounded date
// Rounds up or down to the most recent 5 minute interval
// For example, 08:18 rounds to 08:20, and 08:17 rounds to 08:15
// Thanks to William Alba for submitting

currentTime = new Date();

hours = currentTime.getHours();
minutes = currentTime.getMinutes();

minutes_rounded = 5 * Math.round(minutes/5);

// handle cases when minutes round to 60, and when hours increment to 24

if (minutes_rounded == 60) {
  minutes_rounded = 0;
  hours = hours + 1;
if (hours == 24)
  hours = 0;

// 24-hour format requires leading zero

if (hours < 10)
  hours = "0" + hours;

if (minutes_rounded < 10)
  minutes_rounded = "0" + minutes_rounded;

hours + ":" + minutes_rounded

TextExpander itself is scriptable via AppleScript and JavaScript for automation. User Vlad Ghitulescu wanted to create a large number of snippets for inserting the day and time in OmniFocus. For example, he wanted to type ",di09" and have it expand to "Dienstag 09:00". Did I mention that Vlad works in German? Anyway, we worked with him to create a script to build the group he needed:

set greetWords to {"Monday", "Tuesday", "Wednesday", "Thursday", ¬

"Friday", "Saturday", "Sunday"}

-- set greetWords to {"Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"}

set abbreviationPrefixes to {"mo", "tu", "we", "th", "fr", "sa", "su"}

-- set abbreviationPrefixes to {"mo", "di", "mi", "do", "fr", "sa", "so"}

tell application "TextExpander"

set newGroup to make new group with properties ¬

{name:"Label with Date & Time"}

tell newGroup

if (count greetWords) is not (count abbreviationPrefixes) then

display dialog "The number of greetWords must match ¬

the number of abbreviationPrefixes"


end if

repeat with index from 1 to 6

set greetWord to item index of greetWords

set abbreviationPrefix to item index of abbreviationPrefixes

repeat with x from 6 to 22

set newAbbreviation to "," & abbreviationPrefix

if x is less than 10 then

set newAbbreviation to newAbbreviation & "0"

end if

set newAbbreviation to newAbbreviation & x

if x is less than 10 then

set snippetText to greetWord & " 0" & x & ":00"


set snippetText to greetWord & " " & x & ":00"

end if

set newSnippet to make new snippet with properties ¬
{abbreviation:newAbbreviation, plain text expansion:snippetText}

end repeat

end repeat

end tell

end tell

The original script was written for use in German, so I've commented the German words and abbreviations and replaced them with their English equivalents. Feel free to swap the commenting if you'd prefer them in German, or feel free to change them for other languages.

If you've been having fun scripting with TextExpander, come join the TextExpander Tips Google+ Community and share.

PDFpen Tip for the Day: Stamps

Posted 07/10/2015 by Maia

Need to put a big red Draft stamp on a PDF, or a Sign Here arrow? PDFpen comes with stamps for just that purpose. The stamps are a type of imprint you can place on your document that is new to version 7 of PDFpen and PDFpenPro and version 2 of PDFpen for iPad & iPhone.

Stamps tab

There are three categories of stamps to choose from, which you will notice when you open the Library window (⌘Y) to the stamps tab. You won't see these separate categories in PDFpen for iPad & iPhone.

  • Sign here style arrowed stamps
  • Business stamps for things like Paid, Copied, Approved
  • Dynamic stamps for when you need the current date and time in the stamp

There is a fourth category, and that is User Defined. This is where you can make your own custom stamps. (Making stamps is Mac-version only).

Make a Stamp

  1. Click on the + at the lower left corner of the Library window and choose “Add Custom Stamp.”
  2. In the Add Custom Stamp Window, you have a few customizations to make :
    • label, or, what the stamp will say
    • type (Dynamic, Sign Here or Standard Business)
    • color scheme
  3. Click OK to finish and this stamp will be listed in User Defined.

Here are a few sample pictures of what different stamp options look like:

samples of stamps

If you want something more customized than that, you could create something in your graphics app of choice and then import it into the Library by clicking the + in the lower left of the window and choosing Add File. It would be a static image, so no current date and time, and it would be listed in the Custom tab. You might want something like this for your company logo, for example.

If you purchased PDFpen from the Mac App Store then you can use iCloud to sync these stamps over to PDFpen for iPad & iPhone.

As always, if you have any tips or tricks of your own, let us know and we'll share it.

PDFpen 7.2 Adds Cloud Tool, Advanced Search Options and More

Posted 07/09/2015 by Maia

PDFpen iconPDFpen and PDFpenPro 7.2 are now available with several handy improvements. 

This update adds a new Cloud annotation tool, a case-sensitive search option and a new Editing preference to control automatic switching between the Edit and Select Text tools.

You'll find popup notes for highlights and stamps now offer a Delete note button and the context menu offers Edit and Delete note options. The sidebar's annotation list offers icons for easy identification, wrapped text for improved readability, and date, author, and location when available.

PDFpen users will notice a new Inspector tab for viewing document permissions. Editing document permissions is still PDFpenPro only. 

What's New:

  • Adds new Cloud annotation tool
  • Adds case-sensitive search option
  • Adds Editing preference for automatic selection tool switching
  • Improves popup notes for highlights and stamps:
    • Adds Edit Note and Delete Note menu commands
    • Adds Delete Note button
  • Enhances annotation list:
    • Shows annotation icons
    • Wraps text for improved readability
    • Shows date, author, and location when available
  • Adds read-only Document Permissions window to PDFpen
  • Exports new unsaved documents
  • Other fixes and improvements

WWDC 2015 Happy Hour Round Up

Posted 06/22/2015 by Maia

The Smile Team made it to WWDC this year, and to the other two conferences in SF the same week. We’re looking forward to what iOS 9 and El Capitan will bring later this year, as are you.

Here’s what our developer on the ground, Éric, noticed from within the walls of WWDC:

There was a palpable sense of relief when talking to most of the developers at the conference after they took stock of the keynote announcements. Indeed, it seems that this year’s OS releases are a bit less about broad and sweeping changes such as iOS 7’s UI redesign or last year’s addition of a multitude of OS extension mechanisms and more about incremental refinements of the platforms. While there were still plenty of exciting new features and announcements to be found (split-screen multitasking support for the iPad, system-wide Search API on iOS, a revamped and much-improved Notes application, Swift 2 going open source), it seemed that there’s going to be a little more breathing room for developers to keep pace with Apple’s platform advancements this year.

Dub-Dub was not the only game in town. We helped sponsor the free alternative conference altConf for another year. It was bigger and better than ever, with two speaker tracks and room for 1000 people. As the wrap session said, this conference isn’t just to make better devs, it’s to make better people. There are conferences to make you better at CoreData and Swift and Playgrounds, and then there are conferences that remind you why you do what you do and to stoke that passion for another year. We, and others who support AltConf, believe you need both. Yet another conference joined Dub-Dub week, Layers the design conference. As MC and conference co-founder Jessie Char said, this conference was all about hearing from her favorite designers while eating all her favorite foods. Plus new-version Photoshop sneak peaks. To misquote her further, who doesn’t love that?

(PS, did you know that 3-D printed designer glasses while you wait is a thing? The future is now.)

WWDC is not just a time to watch sessions and learn the new stuff as quickly as possible, but to meet new friends and catch up with old ones.

Peter Cohen (iMore) and Kelly Guimont (Smile).

Greg Scown (Smile) and Bob Cantoni (Nice Mohawk) former Smile-er.

Florian Albrecht (Elgato) and Maia Olson (Smile).

App Camp 4 Girls had a successful party to start off Camp 3.0 Indiegogo campaign. Take a page from the App Camp play book if you want to keep your crowd engaged. Play Social Bingo so that everyone asks around to see who plays guitar and who flew in from Canada.

To finish off the week, on Conference Day 5, we had a Smile Team wrap party. This is one of the few times a year a large group of get together.

(Éric, Angel, Yunor, Kelly, Maia, Nat, Philip)

Hope you enjoyed happy hour. We had pizza and caipiranas. Now, we’re off to make PDFpen and TextExpander ready for the fall OSs.

All About Suggested Snippets

Posted 06/04/2015 by Maia

suggestions windowOur favorite new feature of TextExpander 5 is suggested snippets.


As you type, TextExpander will let you know what you type the most, and suggest you make it into a snippet.

You may have noticed these suggestions appearing in the corner of your screen through Notification Center.


To locate these suggested snippets open the TextExpander window to the “Suggested Snippets” group.


Keep, drop, or delete the suggestions:

  • Keeping a suggestion means adding an abbreviation to it to complete the snippet. You can then move it into another group for better organization. Click the “Keep” button to keep it.
  • Dropping a suggestion means that TextExpander will never, ever, suggest it again. This is not the same as deleting a suggestion. Click the “Drop” button to drop it.
  • Deleting a suggestion means you remove that suggestion. TextExpander may suggest that same snippet again. Select the suggestion then press the Delete key to delete it.


To receive these notifications, open TextExpander’s Preferences > Suggestions and check the suggest snippets option.

If you want to keep the suggests coming, but have fewer of them, drop the ones you know you don’t want, they’ll never come back. Don’t delete suggestions you really don’t want, they could come back as new suggested snippets.

If you don’t want to receive these notifications at all, uncheck the option. However, in version 5.0, you will still receive some notifications on your pending suggested snippets. We do plan to address this in the next update.

The future:

Now that this feature is out in the wild we’re getting great feedback. With some time to reflect, we’ll work on fine tuning the suggestions.

A few ideas we’re tossing around for future settings would allow users to set the minimum length of a suggestion, limit suggestions to phrases only, or to avoid suggestions that are dictionary words.


Keep your suggestions to us coming! Your feedback is invaluable in shaping TextExpander.

TextExpander 5.0: Taking Stock

Posted 06/01/2015 by Greg

A few days have passed since the release of TextExpander 5.0, so it’s time to share what we’ve learned from this release.

Upgrade Overlay

This is our first paid upgrade to use the new upgrade overlay. We made an error in testing, so it shows Version 500 (like 5.0.0) rather than Version 5. We got some well-deserved ribbing from users about this mistake.

The overlay ensures that users know TextExpander 5 is a paid upgrade so that they don't reflexively hit “Install Update” without reading the update text. This has helped us avoid a lot of anger, confusion, and support mail which arises when a user unintentionally updates to a paid upgrade, as was rather common with PDFpen 7.

Some users have reported the overlay nags them. The overlay only appears when the update window is shown. To avoid it, reduce the checking frequency in the Update preferences, or turn off update checking altogether.

Cutoff Date Typo

The cutoff date for free upgrades is January 1, 2015. Due to an error integrating localizations, we show the cutoff date from TextExpander 4 in French, German, Italian, Japanese, and Spanish. The software enforces the correct date, but the display reflects the typo. Most users figured this out on their own, and some wrote for support which allowed us to clarify. We’re sorry for this, and we’ll fix this in our next update.

Error when moving settings file

The worst issue we’ve encountered is that in some cases, OS X failed to recognize our new file extensions (.textexpandersettings and .textexpanderalias). Users experienced this as an “Unknown error when moving settings file” when trying to save their settings to a new location in the Sync preferences. Fortunately, the workaround is easy. Use a tool such as Cocktail or Onyx to rebuild the Launch Services database. Or, delete and re-download TextExpander 5, which apparently forces OS X to update its Launch Services entry for TextExpander.

Display and default font size preferences aren’t saved

If a user sets the display font size for plain text or the default font size for formatted text, this won’t be saved when they quit and re-launch TextExpander. This bug will be fixed in our next update.

Dock covers purchase window

Some users report they’ve been unable to purchase because the Dock covers the buttons at the bottom of the purchase window. The workaround is to temporarily check “Automatically hide and show the Dock” in the Dock pane of System Preferences. We’ll fix this in our next update.

JavaScript for Automation (JSA) scripts return extra newline

These are executed via the osascript terminal command, and it appears that command always adds a newline to its output. We will strip that newline in a future update. In the meantime, you can ‘wrap’ a JSA script in a shell script to strip the newline character:

echo -n "%snippet:jsjs%" | tr -d '\n'

Secure Input Notification

Many users have noted that the Secure Input notifications are too frequent or intrusive and have asked for an option to turn them off. We expect to provide that in a future update. Here’s more info on secure input, if you’re interested.

Plain text password suggestions

When an app requests a password without secure input enabled, TextExpander is able to observe and thus suggest the text. An example of this would be Terminal. Apparently, OS X can’t detect when Terminal is requesting a password. That’s why Terminal has an option in its menu to toggle Secure Keyboard Entry. TextExpander excludes Terminal from Suggestions by default. We can’t control how other apps handle passwords, but they certainly shouldn’t allow themselves to be observed by user-authorized key loggers, such as TextExpander.

If a plain text password appears in TextExpander’s Suggested Snippets group, you can select it and choose “Drop Suggestion” to ensure that it is never suggested again. We expect to update our FAQ in a future release with more detail and recommendations.

Sample JavaScripts for TextExpander 5.0 / TextExpander touch 3.5

Posted 05/28/2015 by Greg

TextExpander 5.0 and TextExpander 3.5 add support for JavaScript snippets. JavaScript includes a very nice math library, so in addition to having snippets which run on both OS X and iOS, there are a number of snippets which are easier to write. Here are some examples of snippets you can make by setting the Content: menu of a new snippet to JavaScript, and pasting the following into the editor:

Calculate Body Mass Index (BMI)

// Body Mass Index (BMI) from height and weight
var height = Number(%filltext:name=m:default=1.64:width=5%);// meters
var weight = Number(%filltext:name=kg:default=57.5:width=5%);// kilograms
"Body mass index for subject " + height.toFixed(2) + "m tall weighing " +
	weight.toFixed(2) + "kg is: " + Number(weight / (height * height)).toFixed(2);

Compute Hourly Rate Total

// Compute a charge by multiplying hours * hourly rate
var hours = Number(%filltext:name=Hours:default=1.5:width=5%);
var hourlyrate = Number(%filltext:name=Rate:default=30:width=5%);
"Billing for " + hours + " hours at $" + hourlyrate + " for a total of $"
	+ (hours * hourlyrate);

JavaScript snippets can include fill-ins. Here's a quick calculator which can evaluate any valid JavaScript expression:

Quick Calculator

// Quick Calculator -- enter a valid JavaScript expression
%filltext:name=equation:default=2 + 3%;

Here is a more elaborate fill-in example used to tally a survey:

Assess Depression on PHQ-9 Depression Scale

// Depression scale
TextExpander.appendOutput("PHQ-9 Depression scale\n" +
"In last 2 weeks, how often have you experienced:\n\n" +
"  (Score for each answer: 0-'not at all'  1-'several days' " +
"   2-'more than half the days'  3-'nearly every day')\n" +
"1- little interest or pleasure in activities? %fillpopup:name=1:default=0:1:2:3%\n" +
"2- feeling down, depressed, or hopeless? %fillpopup:name=2:default=0:1:2:3%\n" +
"3- trouble falling asleep, staying asleep, or sleeping too much? %fillpopup:name=3:default=0:1:2:3%\n" +
"4- feeling tired or having little energy? %fillpopup:name=4:default=0:1:2:3%\n" +
"5- poor appetite or overeating? %fillpopup:name=5:default=0:1:2:3%\n" +
"6- feeling bad about self, feeling failure, or let self or others down? %fillpopup:name=6:default=0:1:2:3%\n" +
"7- trouble concentrating, reading newspaper, or TV? %fillpopup:name=7:default=0:1:2:3%\n" +
"8- moving or speaking so slowly that other people could have noticed? Or the opposite, being so fidgety or restless that you have been moving around a lot more than usual? %fillpopup:name=8:default=0:1:2:3%\n" +
"9- thoughts that you would be better off dead or of hurting yourself in some way? %fillpopup:name=9:default=0:1:2:3%\n\n");

var count = 0;
var sum = 0;
for (count = 1; count <= 9; count++) {
    var fieldVal = Number(TextExpander.filledValues["" + count]);
    if (fieldVal != NaN) {
        sum += fieldVal;
    else break;

TextExpander.appendOutput("Total: " + sum + "\n" +
	"   Greater than 10 => major depression\n" +
	"   Greater than 20 => severe depression\n");

Have a favorite JavaScript? Send it in and include permission so we can share it.

TextExpander Adds JavaScript Support

Posted 05/27/2015 by Greg

TextExpander 5 and TextExpander touch 3.5 now include support for standard JavaScript snippets, and TextExpander 5 also includes support for JavaScript for Automation on OS X.

As a basic example, a scientist with a frequent need for an approximation of Pi to eight digits of precision could set up a JavaScript snippet with abbreviation zpi and content:


Any time the user types zpi, it will expand to: 3.14159265.

Here is a more complex example. It's a TextExpander fill-in snippet which tells the user their zodiac sign:

zodiacSigns = ['monkey', 'rooster', 'dog', 'pig', 'rat', 'ox',
                'tiger', 'rabbit', 'dragon', 'snake', 'horse', 'goat'];
var index = %filltext:name=Enter your birth year:default=1984% % 12;
"Your Zodiac sign is the " + zodiacSigns[index] + ".\n";
// %filltop%

When expanded, the user is prompted for their birth date, and the snippet returns their zodiac sign. For example, if the user enters 1972, the snippet expands to "Your Zodiac sign is the rat."

Did you notice %filltop%? That tells TextExpander to duplicate any single line and popup fields at the top of the fill-in window and hide the script. You'll find that via the insert menu under Fill-ins > Show at top.

Content Object

TextExpander includes a JavaScript context object, which exposes the following items you might find useful. Precede these with TextExpander, for example, TextExpander.appendOutput("Hello, world!").

triggeringAbbreviation - the abbreviation which triggered the expansion [boolean, read/write]
ignoreOutput - do not use the final statement as the expansion [boolean, read/write]
appendOutput(text) - add text to the expansion [function]
baseDate - date and time at which the snippet is expanded [date, read only]
adjustedDate - date and time used to expand the snippet [date, read/write]
pasteboardText - clipboard contents [string, read/write]
expansionContext - bundle ID within which snippet is being expanded [string, read only; can be nil]
filledValues - fill-in field values [associative array of strings, read/write]

JavaScript for iOS and OS X

You can take advantage of JavaScript support on both OS X and iOS to create snippets which run on both platforms — something you can't do with AppleScripts and Shell Scripts. You can write a snippet to make the clipboard content lowercase in JavaScript like this:


JavaScript for Automation

On OS X, you can use JavaScript for Automation (JSA) as an alternative to AppleScript. This form of JavaScript will not function in iOS. TextExpander should automatically detect JSA, or you can force JavaScript to be treated as JSA by starting it with a comment: //JSA

Here is a JSA script to create a new message, set its subject, and set its content:

Mail = Application('Mail');
message = Mail.OutgoingMessage().make()
message.subject = "New Message";
message.content = "This is a new message created via JavaScript."

You might enjoy this article from MacStories on Getting Started with JavaScript for Automation.

If you have a favorite JavaScript, please send it in, and let us know if we can share it with the world.

TextExpander 5, featuring snippet suggestions

Posted 05/27/2015 by Team

We're excited to present TextExpander 5, featuring snippet suggestions.

TextExpander 5 suggests new snippets based on what you type the most, and reminds you when you miss a chance to use a snippet. That's time saved.

Sync with iCloud Drive, any Dropbox folder, or any syncing folder. (Details below.) Get improved search and JavaScript snippets among a host of other new features.



US $19.95 to upgrade from your current version. 

Free upgrades are available via the TextExpander 5 application to those who purchased version 4 on or after January 1, 2015.

Upgrade by downloading TextExpander 5. Launch it, and it will tell you if your upgrade is free or paid. If it's paid, click "Buy an upgrade license."

TextExpander 5 requires OS X 10.10 (Yosemite) or later.

What's New in Version 5:

  • Suggests snippets from phrases you habitually type
  • Reminds you of missed opportunities to use your abbreviations
  • Customize snippet file location
  • Sync via iCloud Drive or any sync folder
  • Simplified expansion of lengthy fill-ins and scripts
  • Search and expand snippets, abbreviations, and suggestions inline as you type
  • Preview expanded snippet
  • Refreshed statistics display
  • Supports JavaScript snippets that also operate on iOS
  • Updated for Mac OS X 10.10 Yosemite (required)


Setup New Sync:

Sync with any syncing folder.

  1. Open TextExpander to Preferences > Sync.
  2. Click Save Snippets As…
  3. Choose a location on your hard drive to store your snippets. If you choose a syncing folder, then your snippets will sync.

Update your other devices:

  1. On your second Mac open TextExpander to Preferences > Sync. On an iOS device open TextExpander's Settings to Sync Snippets.
  2. Click on Link To Snippets… 
  3. Locate your Settings.textexpandersettings file and select it. 

If you have an older version of TextExpander for Mac (4 or earlier) or TextExpander touch (3.2.4 or earlier), then you need to keep using the Older Version Dropbox sync by clicking Sync with TextExpander 4…

Setup Inline Search:

Can't remember snippets? Use search. It's more convenient to use than before.

  1. Open TextExpander to Preferences > Hotkey.
  2. Click the Click to Set Hotkey button next to Inline Search.
  3. Press your preferred hotkey combo. (Note: hotkey combinations must include Command, Option, Control and/or Shift plus any character or number key.)

Use the Inline Search :  

  1. Type your hotkey. The TextExpander search window will appear near your cursor.
  2. Type any part of your snippet, abbreviation, content, or label. Scroll through the results and click the one you want, or press Command + # for the option you want.

TextExpander touch 3.5: Sync with iCloud Drive, JavaScript snippets

Posted 05/26/2015 by Maia

TextExpander touch 3.5 is now available. Sync and store your snippets using any folder on Dropbox or iCloud Drive. We'll tell you how to set that up below.

Now you can search your snippets and abbreviations.

To update look in the Purchases tab of the App Store, tap Updates, then tap Update next to TextExpander 3.5.

TextExpander 5 for Mac is coming soon with support for the new Dropbox and iCloud Drive sync. Please update to TextExpander touch 3.5 to take full advantage of new sync options.

What's New in Version 3.5:

  • Sync snippets using iCloud Drive
  • Sync snippets using any Dropbox folder
  • Search snippets and abbreviations
  • Create JavaScript snippets
  • Other minor fixes and improvements

Setup New Sync:

  1. Open TextExpander's Settings and tap Sync Snippets.
  2. Click Save Snippets As… under iCloud Drive or Dropbox.
  3. Select a folder to store your snippets.

Make sure to update your other devices.

  1. On your second device open TextExpander's Settings to Sync Snippets.
  2. Tap on Link To Snippets… under Dropbox or iCloud Drive, whichever you used before.
  3. Locate your Settings.textexpandersettings file and select it. 

If you have an older version of TextExpander touch (3.2.4 or earlier), or TextExpander for Mac (4 or earlier), then you need to keep using the Older Version Dropbox sync.