Drafts, Shortcuts, and blogging

For the past several months, almost all of my blog posts have been written on my iPad. My system for publishing the posts, though, was still Mac-based. It consisted of a set of scripts and Makefiles that would compile the Markdown source of the post into HTML and regenerate whatever new pages were needed to update the site. It did all this locally, on the Mac, and then ran rsync to upload the new and altered pages to the blog server. A good system for all those years I was writing posts on the Mac, but less good if I’m going to be writing mostly on the iPad.

To publish a post written on the iPad, I had to get the Markdown source file over to the Mac (Dropbox made this easy) and then I had two choices:

  1. Leave my iPad, go to the Mac and run the publishing scripts. I almost never did this.
  2. Log into my Mac from the iPad using Prompt and run the publishing scripts.

The second option, in which the Mac was basically an intermediary between the iPad and the server, seemed like a waste. So a couple of days ago I moved all the publishing scripts and Makefiles to the server, cutting out the middle man.

My publishing system is a melange of Python and PHP—Python because that’s what I prefer scripting in; PHP because this used to be a WordPress site and I have some custom PHP from those days that I don’t want to rewrite. A few Makefiles control the scripts to ensure that only the pages that need to be regenerated are. A system like this runs as easily on Linux as it does on the Mac, so I just had to add a library or two and change a few paths here and there to get everything working on the server. Then it was time to do some scripting on the iPad.

First, I needed to be able to upload a draft from Drafts to the server. I already had a two-step action for uploading a draft to Dropbox, so I was more than halfway there.

The source code for a post starts with a header that looks something like this:

Title: Drafts, Shortcuts, and blogging
Keywords: drafts shortcuts blogging
Summary: A change to how I blog means new Drafts actions that use Shortcuts.
Image: https://leancrew.com/all-this/images2018/20181215-Publish%20shortcut%20options.png
Date: 2018-12-15 12:10:23
Slug: drafts-shortcuts-and-blogging

The name for the Markdown source file and the folder into which it’s saved are determined by the year, the month, and the slug. The first step in my uploading action is this script:

javascript:
 1:  // Set template tags for the path and filename
 2:  // of a blog post.
 3:  
 4:  var d = draft.content;
 5:  
 6:  // Set up regexes for header info.
 7:  var dateRE = /^Date: (\d\d\d\d)-(\d\d)-\d\d \d\d:\d\d:\d\d$/m;
 8:  var slugRE = /^Slug: (.+)$/m;
 9:  
10:  // Get the year and month and set the path.
11:  var date = d.match(dateRE);
12:  var year = date[1];
13:  var month = date[2];
14:  var path = '/path/to/blog/source/' + year + '/' + month + '/';
15:  
16:  // Get the filename from the slug.
17:  slug = d.match(slugRE)[1];
18:  
19:  // Set tags for use in other action steps.
20:  draft.setTemplateTag('source_path', path + slug + ".md");

This is almost identical to the earlier script, so I won’t describe it in full. The main differences are in Line 14, which defined the path on the server to the folder where the Markdown source files are kept, and Line 20, which defines the source_path template tag that will be used in the second step of the action.

Drafts1 has action steps for easily uploading to Dropbox, Google Drive, One Drive, Box, and WebDAV, but not for uploading via SFTP. I could install Dropbox for Linux on the server or maybe get WebDAV working on it, but I didn’t really want to install new stuff on the server just to be able to upload files. I could also switch to using Coda or some other editor on the iPad that handles SFTP, but I wanted to stick with Drafts. Because I already know how to upload files via SFTP in Shortcuts, I decided to use the Run Shortcut action step:

Run Shortcut step for uploading to server

This step call the Upload Blog Source shortcut (which we’ll get to in a minute) and passes to it the source_path template tag that was defined above, a line of 10 carets, and then the full contents of the current draft. As you can probably guess, the line of carets is there to provide a distinct separator that the Upload Blog Source shortcut can parse.

Speaking of the Upload Blog Source shortcut, here it is:

Upload Blog Source shortcut

The second step of the shortcut splits the input text, using ten carets as the separator. This creates a list. The next two steps take the first item of that list, which is the source_path followed by a newline, and strips the trailing whitespace. This output is available to later parts of the shortcut through a magic variable. By default, this magic variable would be named Replace Text, but because there is another Replace Text step in the shortcut, I renamed it sourcePath to avoid confusion. Unfortunately, this renaming is hidden when you take a screenshot of a shortcut, which could be its own source of confusion.

The next three steps return to the list of split items created in Step 2, pull out the last item from it, and strip the leading whitespace. This leaves us with the text of the draft.

Finally, the last step connects to the server and runs the cat command to redirect the standard input passed to the step (the Markdown source) to a file defined by sourcePath.

This is harder to explain than it is to do, but it would be easier if Drafts had a native action step for SFTP. I think I’ll put that bug in Greg Pierce’s ear.

OK, now I have an action that saves a draft to the server. I can use Prompt to log onto the server and run the make command that generates the necessary HTML and publishes the new pages. But wouldn’t it be nicer to just have an action that does that directly from Drafts. Of course it would. This is a single-step action that uses Run Shortcut:

Run Shortcut step from Publish action

Boy, that’s dull. Here’s the shortcut it runs:

Publish shortcut

My Makefile has several sections. By default, when make is run without an argument, it runs the sections needed to publish a new post. When given the up argument, it runs the sections needed to update an already-published post. Thats why there are two options to the Publish shortcut.

Publish shortcut options

Many of you are thinking I could have written a shortcut just like this to log in and run make on my Mac, which would have saved me the trouble of moving all my publishing scripts to the server. You’re right, I could have. But I never did because the incentive wasn’t strong enough. It was only after I put the publishing system on the server—something I’ve been meaning to do for longer than I’ve had an iPad—and needed to solve other problems that I felt compelled to write the publishing shortcut. Motivation is funny.

The obvious drawback to setting things up this way is that I’ve now made it harder to blog from my Mac. But BBEdit knows SFTP, so it won’t be hard to teach it how to upload a file to right place. And there are any number of ways on a Mac to run a command on a remote server. I’ll fill those holes soon.


  1. Which is, by the way, Time Magazine’s #3 app of 2018


An unfortunate hole in my portable brain

This morning I got an email from one of my business partners. She’s out of town on a job and needed our FedEx number sent to another lab so they can ship some samples to us. No problem, I thought, I’m sure I have it on my phone. But no, that was one of those things I always meant to save on my phone but never got around to. My partner thought she had it on her phone, too.

Here are the things I have gotten around to saving to my phone:1

Some of these may seem silly, but I’ve made use of almost all of them at one time or another. A couple of years ago, when my mom moved to a nursing home and I needed to close out certain services at her house, I learned that the phone service was still in my dad’s name. She’d never changed it when he died ten years earlier. So I used his SSN (along with my grandmother’s maiden name, which wasn’t saved to my phone but didn’t need to be) to impersonate him with the phone company and get the account closed. That was a little weird.

(I have since learned that friends my age commonly pretend to be their aging parents to deal with customer service reps. I am, however, the only one I know who pretended to be a dead parent.)

As I look through the list, I see that I still haven’t added things I’ve always meant to. In particular, apart from the FedEx number, I should be keeping the account numbers for various insurance policies.

Up until recently, I’ve had (or intended to have) all of this stuff in secure notes in 1Password. As part of my shift to a more iCloud-based system, I’ve copied them over to locked notes in the Notes app. There have been advantages and disadvantages to the change.


  1. And iPad and Macs, but it’s mostly when I’m out with just my phone that I need them. 


License files for Airtable

Shortly after my software license post went up, Jezper Söderlund tweeted me a very good question: How do you handle software that uses a license file instead of a license key? Turns out there’s a simple answer, and I needed it.

After exporting the licenses from 1Password and importing them into Airtable, I had noticed that the entry for Witch, the better-than-stock app switcher from Many Tricks, had no license key. Weird, I thought, but I didn’t follow up on it. When I saw Jezper’s tweet, I realized why.

Witch does, in fact, use a license file instead of a license key to authorize its use. The license file is buried in the Application Support subfolder of your Library folder. 1Password has a system for adding attachments to software license entries, and I had done that when I bought Witch. Unsurprisingly, the file attachment didn’t get exported to the CSV file. I was a little surprised, though, that the CSV didn’t have a field to indicate there was an attachment for that entry.

In any event, now that I knew I needed to handle file attachments, the solution was simple. I added a new field to my Airtable database and chose the Attachment field type.

Airtable field type

With this field added to the database, it was easy to drag Witch’s license file into Airtable. When you click on an empty attachment field in Safari on the Mac, the field tells you it’s ready to have a file dragged and dropped onto it.

Airtable attachment field in Safari

I scrolled through all the other software licenses in 1Password to see if any others had license files. They didn’t, but now I’m ready to handle any new apps that do.


Reorganizing software licenses

As part of the slow process of moving myself away from 1Password to iCloud Keychain, last week I exported the list of software licenses and put them in a database. This took more time than I expected, as I tried out different ways to organize the list.

I have, by the way, nothing against 1Password. It’s a great program and has been a big help to me for many years. But as I try to simplify my computing setup, it seemed best to avoid having a separate program that, as I use it, largely replicates a function of the operating system. Especially when that separate program has moved to a subscription service—I’d rather use that money to pay for software that’s substantially different from what Apple provides.

One of 1Password’s functions that isn’t in iCloud Keychain is the list of software licenses.

1Password software licenses

There are a couple of ways to get the license data out of 1Password:

I started out doing it the iOS way and quickly decided the Mac way would take less time for the several dozen licenses I needed to export. Whichever method you choose, you won’t be pleased with how much fiddling you have to do.

With the data in a Numbers spreadsheet, I figured there were three options:

  1. Just keep it in a spreadsheet. That’s not a bad format for this kind of data, and I could make it available on all my devices by saving it to iCloud Drive.1
  2. Export the spreadsheet out to a CSV file and import that into a database. Airtable would be my choice, as it looks good and works across platforms. I’m not entirely sold on its security2, but software licenses don’t strike me as especially damaging if they get hacked.
  3. Export the spreadsheet to CSV and then turn it into formatted text that can be kept in Notes. This is also available on all my devices and notes have the additional advantage of being lockable. This little Python script reads the CSV and formats it for a note:

    python:
     1:  #!/usr/bin/env python
     2:  
     3:  import csv
     4:  
     5:  print("Software licenses\n")
     6:  with open('1p.csv') as csvfile:
     7:    reader = csv.DictReader(csvfile)
     8:    for row in reader:
     9:      print(row['app'])
    10:      for f in reader.fieldnames[1:]:
    11:        if row[f]:
    12:          print("{}: {}".format(f, row[f]))
    13:      print()
    14:         
    

    It opens the CSV file named 1p.csv, and writes out every record in its own paragraph. The first line is the name of the app, and the subsequent lines are all the other fields in

    key: value
    

    format. After importing to Notes, it looks like this:

    Software licenses in Notes

    The disadvantage of using Notes is that I have to type everything in myself when adding a new entry. Also, I can’t just add it to the bottom if I want the list to stay alphabetized.

Although I’ve done all three of these to see how they work, I think I’ll stick with the Airtable solution. It’s easier to scroll through than Notes and has a single-entry view that Numbers doesn’t provide, which is especially convenient when using an iPhone.

Single entry in Airtable


  1. And password protect it, too. Thanks to Teddy Svoronos for reminding me. 

  2. No particular reason for this; I’m just generally skeptical of cloud security, especially with things I’m not paying for.