Tweet This Post

If you get a Spotify share URL like http://open.spotify.com/album/3eAA4fvTVttgUlE43vRVMq and open it in Safari for iOS, use this bookmarklet to jump directly to that artist/album/track in the app:

javascript:window.location='spotify:'+(window.location.href);

To install, you can either set it as a bookmarklet in Safari for Mac and sync with iCloud, or do the following:

  1. Bookmark any page in Safari for iOS and call it Spotify.

  2. Go to edit bookmarks, and replace the URL of that bookmark with the javascript above.

06/19/14; 03:35:31 PM

Tweet This Post

I've written a previous post on how to schedule a text message for later with Due and Launch Center Pro. However, now that LCP's encoding grammar has simplified, I'd like to revisit the topic. First off, an action to save a text in Drafts:

drafts://x-callback-url/create?text={{launch://messaging?to=8005551212&body=[prompt]}}

Click on this link to import it onto your iOS device.

Tap on the action, enter your text message, and an encoded launch://messaging URL scheme is saved in Drafts. When you are ready to send the text message, just make links clickable and tap on the URL scheme. It will open the text message in Messages to the designated recipient (change 8005551212 to his or her cell number).

The Contact Picker

LCP now has a contact picker -- [contact] -- that will allow you to choose a contact when you start the action. I tried creating the action above by substituting the phone number with [contact] -- the action can be imported here -- but it does not work.

drafts://x-callback-url/create?text={{launch://messaging?to=[contact]&body=[prompt]}}

The problem is that the body text is not encoded, so you get something like this:

 

Screenshot by @tahewett

 

I could not figure out how to fix this, so I wrote a pretty complicated action that does do the job. (Import it here).

launch://x-callback-url/clipboard?text=[contact]&x-success={{texttool://x-callback-url/transform?text=[prompt:your message]&method=encode&clipboard=0&x-success={{drafts:///create?text={{launch://messaging?to=||clipboard||&body=[[output]]}}}}}}

How It Works

First, the action asks you to pick a contact, and the number you choose is saved to the clipboard.

Then the action prompts you to enter your message. TextTool url-encodes your message, but does not save it to the clipboard (because we need the clipboard for the contact's number).

Then the action tells Drafts to create a new draft, the launch://messaging action. The body of the message is the [output] value carried from TextTool, and the to field is the clipboard contents, which -- because it has carried over two different x-successes -- needs to use ||clipboard|| to work, as explained here:

/create URL scheme now supports a special “||clipboard||” tag within the text parameter, which will substitute the contents of the clipboard at the time the “create” URL is opened. This can be used in an x-success callback URL to allow capture of a clipboard value that changed before returning to Drafts. Note the pipe characters, not brackets. This tag is not evaluated other time, only on /create URLs when processed by Drafts.

06/19/14; 11:35:06 AM

Tweet This Post

Here is an example of an RSS feed for @newyorkcity. If you click on a link, you get to see the raw image. How I did it:

1. Use this IFTTT Recipe

Customize this IFTTT recipe with the Instagram profile you want to use, as well as the tag(s) you want. (Note: this recipe requires a Pinboard account, which requires a one-time fee.)

2. Wait Until the Recipe Has Been Triggered

Here is the newyorkcity_instagram tag for my Pinboard account. To get the RSS feed, I follow these instructions to get the following:

https://feeds.pinboard.in/rss/u:kishner/t:newyorkcity_instagram
06/18/14; 02:46:43 PM

Tweet This Post

The latest update to Launch Center Pro has made it easier to create nested lists. Previously one had to use launch://?url= but now that is no longer necessary. Here is an abridged version of my LCP action to open albums in Ecoute:

ecoute://play?terms=[[list:Artist|Eminem=[list:Album|Marshall Mathers|Recovery]|Foo Fighters=[list:Albums|The Colour and the Shape|There Is Nothing Left to Lose]|Pharrell Williams={{Pharrell Williams}}|Search=[prompt:Search]]]

When I tap on this action, it presents a list of artists (Eminem, Foo Fighters, Pharrell Williams, and "Search"). If I tap on either of the first two, I am presented with a list of albums, and when I tap on the album name, that album auto-plays in Ecoute. If I tap on Pharrell Williams, G I R L automatically plays because I only have one album by him in my library. And if I tap on Search I am presented with a prompt, and if my query matches something in my music library, then it starts playing. (Thanks to Eric Pramono @epramono for help encoding this last part.)

The key to this nested list is that the first list is surrounded by double brackets and the embedded lists are only surrounded by single brackets. Two brackets means don't encode this. Because the first list is not encoded, I have to encode Pharrell Williams in double curly brackets since his name does not included an embedded list. And the search prompt only needs single brackets because they encode the prompt text.

The Spotify URL scheme is a bit more complicated. Here is an abridged version of my Spotify action:

spotify:[[list:Pick a List|Ali Farka Touré={{http://open.spotify.com/artist/3mNygoyrEKLgo6sx0MzwOL}}|King's X=[list:|Xv=http://open.spotify.com/album/792TsZibmmEiOCL2rEoJvm|Please Come Home....Mr. Bulbous=http://open.spotify.com/album/2ZyMISUxP7MLzxZCZLHEHJ]|Yes=[list:|Fragile=http://open.spotify.com/album/4X6gq5bgpGXcHINlFWzriM|Relayer=http://open.spotify.com/album/6MK9yp7hFeOLeR7F1hsBp6]]]

When I click on this action I would be presented with Ali Farka Touré, King's X, and Yes. Following the pattern above, if I don't have an embedded list for an artist, I just encode that value with double curly brackets. Otherwise I just use single brackets around the embedded list.

The URL scheme for Spotify is spotify:SPOTIFY_URL. You can get the Spotify URL from the app (in the share settings) or via a google search. I've even written a search tool using their API here.

How to Manage These Actions

One of the major downsides of LCP is that it's difficult to edit very long actions in the app's editor. However, there is a way around this. Import this action or just create a new action called Import and enter this string:

launch://import?url=[dropbox-text:ACTION.txt]

Then keep your music actions in their own text files in Dropbox. For example, I currently have my unabridged Spotify action as a text file called spotify.txt in the root of my Dropbox folder. I then just use the following action to import it:

 launch://import?url=[dropbox-text:spotify.txt]

LCP will import that text file, and ask you if you want to add it, just like if you were to use one of the importable actions at launchcenterpro.com. This way, you can make your edits in any Dropbox text editor instead of within the app itself.

06/16/14; 11:57:07 AM

Tweet This Post

Tweetbot has a list of URL schemes, the most recent of which is one to jump immediately to a Twitter list. I have never used it until now because I never knew how to find a list's ID. But now that I've figured it out, I'd like to share it with you.

The full scheme is

tweetbot://<screenname>/list/<list_id>?callback_url=<url> 

but you don't need to include the ? parameter unless you want to go somewhere other than your most recent timeline view in the app.

Let's say I want to view my ios Twitter list. To get the list ID, I view the source of the web page and search for data-list-id. In this example, the source code includes data-list-id="79393622". I take that value and put it in the URL scheme:

tweetbot://kishner/list/79393622

If I include this as an action in Launch Center Pro, then clicking on it will bring me right to that list.

If I have a preferred app I want to go to after I click the Cancel button, I can include the callback_url parameter, which is an encoded URL. If I want to go to Launch Center Pro:

tweetbot://kishner/list/79393622?callback_url=launch://

If I want to go to an actual website like google.com instead:

tweetbot://kishner/list/79393622?callback_url=http%3A%2F%2Fgoogle.com

Enjoy!

06/16/14; 09:21:52 AM

Tweet This Post

I am very much a newbie at bash scripting in Terminal, but I felt tempted to replicate the tool I built at TaskPusher for the command line: namely to send text and an optional action to Drafts from a Mac OS computer.

TaskPusher is a PHP web application that sends an url-encoded string to Pushover, a notifications app for iOS. Pushover already provided the code to send notifications from the Unix command line so I only had to make a few modifications to send a message to Drafts.

Before we begin, I need to qualify that I literally have only started bash scripting this week, so please bear with me if there are any inefficiencies or errors. The script works, but if you have any suggestions please comment below in the Disqus widget or send me a tweet.

The first challenge is that all the text after the Drafts URL scheme drafts:///create?text= needs to be url-encoded. I found a basic sed find/replace script here and I copied the code snippet into this gist:

 

 

Just add this in a text file somewhere in your directory and call it urlencode.sed. I haven't gotten to move new scripts into /usr/local/bin (or what-have-you) so in the pushover script below you will have to precede urlencode.sed with the directory path. In my working script I replace it with ~/j/scripts/urlencode.sed.

I named the following script pushover but you can call it whatever you want:

 

 

How to Run the Script

If you haven't already, purchase Pushover in the app store, create an account and get your user key. Then create an app in Pushover and save the API token. Where it says $APP_TOKEN and $USER_KEY enter yours in the script.

Now go to Terminal. You need to set one or two variables to send to Drafts: the message and the action. The message is the actual text of your draft. The action is the exact wording of any of the actions in the Action Directory. For example, I may want to send text to Due: 6pm pick up prescription. In Drafts, the action is called Send to Due. So on the command line, I type the following:

export message="6pm pick up prescription"

export action="Send to Due"

pushover

(In my case, I type ~/j/scripts/pushover. If Terminal says you don't have permission to run the script, type chmod 700 pushover.)

Your notification will be sent to Pushover, and you'll get a status response on the command line. When you get your notification, just swipe to open it, and tap on the URL string. In the example above, it would look like

drafts:///create?text=6pm%20pick%20up%20prescription&action=Send%20to%Due

When you tap on the URL, it will send the text to Drafts and tell Drafts to send that text to Due.

If you just want to send text to Drafts and not immediately act on it, just leave the action variable null. To clear the action variable from a previous notification, type unset action.

There are additional variables you can add to the script (as defined in Pushover's API) if you want to send your notification to a specific device or customize the sound. Just add an additional line in the script, like -F "sound=cashregister" \.

05/23/14; 08:47:30 AM

Tweet This Post

I recently showed how you can read RSS feeds in Fargo. Did you know that you can "subscribe" to complete OPML lists in Fargo as well? Feedshare.net is a place where people share their feed reading lists. If you want to see what Brent Simmons reads, go to his share page and grab his OPML link. Then go into Fargo and add this link as an include.

I just typed "Brent Simmons - Inessential" on a new headline and added the following attributes to the headline:

  • type="include"

  • url="http://ranchero.com/downloads/BrentSubscriptions.opml"

I then expand the headline to see all the feeds it includes:

 

 

and then use the "View Feed" script (outlined in my previous blog post) to read one of the feeds:

 

05/22/14; 09:32:41 AM

Tweet This Post

Eric Davis has written a script to enable a user to read RSS feeds in Fargo. The script does not beautifully render the contents of the description tag, but if you want a quick-and-dirty solution, this will work. For example, if you're compiling research in an outline and only plan to check a related RSS feed when you're working in that tab, you can just update the feed there.

At bare minimum, you need a menubar.opml file. Add the following script to that outline:

 

 

This script calls a longer script. I suggest you copy this entire page to your clipboard, paste it into a new text file, title it rssReader.js, and save it somewhere in your Dropbox. Then make that file shareable and replace DOMAIN.COM/rssReader.js in the first script with that Dropbox URL. (Mine looks like https://dl.dropboxusercontent.com/s/.../rssReader.js.)

How to Use the Script

In any outline, type the name of a blog on a headline. Then all you need to do is add the RSS feed as the value of the xmlUrl attribute. You can use this script to easily add a feed:

 

 

You do not need to add the type="rss" attribute to this headline to make it work.

Then go to your scripts menubar, choose View Feed, and the items will show below the headline. If you open the headline of a title, you will see the description content for that feed. (If a publisher chooses to include the entire content of a post within the description tag, it will all be formatted as one long headline, so it is not ideal for reading, but rather for getting a sense of whether you want to read the full post at the publisher's site.)

Reading the Full Post

If I want to read the full post, I make sure the cursor is on the headline of the post title, and I view it in Instapaper without saving it, or save it to Instapaper:

 

 

Or I can just read the post in a new window:

 

 

A Keyboard Shortcut

I use a keyboard shortcut to trigger the View Feed script. If I could remember who wrote what I would provide credit, but unfortunately I don't remember -- I grabbed these ideas from one of the Fargo google groups and/or the community feed that existed when Fargo was first launched.

First, create a text file called myVerbs.js and put it in your /Apps/Fargo folder.

Put the following code in it:

 

 

(You can change jeffVerbs to daveVerbs or whatever you want as long as you use the name consistently. And make sure to replace domain.com with your shareable Dropbox URL.)

Then, in Fargo, click on your name at the top right, then choose Settings and go to the Code tab. Put this in the Startup field and hit Save:

 

 

After you reload Fargo, you should be able to have your cursor on a headline that has a feed and hit Control-E to trigger the View Feed script. (Note that this totally depends on whether there is a conflicting mapping on your computer. I use Chrome for Mac and it works for me.)

05/19/14; 03:26:20 PM

Tweet This Post

I haven't "clubbed" for a long time -- I don't like stay up super-late (even on weekends) and dance clubs are not really my scene. Mostly I stay within my 5Rhythms cocoon, regularly attending Tuesday and Friday classes in Manhattan.

However, I have followed Tasha Blank for years as she's DJ'd at more holistic spaces in the city. She started with Get Your Dance On first at Brooklyn Bowl and then at various yoga studios, and over the last year she has been DJing at The Get Down at Cielo.

Cielo is an EDM dance club in the meatpacking district, where the doors don't even open until 10pm. But The Get Down starts at 7, so that you can enjoy the clubbing experience and still get a decent night of sleep before going to your 9-5 job (if that's your lifestyle). But unlike the yoga studio dance experience, at Cielo you can drink (in fact you need to be at least 21 to enter) and you have to wear shoes.

I showed up shortly before 7 as the 1/2-hour pre-dance meditation was wrapping up. I felt in my comfort zone because a great number of people at the event were familiar faces from 5Rhythms classes or other dances hosted by Tasha. The music was great -- other DJs were Soultek and Sascha Lewis, and they were accompanied by live violinist Jourdan Brandt and vocalists (for lack of a better word) Akil and Elana Meta.

The floor got more progressively packed as time passed (it's not terribly large to begin with) so I danced at a peripheral location for a while and then edged myself back in. And then the vibe shifted. There were people on the dance floor holding drinks in glasses. (Maybe I just haven't been to a dance club in ages, but who brings glass onto a dance floor?) One glass broke and a few people helped pick up shards. And then more and more "civilians" started entering the space.

I know I am probably just being judgmental, but it seems to me that there are Dancers and then there are Muggles. Anyone who regularly goes to 5R is to me a dancer. He is not dependent on alcohol to allow himself to move freely. She doesn't just stand in a circle on the dance floor with her friends. As more and more "normals" joined the floor, I felt less and less comfortable. (To begin with, I don't feel terribly safe around the combination of "traditional males" and alcohol consumption.)

Another element of the evening that had its pluses and minuses was when the same subset of people would take turns dancing in the middle of a circle, usually doing B-boy or hip hop moves. I'm all for spectacle, but after a while it just seems like a form of grandstanding, not to mention disruptive when there's not much space on the dance floor to begin with.

All in all, I danced for a good 2 1/2 hours to excellent music around many people from my dance community, so it was overall a positive experience. My assessment is that if it were not in a real dance club, most of the negatives described above would not have been present. But I can see how The Get Down reaches that "happy place" for dancers who miss the clubbing experience but don't want to be up until 3am to do it.

05/16/14; 09:10:04 AM

Photo credit: Antonio Rosario via Creative Commons license

I live in Brooklyn and don't own a car. I like that I can travel throughout the city without one, and I feel good that my carbon footprint is smaller than that of a car owner. However, the subway can be an unpleasant experience.

Last night, someone was pissing right on the subway platform (at a column), in front of anyone who happened to be around. And this morning the smell of the subway car I entered was so offensive (a homeless person was sitting at one end) that I debated whether to change cars at the next stop even though this leg of my commute was only two stops.

I know Mayor de Blasio has a grand plan for affordable housing, and I understand that -- for a homeless person -- being "underground" is probably much safer than being on the streets. But when many people are sharing a small space, the actions (or scent) of a single person can mar everyone else's experience.

I know I have it much better than the people about which I am complaining, but I wish the city would do something about it.

End rant.

05/14/14; 08:31:43 AM

This is me dancing there in the back (wearing the elbow compression band) at an event called Morning Gloryville NYC. It's like clubbing, but from 6:30-10:30 am, and without alcohol.

Here's a video on Instagram and the mp4 or just view it below:

Media Coverage

The Daily Beast

Metro

Shape

Wall Street Journal

05/07/14; 02:49:42 PM

Tweet This Post

Last night, my 16-year old daughter and I saw Alter Bridge live at the Best Buy Theater in Times Square. At the end of the concert, my daughter said, "Everyone here is white." I looked around, and indeed she was right. I saw absolutely no one who looked of African, Latin or Asian descent until we walked out of the auditorium, when we saw one African-American teen. There were also very few women (even though there seems to be a rabid love of Myles Kennedy among women of the internets).

On the train home, I was explaining why I thought the audience primarily consisted of white (and presumably straight) men. Alter Bridge's rhythm is very straight, by which I mean it is lacking that ineffable quality in music that makes you want to shake your booty. Alter Bridge is most definitely head-banging music. I believe that African and Latin American music is more based on movement of the hips, not the head. Hence, Alter Bridge doesn't (typically) attract people of color.

As a dancer who regularly practices the Five Rhythms, I know that letting go of your head is associated with the rhythm of Chaos. However, head-banging is isolated from the rest of the body (unless one is making upper arm movements into the air with one's fist), whereas in Chaos one lets go of the head and everything else below the neck. One rarely sees the White Male moving his hips, unless he is comfortable moving out of his White Male box.

About the Author

Jeffrey Kishner is a white male, and Alter Bridge is his favorite rock band.

04/25/14; 08:50:49 AM

Tweet This Post

Following up on a previous post using nested lists in Launch Center Pro to perform search queries in Due, I've written an action to immediately play albums in Ecoute.

If you're reading this on your iOS device, tap on this link to install the action. You can then adapt it to your needs.

Here is the action:

 

 

The opening is standard for nested lists, it's just launch://?url= followed by itself, URL-encoded.

It's followed by a simple list:

[list:|Alter Bridge=|Eminem=]

The complicated part is the lists inside the lists.

If we URL-decode everything between the first = and the | before Eminem, we get:

launch://?url=ecoute%3A%2F%2Fplay%3Fterms%3D[list:|Fortress|One Day Remains=One%20Day%20Remains]

It starts with yet another launch://?url= followed by an URL-encoded ecoute://play?terms=, which is the Ecoute URL scheme to play the results matching a search query. Then there's the second list. The key thing to note here is that any album title containing more than one words has to be URL-encoded, so I had to stick in the definition for One Day Remains.

Below are screenshots of what the first two steps should look like. (I added Artists and Albums respectively after the list: because LCP was for some reason putting "Brightness" at the top of the lists.)

04/01/14; 09:11:41 AM

Tweet This Post

The following script lets you add a Google Map to your Fargo noteblog.

With your cursor on the date headline, choose the script, and enter the following in the dialog box, in this order: Latitude, Longitude, and mapType (each separated by commas). If Latitude is South or Longitude is West, precede the value with a minus sign. The mapTypes are roadmap, satellite, hybrid, and terrain. For example: "41.0967,-73.5522,hybrid" is what I'm using for this post.

Although the attribute mapZoom is supported in Fargo, I am not including it in this script.

I don't check for errors in entry, so if there are problems, please check the instructions first. If you are still getting errors, please contact me.

Disclaimer: Dave Winer has not even written up documentation for this feature, so use "as is."

Visit the Fargo scripting page in the docs to learn how to install this script, or watch this video.

Here is the OPML for the script.

03/28/14; 11:20:56 AM

Tweet This Post

Inspired by this LCP action by Alex Guyot, I have written a Launch Center Pro action to search queries in either the Timers or Logbook section of Due: you can install it here.

When you launch the action, you're presented with a choice between Timers or Logbook:

 

 

Then, depending on your choice, you're presented with a list of queries:

 

 

(Obviously, you will have to adapt for your own use. Yolanda cuts my hair.)

After you choose the query, Due opens with the search already completed. You can then start a timer or recycle an old reminder.

A Breakdown of the Action

 

Here is the full string:

 

 

Here I will URL-decode the first list item (between Timers= and the |):

launchpro://?url=due%3A%2F%2Fx-callback-url%2Fsearch%3Fsection%3DTimers%26query%3D[list:Timers|Coffee|White rice|Collards|Freebird|Cauliflower|Chicken]   

The second list (the queries) is written as you would ordinarily compose a list in LCP. The important thing to note is that, since the Due URL scheme is not included in those brackets, it has to be URL-encoded after the launchpro://?url=:

due://x-callback-url/search?section=Timers&query=
03/25/14; 01:49:58 PM

Tweet This Post

Inspired by this post by Phillip Gruneich, I have written the following iOS bookmarklet. If you are browsing a blog on Tumblr in a web browser, the bookmarklet will open that blog into the Tumblr for iOS app.

javascript:window.location='tumblr://x-callback-url/blog?blogName='+window.location.hostname.split('.')[0]
03/10/14; 10:36:56 AM

Tweet This Post

The following is inspired by Using Launch Center Pro 2, Drafts, and Dropbox to List Down My Expenses by Dexter Ang.

I am currently using a TiddlyWiki to keep track of spending. I have written actions for both Launch Center Pro and Drafts to enter expenses and then have the data prepended to a text file in wiki table format. At my convenience, I can then copy a row from the table and paste it into the appropriate financial category tiddler. (Note that all of the following can be used to simply add a running list of expenses into a Markdown table in a text file -- you don't need to use a wiki with these actions.)

A row in a wiki- or markdown-table looks like this:

|2014-02-12|Groceries|$14|

The LCP action uses the TextExpander snippet to enter the date, and uses prompts to enter the type of spending and the amount spent. These three fields are separated by an URL-encoded pipe (|), and then the entire string is sent to Drafts to launch the moneyWiki action. Upon success, I am sent back to LCP.

drafts://x-callback-url/create?text=<ddate>%7C[prompt:Where and What]%7C%24[prompt-num:Amount]&action=moneyWiki&x-success={{launch:}}

(%7C is an URL-encoded |. %24 is an URL-encoded $.)

In Drafts, moneyWiki is a Dropbox action in which I prepend the following to the money.txt file in my /Apps/TWSync/Text/ folder in Dropbox:

|[[draft]]|

(The folder can be of your choosing. I use TWSync because that's where TWEdit syncs TiddlyWiki files.)

When the [[draft]] is surrounded by pipes, the result is a valid table row. The advantage of this action is that I can enter something like 2014-02-12|Groceries|$14 into Drafts, trigger the same moneyWiki action, and once again have a valid table row prepended into my money.txt file. (In other words, I can enter expenses into LCP on-the-go, or enter into Drafts so that I can act upon the draft later -- for instance, if I do not have internet access.)

Addendum: A Note About Markdown Tables

After reading more about tables in Markdown, I've learned that Markdown proper doesn't include special formatting for tables, but extensions like Github Flavored Markdown do. In this case, a table must have a header to render properly. If you're going to use a header, then obviously you cannot prepend new expenses to your text file, you will have to append instead.

02/11/14; 10:51:54 AM

Tweet This Post

I've played around with Dave Winer's River 2 and River 3, but ultimately these solutions are expensive because they require a server to process the RSS feeds included in an OPML file. (Here's Dave's River so you know what it looks like.) I used to run my River using EC2 for Poets and the Amazon Web Services bill was way too high just to publish a feed reader.

Fotis Evangelou has developed a client-side feed reader based on javascript called AMJR (Asynchronous Multifeed JavaScript Reader). I've adapted his slightly for my own "river" about iOS Automation. All I had to do was create my own list of feeds and do some tweaking of the CSS and HTML to remove the fixed content area on the right.

Like the OPML Editor River of News, there are no bells and whistles here. You can't read full feeds within the "app" or 'Send to Instapaper' or star an item to save it in Pinboard. But it's a good way to just view headlines from your favorite feeds. And because it's a static app and the work is done in the browser, you don't incur server costs beyond just hosting the files somewhere.

02/07/14; 04:59:03 PM

Tweet This Post

Plain text rocks, but I've been crushing on the list-making iOS app Paperless recently, and because it stores its data in XML files (at least when using Dropbox for sync), it's difficult to mark an item complete in a text editor. However, it's not impossible.

I would not advise the following steps to anyone other than those who are comfortable editing XML files.

To find the XML files, just go to the \Paperless folder in Dropbox. A typical list item will look like this:

<item>

<dateCompleted></dateCompleted>

<itemName>Cell phone bill</itemName>

<itemNote>$100</itemNote>

<itemReadOnly>NO</itemReadOnly>

<itemCompleted>NO</itemCompleted>

</item>

To mark as complete, we have to do two things:

  1. Enter a value for <dateCompleted>

  2. Change the value for <itemCompleted>

<item>

<dateCompleted>2014-02-06 15:32:11 -0500</dateCompleted>

<itemName>Cell phone bill</itemName>

<itemNote>$100</itemName>

<itemReadOnly>NO</itemReadOnly>

<itemCompleted>YES</itemCompleted>

</item>

Above, I've changed the value of <itemCompleted> to YES. I've also entered a date string for <dateCompleted>. If you use TextExpander, use this data math for the snippet:

%Y-%m-%d %H:%M:%S -0500

The app uses +0000 UTC time, but above I've chosen -0500 because I live in New York. When I re-sync the app with Dropbox, it shows at the bottom: "Completed: Feb 6, 2014, 3:32 PM" so I know I did the date math correctly.

02/06/14; 03:18:44 PM

Tweet This Post

After reading this Twitter conversation between @welkpatrick, @epramono and @Pgruneich, I now have a deeper understanding of how launch://?url= works:

Combined with Federico Viticci's Safari Action Menu In Launch Center Pro, it's all starting to come together: I can write a Launch Center Pro action, and use it from within another app entirely, without having to have that action entered in LCP itself.

For example, I have an action in LCP to add an item and optional note to Paperless:

paperless://addItem?itemName=[prompt:Item]&itemNote=[prompt:Note]&toListNamed=[list:Choose a list|List1|List2|List3]

(You can view that URL Scheme documentation here.)

Now, if I've noted something in Drafts and later decide I want to send it to Paperless, I can just tap on the paperlessList action in the Drafts Actions menu to launch LCP with a menu of lists already open. All I have to do is tap on the list to which I want to send the task, and the task and note are imported into Paperless.

If you're in Drafts, tap on this link to import the URL Action. And here is the action itself:

launch://?url={{paperless://addItem?itemName=[[title]]&itemNote=[[body]]&toListNamed=[list:Choose a list|List1|List2|List3]}}

The first line is the task, and any additional lines (if they exist) are added in the note field.

02/06/14; 10:01:02 AM

Tweet This Post

I wrote the above Launch Center Pro action over the weekend. I thought it would take 15 minutes, but it took 45, because the encoding was such a challenge.

The Problem I Wanted to Solve

When I add new list items to an LCP action using the list tag, I sometimes just randomly add an item after the first pipe (|) I can find. Then I notice that the order of my list items has no rhyme or reason to it, so I want to alphabetize it. This is not an easy task, cut-and-pasting in a small text area on an iPhone screen. So I decided to use TextTool to automate the process for me.

  1. Remove the pipes in a sequence like Apples|Pears|Bananas using the split method.

  2. Use the sort method to alphabetize the list

  3. Add the pipes again between each item, using the join method.

Here is the full LCP action (click on the link in the Twitter embed above to install):

texttool://x-callback-url/transform?text=[clipboard]&method=split&delimiter=%7C&x-success=texttool%3A%2F%2Fx-callback-url%2Ftransform%3Ftext%3D%5B%5Boutput%5D%5D%26method%3Dsort%26x-success%3Dtexttool%253A%252F%252Fx-callback-url%252Ftransform%253Ftext%253D%25255B%25255Boutput%25255D%25255D%2526method%253Djoin%2526delimiter%253D%25257C

The sort transformation, URL-decoded:

texttool://x-callback-url/transform?text=[[output]]&method=sort

The join transformation, URL-decoded twice:

texttool://x-callback-url/transform?text=%5B%5Boutput%5D%5D&method=join&delimiter=%7C

Notice how, even though this action was URL-encoded twice after the second x-success parameter, the [[output]] had to be encoded yet again before the entire action was URL-encoded twice. I had to add an extra %25 before each double-encoded bracket to make the complete action work.

Related: Take a Photo, Get a Markdown Image Link with Launch Center Pro, Clean Links, and TextTool

Resources: TextTool x-callback-url Support page

02/03/14; 10:33:23 AM

Tweet This Post

Paperless is an iOS lists app that stores its data in XML files in Dropbox (if you choose to sync). What follows is an attempt to procure the first item in a list and send it to Due without having to copy and paste.

The first list item in any Paperless list appears to occur on line 12 of the list's XML file. It looks like this:

<itemName>LIST ITEM</itemName>

Launch Center Pro's dropbox tag lets you get the contents of a text file, so I figured I could grab the entire contents of an XML file and push it to Drafts. Tap on this link to import into LCP, or copy the action below and adapt for your purposes:

drafts://x-callback-url/create?text=[dropbox-text:Paperless/Errands.xml]&action=line12

What this does is grab the full text from the Errands list in Paperless, send it to Drafts, and then activate the line12 custom URL action.

line12 uses a Drafts tag [[line|12]] to send line 12 of the XML file to TextTool and then use the regex method to replace <itemName> and </itemName> with blank spaces. I know next to nothing about regex, but I found here that I could easily create a regex expression to match both <itemName> and </itemName>:

<(/|)itemName>

So the search parameter in TextTool is the above URL-encoded, and the replace parameter is a single space, URL-encoded:

texttool://x-callback-url/transform?text=[[line|12]]&method=regex&search=%3C(%2F%7C)itemName%3E&replace=%20&x-success=due%3A%2F%2Fx-callback-url%2Fadd%3Ftitle%3D%5B%5Boutput%5D%5D

(Tap on this link to import into Drafts.)

The x-success parameter above tells TextTool to take the [[output]] of that transformation and send it to Due. Here is that action URL-decoded:

due://x-callback-url/add?title=[[output]]

The final result... I tap on the LCP action, and it adds the first list item from my Errands list and sends it to Due. There are spaces preceding the text, but the XML is extracted.

Although the automation required to perform the above is a bit excessive (in contrast to just copying an item from Paperless and then pasting it into Due) it demonstrates the ability of the included iOS apps to accomplish pretty remarkable tasks.

 

Addendum (2014-02-04)

Here is an importable line12 Drafts action that trims the TextTool regex output before it sends the list item to Due. And here is the URL action itself:

texttool://x-callback-url/transform?text=[[line|12]]&method=regex&search=%3C(%2F%7C)itemName%3E&replace=%20&x-success=texttool%3A%2F%2Fx-callback-url%2Ftransform%3Ftext%3D%5B%5Boutput%5D%5D%26method%3Dtrim%26x-success%3Ddue%253A%252F%252Fx-callback-url%252Fadd%253Ftitle%253D%25255B%25255Boutput%25255D%25255D

 

Addendum 2 (2014-02-04)

Here is an importable line12 Drafts action that will include a link to the Errands list in Paperless within the Due text, so that when you complete the task, you can visit the list and check off the item there. (Thanks to @epramono for inspiring this.) And here is the URL action itself:

texttool://x-callback-url/transform?text=[[line|12]]&method=regex&search=%3C(%2F%7C)itemName%3E&replace=%20&x-success=texttool%3A%2F%2Fx-callback-url%2Ftransform%3Ftext%3D%5B%5Boutput%5D%5D%26method%3Dtrim%26x-success%3Ddue%253A%252F%252Fx-callback-url%252Fadd%253Ftitle%253D%25255B%25255Boutput%25255D%25255D%25250Apaperless%25253A%25252F%25252FviewList%25253FlistName%25253DErrands
02/03/14; 12:47:01 PM

Tweet This Post

I've been using a list-making app called Paperless. Although I'm a big supporter of apps that use plain text files, Paperless stores its lists on Dropbox in XML. No biggie. I've already written scripts to import a list into Paperless and export a list from Paperless.

The developer includes a stylesheet in the XML files, so that if you open one up in the browser, it looks readable. All you have to do is open an XML file in your /Paperless Dropbox folder in a web browser. Unfortunately for me, I am at an office computer all day, and I do not have my Dropbox files sitting in my hard drive. So to view those XML files I would have to download them from Dropbox to my work computer hard drive and then open them in the browser.

To overcome this handicap, I have written a tool that will allow you to view any number of your Paperless lists online. All you have to do is make the lists you want to view shareable, and enter these URLs into a form. Shared Dropbox URLs are not easily discoverable, and if you really don't want someone to accidentally come upon one of your XML files, then don't make the URL public.

The script I developed generates each of your lists in an HTML table. The URLs are not uploaded to any server. The script just reads your XML files locally, so you can feel secure that the view of your lists that you see in the browser is not viewable by anyone else online. You can even just download the html file to your hard drive and use it locally (that is, open it from the hard drive into your browser).

To see how it works, visit the page, enter the following four Dropbox URLs into the input field, and then hit Publish. These are the four lists that come pre-installed when you download Paperless to your iOS device.

https://www.dropbox.com/s/1c3j4u1y7ajcwss/Today.xml,https://www.dropbox.com/s/9l46i1iojr6nc3t/Story%20Outline.xml,https://www.dropbox.com/s/ptj4f95md4fkkpd/Someday.xml,https://www.dropbox.com/s/fbp9iv7shwy5t0f/Groceries.xml

You should see four lists generated below the input form.

If you want to view your own lists, just get the shared Dropbox URL for each, and enter them as a comma-separated list.

This is version 1.0, and I will likely work on styling and generating more of a grid than having the lists stacked on top of each other.

01/31/14; 01:10:03 PM

Tweet This Post

I often forget today's date. This tiddler inserts an empty Google Calendar into the sidebar of my wiki so that I can quickly glance at it.

 

 

Just create a new tiddler, call it "Calendar" (or whatever you want) and paste this embed code into the body of your tiddler:

<iframe src="https://www.google.com/calendar/embed?src=qqndj42ted2fn9ph0v6bc0ij34%40group.calendar.google.com&ctz=America/New_York" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>

Then -- and this is the important part -- add or create this tag: $:/tags/SideBar. Then save the tiddler and you ought to see a Calendar tab in your sidebar.

You can of course use any of your current Google Calendars -- just go to the Calendar Details tab, scroll down to Embed This Calendar, and grab the embed code.

 

01/29/14; 11:47:20 AM

Tweet This Post

Inspired by Federico Viticci's Launch Center Pro action to add a photo as a reminder to Fantastical 2, I've written the following to do the same with Due:

launchpro-dropbox://x-callback-url/addlastphoto?getlink=1&x-success=due%3A%2F%2F%2Fadd%3Ftitle%3D{{[prompt]}}%2520%5Bclipboard%5D

If you're on your iOS device, you can tap on this link to install it.

This action uses /addlastphoto but there are more recent options like /addphoto?attach=photo:library which will let you choose an image from your photo library. All the options are listed in LCP's 2.1 Release Notes.

The encoding is confusing, but Viticci figured it out. When in doubt, copy. The key, really, is that the clipboard prompt has to be manually encoded or else LCP chooses what was originally on the clipboard before the Dropbox action.

Here is the x-success parameter URL-decoded:

due:///add?title={{[prompt]}}%20[clipboard]

When encoded, the URL-encoded [prompt] -- signified by the {{ }} -- should not be URL-encoded again.

01/29/14; 09:59:58 AM

Last built: Thu, Jun 19, 2014 at 3:40 PM

By Jeffrey Kishner, Thursday, June 19, 2014 at 3:40 PM.