"Chopping" a Draft.

A new method for using Drafts to automatically repeat an action on a series of drafts pulled one by one from a list.

A few days ago I was sitting in a Starbucks debating on how I could possibly get a batch import action to work. The goal was to take a list of custom URL actions and somehow create another action that would import them all, automatically, into Drafts. A few months back I created the import action, which imported a single action into the action list from a draft made up of the name of the action in the title and the URL of the action in the body. This action helped a lot for laying out URL actions where I could see them in a draft and then importing without ever having to go through all the menus in settings and copy and pasting things and typing into different boxes just to import one action. Back when I made the import action, my next goal was to make one to batch import actions from a list, but at that point in time it was impossible.

Today, however, with a combination of the new features from Drafts 3.0 and Launch Center Pro 1.1, I was able to design a way to batch import actions. What I find really interesting though, is the method that I came up with to do it. I think this method, which I refer to as "chopping" a draft, could actually be extremely useful in a lot of other situation besides batch importing.

Variables

Before you understand how chopping a draft works, you have to understand how Drafts handles variables. In any given URL action, you can include a max of three variables. Two of these are drawn from your Draft, the [[title]] variable, and the [[body]] variable. If [[title]] is placed anywhere in your URL, then when the action is run Drafts replaces [[title]] with an encoded version of whatever text you have in only the first line of your draft. (That is, all the text until the first line break. If you have a paragraph of text before you make a line break, the entire paragraph will be [[title]]. If your draft has no line breaks, the whole draft will be [[title]].) If [[body]] is placed anywhere in your URL, then when the action is run Drafts will replace [[body]] with an encoded version of whatever text is in your entire draft after the first line. (That is, all the text after the first line break.) Drafts is incapable of differentiating any additional line breaks after the first one, so even if you have one word on your first line and twenty paragraphs after it, all twenty paragraphs would be substituted for [[body]] and only the one word would be substituted for [[title]].

Before Drafts 3.0, these were the only two variable Drafts could handle (other than the [[draft]] variable, but that takes the entire draft, a mixture of both [[title]] and [[body]], so it is not useful for the task I am discussing). The import action requires the name of the action in the [[title]] position, and the URL of the draft in the [[body]] position. Because of this, before Drafts 3.0, there was no way to batch import anything because there wasn't another variable to store the rest of your actions in as each was imported. With Drafts 3.0, however, there exists a third variable: [[clipboard]]. The [[clipboard]] variable, not surprisingly, is replaced, when an action is run, by whatever is currently in your clipboard. There is also a built in "Copy to Clipboard" action that allows you to copy a draft, or part of a draft, to your clipboard. These two features are what make chopping a draft possible.

How it Works

In order to chop your draft, you must have a list of whatever data you want to perform a specific action on. For this example I am simply going to use the data I learned it with, a list of actions that I want Drafts to automatically import, one by one. Chopping basically works by utilizing Drafts' ability to separate the title of your draft from the rest of it in order to "chop" that title line out of the draft. The [[title]] is copied to the clipboard and the [[clipboard]] is used to make the next draft. You can then perform actions on the [[clipboard]] draft while the rest of the last draft, containing the remaining items in your list, is still preserved by the [[body]] tag (although it becomes the [[draft]] tag as soon as it enters the next action) until you're ready to chop out the next section. This is probably pretty hard to visualize, but bear with me and I'll explain better when I show you the actions themselves.

There's one last part to this. Since the [[title]] variable can only be made up of one line with no line breaks, that means that any draft created from it would only have one line as well. There's no way for my import action to work on a draft that has the name and URL of the action on the same line. However, if you take a properly formatted action (that is, the name of the action on the top line alone, then a line break, then the URL of the action) and URL encode it, it all changes into being on a single line, the line break transformed into the encoded format for line breaks, "%0A". Now your URL action and name are combined into one line which can be your [[title]] line, all you have to do is decode them once they've been chopped out of the draft list.

Enter Launch Center Pro 1.1. LCP 1.1 has a built in feature allowing you to take the contents of your clipboard and both URL encode or URL decode them. So if we throw in a quick action to jump over to LCP, get the clipboard decoded, then jump back into Drafts, we just switched from having a single line of encoded text on our clipboard to having two lines of decoded text. Create a new draft from the [[clipboard]] variable, and there you have it: a draft in the proper format to be imported as a URL action. The action sequence now imports that action and then calls the [[draft]] variable, which I carefully pulled into the end of each action bringing us to this point, to create a new draft with the entire rest of your list intact. Now, however, the second line of the list is in the [[title]] position, because the previous first line was removed and put on the clipboard.

The final step is to call the original action one more time, then the process is restarted and your second action is copied, decoded, and imported. The entire sequence is actually an infinite loop. It doesn't end until the entire contents of your list have been imported, then it halts with an error as it tries to create a draft with an empty variable. (You have to make sure to add one extra line to the end of your list that says anything in order to import every action you are trying to. When only one item remains in the list, that's when the error occurs to end the loop. This makes sense if you look at what the actions are trying to do, but I won't explain it here. I just add the word "burner" or "end" on it's own line at the end of all the actions I'm importing so that everything works properly. Don't worry, Drafts won't try to import an action that just say "burner," it will error before it gets there.)

The Actions

So without further blathering about the theory and mechanics of the sequence, here are the instructions and the four simple actions that make it work:

Begin with a draft formatted in the way I explained above: an encoded list of action names followed by line breaks and then the URLs for these actions. Here's an example with three of the actions from my Drafts 3.0 Stress Test. Your draft should be formatted identically to this, except with whatever actions you want in substitute of the example ones I'm using below:

"stresstestDue%0Adue%3A%2F%2Fx-callback-url%2Fadd%3Ftitle%3D%5B%5Bclipboard%5D%5D%26x-source%3DDrafts%26x-success%3D%7B%7Bdrafts%3A%2F%2Fx-callback-url%2Fcreate%3Ftext%3D%5B%5Bclipboard%5D%5D%26action%3DstresstestInstapaper%7D%7D

stresstestInstapaper%0Ax-callback-instapaper%3A%2F%2Fx-callback-url%2Fadd%3Furl%3D%5B%5Bbody%5D%5D%26x-success%3D%7B%7Bdrafts%3A%2F%2Fx-callback-url%2Fcreate%3Ftext%3D%5B%5Bdraft%5D%5D%26action%3DstresstestFantastical%7D%7D

stresstestFantastical%0Afantastical%3A%2F%2Fx-callback-url%2Fparse%3Fsentence%3Dtomorrow%2520%5B%5Bbody%5D%5D%26notes%3D%5B%5Btitle%5D%5D%26x-success%3D%7B%7Bgooglechrome%3A%2F%2F%7D%7D

Burner."

First, the "Chopper" action. In this case, it should probably be renamed Batch Import, but I called it Chopper originally before I knew if it would work, and I kind of like it. Here's the action:

drafts://x-callback-url/create?text=[[title]]&action={{Copy to Clipboard}}&x-success={{drafts://x-callback-url/create?text=[[body]]&action=textDecode}}

Choose Chopper from the action list to run it on your list of actions. It will pull the [[title]], which is the first action in your list, and copy it to the clipboard. Then the x-success parameter creates a new draft using the [[body]] parameter. You just chopped your draft: the first line is now in the clipboard instead of in the draft, and the rest of your list has now been bumped up so the second list item is in the [[title]] position. Now textDecode is run on the draft of [[body]]:

launchpro-clipboard://x-callback-url/convert?format=Urldecode&x-success={{drafts://x-callback-url/create?text=[[draft]]&action=chopper2}}

textDecode is a Launch Center Pro action which takes whatever was in your clipboard and decodes it from URL format to regular plain text format. This means that what was originally in your clipboard, the first action, has gone from this:

"stresstestDue%0Adue%3A%2F%2Fx-callback-url%2Fadd%3Ftitle%3D%5B%5Bclipboard%5D%5D%26x-source%3DDrafts%26x-success%3D%7B%7Bdrafts%3A%2F%2Fx-callback-url%2Fcreate%3Ftext%3D%5B%5Bclipboard%5D%5D%26action%3DstresstestInstapaper%7D%7D"

To this:

stresstestDue due://x-callback-url/add?title=[[clipboard]]&x-source=Drafts&x-success={{drafts://x-callback-url/create?text=[[clipboard]]&action=stresstestInstapaper}}

Then the action "chopper2" is run on [[draft]], the variable that is currently still filled with the rest of your list. chopper2, however, only effects the [[clipboard]] variable. The reason we have to keep running actions on the [[body]] and [[draft]] variables when they only affect the [[clipboard]] variable is that this is what keeps pulling the remainder of your list along behind the action you're manipulating. If we left [[draft]] behind in LCP and only ran actions on [[clipboard]], then we would have lost the rest of our list in the thread of the sequence, rendering the process useless. So we run chopper2 on [[draft]], but it only effects [[clipboard]], as so:

drafts://x-callback-url/create?text=[[clipboard]]&action={{importURL}}&x-success={{drafts://x-callback-url/create?text=[[draft]]&action=Chopper}}

This action creates a draft from [[clipboard]], which is our decoded action name and URL, then it runs the importURL action on that draft:

drafts://x-callback-url/import_action?type=URL&name=[[title]]&url=[[body]]

The importURL action quite simply imports the draft into your action list using [[title]] for the name of the action and [[body]] for the URL. Drafts gives you a message saying it successfully imported your action, then the x-success parameter from chopper2 kicks in, returning to your still intact list of actions and once more running Chopper on them. Now, however, your list is one less, as the first action was already removed. Chopper now chops out the second action, decodes it with textDecode, sends it back to Drafts and imports it via chopper2 and importURL, then runs Chopper once again. The process repeats until it chops out the last item in your list before "burner." Burner is literally just a burn line. When Drafts tries to run Chopper on it, it copies the word "burner" to the clipboard, then tries to create a new draft from the empty list that remains. Since that's not possible, an error occurs and the sequence grinds to a halt. Check your action list and all the actions will now be imported.

Variations

So there you have it, my "chopping" method for dealing with lists of data in Drafts. You could theoretically use this for a whole lot more purposes than just importing actions. For instance, if you have a long list of events you want to import into Fantastical, something that previously would be a long and annoying task of tapping the plus button, copying, pasting, tweaking times and words, and generally is just an extremely annoying process, I'm sure a variation of this chopping method could be used to take a list that you type out yourself, and import all of the items one by one without you having to do any of the annoying tapping, typing, tapping and holding and trying to position the magnifying glass correctly, and all the other annoyances that arise from the sad state of affairs of text input on iOS. That's just one more of the many options this could provide. I'd love to hear of any other ideas anyone has, and I'd be happy to do the tweaking to make each variation possible if anyone wants me to. For that matter though, said tweaking should in fact be extremely easy. The chopping sequence will actually remain exactly the same for every action involved except chopper2, where you simply need to substitute "importURL" for whatever action you want to be run on the items in your list.

Sharing

One interesting thought I had regarding using this method for importing URLs, as I discussed above, is that this could turn out to be a great way for us URL action buffs to share URLs with each other. As of Drafts 3.0, I think we could technically share the Dropbox files of our action lists to have access to each others' lists, but that just overwrites everything. This method is more of a sync, adding all of these actions to the ones you already have instead of replacing the entire list. Better sharing of actions has been something myself and a lot of others have been interested in since Drafts 2.5 originally allowed their creation.

If you want to test out this idea of sharing actions, go to the Import Links section of my Drafts 3.0 Stress Test. You can use the first link, as it will tell you on that page, to create a new Draft formatted in the proper manner for the batch import to work. Import the actions below and run Chopper on the draft and it will import all the URL actions from the sequence from the single draft you will have opened.

Here are the direct import links for the actions required to allow chopping of your drafts. Feel free to use them however you want, but I'd appreciate it if you'd tell me about anything cool you may use them to accomplish.

Get in touch with me from my contact page.

Direct Import Link for importURL Action

Direct Import Link for Chopper Action

Direct Import Link for textDecode Action (Requires Launch Center Pro)

Direct Import Link for chopper2 Action

Post to ADN