The Quest to Automate my Workout Log

I recently spent more time than I really want to think about to change one tiny thing about my workout log workflow. I would have given up long before, but I’m stubborn, not being able to solve a problem — especially one I think I should be able to solve — tends to make me fixate on it, and I thought that what I learned would pay dividends in the long run.

You need a few apps to copy this specific workflow. However, I think it can serve as a more general example of how to chain multiple apps together.

First, you need at least Drafts 3 (apparently, this version is no longer available, but I’ve kept the link intact anyway). This is the linch-pin of the whole series of actions. The newly-released Drafts 4 will certainly work as well. Based on its predecessor, I insta-bought Drafts 4 when it came out, but haven’t fiddled with it much yet. Hell, as of this writing it’s still 50% off, so go buy it now!

Drafts is highly recommended for geek users — especially URL automators — but I would also recommend it as a very fast-launching and simple app for anyone who works with text a lot on their iPhones. I previously wrote about my writing workflow, which included a section on Drafts, or you could read about it on the developer’s website, Agile Tortoise.

You also need Dropbox; TextExpander (the new version now features a custom keyboard in iOS 8 so you can use your snippets in any app); Editorial (from the same guy who made Pythonista); Launch Center Pro; and Day One.

The main URL is called from Launch Center Pro, using its built-in support for automated URL encoding using double braces, i.e.: {{text to be encoded}}

drafts://x-callback-url/create?text=Notes/[textexpander:ldate]&action={{Copy to Clipboard}}&afterSuccess=Delete&x-success={{launch://x-callback-url/dropbox/clipboard?path={{[clipboard].txt}}&afterSuccess=Delete&x-success={{drafts://x-callback-url/create?text=[clipboard]&action={{Hashtag}}}}}}

Why do you need to encode parts of the action? If you don’t, then it won’t be interpreted properly. The action either won’t work at all, or will error-out at some point during the chain. I initially beat my head against the wall trying to get several layers of encoding to work, even going so far as to manually encode sections using online tools, but never got anything over 3 layers deep to work properly even though I swore it should work. This is part of why I had to call part of the process through a Drafts action, which I’ll detail later.

The TextExpander snippet ldate you see in in the first action expands into the date format I chose to use for my date tagging, ISO 8601 (see Randall Munroe’s brief argument for using it here). I use this date as the file name for my workout logs.

The above action:

  1. Creates a note in Drafts using TextExpander to generate the current date as essentially a variable in the action. Notes is the Dropbox directory where I keep all of my text notes. Then it …
  2. Copies that path to the clipboard, deletes the unnecessary draft, and throws it to Launch Center Pro, which,
  3. Appends a file extension, which is .txt in this case. (It caused me some frustration before I eventually found that some of my files, but not all, were in fact not plain text files, but had Markdown .md or MultiMarkdown .mmd extensions.) The action won’t work if you don’t specify an extension. I found out the hard way, through trial and error. Mostly the latter.
  4. This provides the path for Launch Center Pro’s built-in Dropbox action to get the text of a file previously saved in Dropbox.
  5. The contents of the retrieved file are fed back to Drafts as a new document.
  6. After Drafts gets this text, it runs the Hashtag action to continue the chain and again deletes the unneeded draft.

The Hashtag action in Drafts 3 was one I created to implement this chain. You can create your own URL actions by going into Settings → Custom Actions → URL Actions. You can create actions entirely in Drafts itself, which is no surprise considering that the spec for x-callback-url originated with Greg Pierce of Agile Tortoise.

(Shout out to Alex Guyot at The Axx for his Drafts URL creation snippets, which make typing this kind of stuff in iOS much easier, and which provided me with a helpful framework for the initial version of the URL. Also, his Drafts 3.0 Stress Test gave me some hints I needed to get the rest of the action working when it looked like I was insolvably roadblocked.)

The Hashtag action code is:

editorial://?input=[[draft]]&command={{Hashtag}}&afterSuccess=Delete&x-success={{dayone://post?entry=[[output]]}}

You can see that this action sends the text of the file we grabbed with Launch Center Pro to Editorial, which also runs an action I (unoriginally) named Hashtag. What does this do? After some abortive attempts to learn how to pipe things through Pythonista using the replace command, and being stymied by not knowing enough to get the output anywhere useful, I experimented with Editorial’s built-in find/replace tool. You can save really elaborate workflows, but all I needed was that simple character change from @ to #, so that’s what I used.

(I now know that I probably could have done this whole process in Editorial, without doing all this app jumping, but Editorial was literally the last app I installed in all this tinkering around, and giving up without making the x-callback-url work would have felt like defeat.)

Once Editorial does a search-and-replace, the output is fed back to Drafts, which sends it to Day One as a post, and deletes the superfluous draft.

Without the deletion actions, you’d end up with several drafts in your Drafts archive, unless your default is to delete a draft upon use. My default is to archive and occasionally purge, since sometimes I want to perform another action on the same draft, and in case something doesn’t work properly I don’t want to have to retype my note if I can just archive it.

The action does require interaction part of the way through. I actually don’t know for sure if it’s one of the apps involved (at a guess, probably Launch Center Pro), or a system dialog, but I do have to tap Allow to let part of the URL callback proceed. There is another minor interaction as Day One sees the hashtag and asks if I want to add it as a native tag. Of course I tap, “Yes” because that was the point of this overly-elaborate exercise.

So there you have it, a Rube Goldberg machine that jumps between 4 different iOS apps, and uses the capabilities of a 5th, all just so that I don’t have to copy and paste manually, position a cursor, and hit a delete key. Is It Worth the Time? Maybe.

By my earlier calculus, I’ve probably wasted several thousand yen of effort on this problem if you only consider the time saved. But, I also learned a lot about URL schemes and iOS automation, which I have already leveraged to create other time-and-effort saving actions. Plus, success! Nothing feels quite like solving a problem that had previously defeated you.