Home

You’re Doing That Wrong is a journal of various successes and failures by Dan Sturm.

"Open on Which Mac" Shortcut

A few weeks ago, I started a new job. Along with that job came a new iMac and Touch Bar MacBook Pro. Having doubled the number of computers in my life, I quickly found that my frequently-used Open on Mac iOS Shortcut was not working as expected.

While at work, attempting to open a webpage on my iMac would result in...nothing. When I got home, I found the pages open and waiting for me on my personal iMac.

Prior to the newly acquired computers, I had never given much thought to why webpages opened on my iMac rather than my MacBook Pro. I spent 98% of my time on the iMac and, since it was doing what I wanted it to do, there was no reason to ask why. I mostly assumed it was because the MacBook Pro was asleep and the iMac is always awake.

As it turns out, the real reason webpages always opened on my personal iMac is because it has the fastest internet connection (a wired fiber connection) and would therefore download the Dropbox file containing the URL before any other computers had the chance. Hazel would then do its thing, trash the file, and that was that.

It had become necessary to modify my iOS Shortcut, allowing me to specify on which computer I wanted to open the webpage. To accomplish that goal, I added a "Choose from List" action to the shortcut where I could pick which computer to use. Then, I added short prefixes to the filename that represented each computer.

 
 

The original text file containing the page URL was called "URL-Current Date.txt". The new file names are:

  • The Touch Bar: tbr-URL-Current Date.txt
  • The New iMac: niM-URL-Current Date.txt
  • My MacBook Pro: mbp-URL-Current Date.txt
  • My iMac: diM-URL-Current Date.txt

Add a couple of "If" statements to the shortcut and we're about done. Here's what the new, much longer shortcut looks like.

 

These If statements are terrible and ugly and there’s got to be a better way to do this, but I don't know what it is.

 

After finishing the shortcut, all that was left to do was add the prefixes to the name search field in the Hazel rules running on each computer and call it done.

P.S. Thank you, again, to Jason Snell for fixing my very unsafe, poorly conceived version 1.0.

Open Website on Mac Workflow

Update – 2018-01-05

Over at Six Colors, Jason Snell has created a much smarter, safer version of this whole iOS to Mac automation idea.

His version, smartly, builds the shell script on the Mac side — only receiving keywords and URLs from the iOS device — as opposed to my version which is set up to just immediately run whatever text file shell script happens to pop up in my Dropbox folder. A less-than-ideal setup should someone else acquire access to that Dropbox folder. Go check it out.


This may be one of the laziest automation tools I've ever created, but I solves an annoyance that's been bugging me for a long while now.

Often times I'll be looking at a website on my iPhone and I'll want to switch over to viewing it on my Mac. "That's why Apple created Handoff," you say. Yes, well, personally I find Handoff to be slow, unreliable, and only half of the solution.

I'm looking at a website on my phone. I want to press a button on my phone and have that website open in Safari on my Mac. I don't want to wait for a dock icon to appear on my Mac. I don't want to try to click on it, quickly, before it disappears. I don't want to look through a list of open iCloud tabs in Safari on my Mac.

I want to tap and have it open.

What I Did

I used everyone's favorite iOS automation tool Workflow.app to create an Application Extension Workflow that grabs the current URL and saves it to a date/time stamped text file in a specific Dropbox folder. It looks like this:

 
 

Then, I set up Hazel on my Mac to monitor that folder and, when it sees a new file, run the file with Bash, then throw it in the Trash. Here's what that looks like:

Overly complicated? Probably.

Lazy? Almost certainly.

Does it do the job I wanted it to do? Absolutely.

It takes about 6 seconds from tapping on the Workflow in Safari on my phone to having an open page in Safari on my Mac. That's not exactly fast, but it's no slower than using Handoff. It's also far more reliable and requires less interaction from me.

And, let's not forget, this will work from any distance. There's no Bluetooth range limit like Handoff. Wherever you are, as long as you've got an internet connection, you can use this Workflow to have a website open and waiting for you on your Mac when you get home.

Creating Unique Footnotes with MultiMarkdown Metadata

Footnotes. Writers love ’em. But if you’re not paying proper attention when creating them, you can quickly make a mess of your website or blog. In fact, until very recently, this site had broken footnote links all over the place. I’m going to pretend like none of you noticed, and tell you about how I fixed the problem, gently glossing over my past stupidity.

Each post on this site starts as a MultiMarkdown document in Sublime Text 2. When it’s complete, I preview it in Marked, then copy the HTML code and paste it into a new Squarespace post.

The Problem

Thing is, since I’m creating the post locally on my Mac, with no reference to the site as a whole, Marked has no way of knowing which footnote IDs have already been used, and which have not. Therefore each post labels its first footnote fn:1 and subsequent footnotes increase by 1, as you’d expect. The problem occurs when viewing the home page that shows 10 posts on a single page, each with their own fn:1. When you click on the [1] link in the body text, where do you think it’s going to take you? That’s right, to the first footnote it finds with the label fn:1, regardless of which post it was intended to link to [1].

Now, Marked has a setting in its preference pane called Use Random Footnote IDs which is used “to avoid conflicts when multiple documents are displayed on the web.” So this is already a solved problem, right? Probably, but there’s a part of my brain that feels uneasy about using randomly generated IDs. I’m sure using this feature would solve my problem and everything would be fine, but since I’m a nut, I want to control exactly how these unique footnotes are created.

Enter MultiMarkdown. MultiMarkdown includes a number of enhancements to the original Markdown syntax [2], including support for customizable metadata fields [3]. So, I created a custom metadata key called footnote:. Here’s what my boilerplate MultiMarkdown header looks like [4] :

Title:            
Author:         Dan Sturm      
Date:           %snippet:ddate%  
Marked Style:   ds_doc  
footnote:         

Now, whatever keyword I choose to add after the footnote: label will show up in the HTML header as [5].

Make With The Magic

The next thing I needed was a script to scan the HTML for the metadata key, and add it to all the footnote IDs, turning fn:1 into fn:my-footnote-key1.

import sys  
import re  
import subprocess


#   Open the file and convert it to searchable text  

fileText = open (sys.argv[1], "r+")  
searchText = fileText.read()


#   Pull the MultiMarkdown metadata key from the header  

mmdkey = re.search("(?<=\"footnote\" content=\")(.*)(?=\"/>)", searchText, re   .I)  
mmdkey = mmdkey.group()


#   Create the new footnote IDs  

fnnew = ("fn:", mmdkey)  
fnrefnew = ("fnref:", mmdkey)  

fnnew = "".join(fnnew)  
fnrefnew = "".join(fnrefnew)


#   Swap the footnote IDs for the new ones  

fnfix = re.sub("(fn:)", fnnew, searchText)  
fnreffix = re.sub("(fnref:)", fnrefnew, fnfix)


#   Strip HTML Header and Body tags. Copy the result to Clipboard  

def setClipboardData(data):  
  p = subprocess.Popen(['pbcopy'], stdin=subprocess.PIPE)  
  p.stdin.write(data)  
  p.stdin.close()  
  retcode = p.wait()  

fixStripped = re.sub("(?s).*(\n)\n", "", fnreffix)  
fixStripped = re.sub("(?s)\n\n\n().*", "", fixStripped)  
setClipboardData(fixStripped)


#   Write the updated code to the same file  

# fileText.seek(0)  
# fileText.write(fnreffix)  
# fileText.truncate()  
# fileText.close()  

Click here to download the script.

Now that we have that out of the way, let’s talk about how to actually use this code. I’m using a Hazel [6] rule pointed at a folder called Create Unique Footnotes. It looks like this:

The Hazel Rule

Simply put, it watches the folder for a new file and, when it sees one, it runs the script, displays a confirmation message, then trashes the now-unnecessary file, leaving the cleaned up, new code on the clipboard for easy pasting into your CMS of choice. So, when I like what I see in Marked and I’m ready to post, I hit CMD+S and save the HTML file to my Create Unique Footnotes folder, head over to my site, and hit CMD+V into a new post.

A Small Rabbit Hole

There are a few specific things I want to point out, just to make sure we’re clear.

The new HTML code is copied to the clipboard by the Python script, not by the Hazel rule. My workflow involves pasting HTML code into Squarespace, not uploading an HTML file and, since my MultiMarkdown file is the master copy of the post, that’s why I’m deleting the HTML file after running the script.

The HTML file being used as input for the script is a complete HTML document with a header, body tags, the whole shebang. I don’t need those extra bits when I’m pasting the code into Squarespace, so the Python script removes them before placing the code on the clipboard. In fact, the code on the clipboard looks exactly like what you see when you toggle the Switch to HTML Source View button in Marked [7] while previewing your MultiMarkdown document.

Another important note; keen observers will notice the last four lines of the Python script are commented out. That code is there for people who actually want a fully processed HTML document with fixed footnote IDs. Un-commenting-out [8] those four lines will write the fixed code over the original HTML document, while maintaining the header, et cetera. If you plan on using this workflow, you’ll want to remove the step in the Hazel rule that throws away the HTML document. I’d suggest you change that part of the rule to move the new HTML file to the Desktop as a sort of visual confirmation that the file has been updated.

I Believe Some Recognition is in Order

When I initially conceived of this idea I hadn’t the slightest idea how to best go about tackling it. I am not a programmer in any sense of the word. A Twitter conversation with my pal Sid O’Neill revealed that REGEX is the method by which I could find and replace items in the code. I don’t know how to do that, so…

Patterns is a Mac app for creating Regular Expressions that I’ve heard a number of people compliment in the past. It lets you see a live preview of the current pattern matches and, when you’ve got the selection you want, will generate the appropriate code for you; Python in my case. Completely indispensable and only $2.99.

Next, of course I have to thank Stack Overflow from whence I acquired some REGEX knowledge and code. Patterns comes with a great Reference Sheet for REGEX commands, but some of the descriptions still left me befuddled. Stack Overflow also linked me to…

This article by Gabe at Macdrifter, where I got the code that places the HTML on the clipboard. It was exactly what I needed, so I took it. And I would have gotten away with it if it wasn’t for you pesky kids and…nevermind.

In any case, high-fives all around. Go team.


  1. Some of what I’m describing is obfuscated by the use of Bigfoot for my footnotes, specifically the numeral for each footnote, but the problem remains. Let’s move on.  ↩

  2. Like footnotes, for one.  ↩

  3. You can learn all about MultiMarkdown Metadata here.  ↩

  4. Always invoked via TextExpander.  ↩

  5. Obviously, I need to choose a unique key for each post or this whole exercise is pointless.  ↩

  6. You do use Hazel, don’t you? Good.  ↩

  7. It’s in the upper right corner of your document, next to the fullscreen button.  ↩

  8. That’s so not a word, is it?  ↩

Automated FTP upload with Hazel via Bash

A couple weeks ago Macdrifter had a nice post about automating FTP uploads with Hazel, Dropbox, and Python. It’s a similar idea to the setup I’ve been using to automate my MultiMarkdown workflow, but the main reason it grabbed my interest was this line:

I really like Transmit for FTP, but it seemed a little heavy handed for Hazel automation.

He’s right. Using Transmit for the FTP portion of my process was a poor decision. It just happened to be the only way I knew how, and scripting the FTP upload didn’t even occur to me at the time (there’s a reason for the name of this site).

After reading his post, I decided to swap out the slow and clunky Transmit portion of my Hazel rule with some fancy code. One problem. I don’t know anything about Python[1], and the 3 hours I spent trying to get up to speed were futile and fruitless.

Since I’ve dabbled a bit with Bash, I decided to see if there was an equivalent way to accomplish the same tasks. After a bit of searching, and a lot of trial and error (again, read the name of the site), I came up with this:

HOST=ftp.DOMAIN.com  
USER=myUserName  
PASS=myPassword  

JNAME= \ basename $1\  

ftp -inv $HOST << EOF  

user $USER $PASS  

put "$1" "$JNAME"  

EOF  

echo "http://dansturm.com/$JNAME" >> /Users/PATH/Dropbox/PATH/UPLOADS_LOG_FILE.txt

It’s faster than the Transmit method. It works more often than the Transmit method. And it even records the URL of the uploaded file to a text file in my Dropbox (my favorite idea from the Macdrifter post). I also have the Hazel rule change the file name to all lowercase and swap spaces for underscores, something is already performed in my Text to HTML conversion rule, but now the FTP rule can be used stand-alone as well as in conjunction with the MultiMarkdown process.

It has no error reporting, and you can’t even really tell it’s running (save for the evidence in the log file), but it’s way better than what I was using. Many thanks to Macdrifter for this one.

But…

I’m happy I was able to improve my exiting tools, and learn a few things in the process, but now that I’ve migrated this blog to Squarespace, I’m not sure how much I’ll actually use them considering Squarespace doesn’t support FTP access, and my home site doesn’t need updating very often.


  1. Okay, I know some Python, but only enough to customize the interface in Nuke and build some basic gizmos and comp tools.  ↩

My Hazel CMS

It should be no surprise to anyone familiar with the app, that Noodlesoft’s Hazel is amazing. Today I setup an automated system using Dropbox, Automator, and Hazel to process MultiMarkdown documents into HTML, give them web-ready filenames, and upload them to my website.

Everything on this site starts as a MultiMarkdown text file. I preview the page in Marked, and when its ready to go live, I save a copy of the file in a folder called _1_ready_, which has 3 Hazel rules applied.

Ready

First things first, the text file needs to be converted to an HTML document. I’ve used the Run Shell Script action to call the mmd command.

html_from_new.png

Pretty straight forward. To add some flexibility, the second Hazel rule for the _1_ready_ folder checks for changes to preexisting text files, and processes them using the same bash script. That saves me from having to delete and re-copy a file to make an update.

html_from_updated.png

The last rule for the _1_ready_ folder renames the HTML file, making it entirely lowercase, replaces the spaces with underscores, and moves the new file to a folder called _2_go_.

rename_and_move.png

It’s important to make sure the name element in the with patern: section is set to lowercase, and the replace text dialog is used to swap the spaces for underscores.

Go

The _2_go_ folder automatically uploads any file it finds to the root of my site. As with _1_ready_, the final files are left in the folder to more easily make changes later. Additionally, I keep a copy of my Blog index page and rss XML in the _2_go_ folder so I can quickly update the main page with links to the new posts.

upload_to_ftp.png

To upload the files, the Hazel rule calls an Automator Workflow that uses the Transmit [1] upload action to log into my site (stored as a favorite), and drop everything in the root folder, overwriting files if necessary.

transmit_automator.png

Dropbox

The best part about this whole workflow is Dropbox. Both the _1_ready_ and _2_go_ folders are in my Dropbox, giving me the ability to drop in files from my iPhone, iPad, etc. With apps like TextExpander and Nebulous Notes, there’s no reason I can’t create, and post entirely from an iOS device. Obviously I’ll need a Mac, running and online, but the flexibility of this workflow is well worth the cost of a dedicated system.

Needless to say, I’m incredibly excited to have this new capability, and I can’t wait to see what other workflow magic I can create with Hazel


  1. Many thanks to Macdrifter for recommending Transmit. I love this app.  ↩

Update: I've since revised my upload method to use a Bash script, rather than Transmit. It's much faster and more efficient, so if this idea interests you, you should definitely check it out.