And now it’s all thishttp://leancrew.com/all-this/
I just said what I said and it was wrong. Or was taken wrong.Wed, 14 Nov 2018 23:19:15 +0000en-UShourly1http://wordpress.org/?v=4.0Screenshooting on the iPadhttp://leancrew.com/all-this/2018/11/screenshooting-on-the-ipad/
Wed, 14 Nov 2018 23:19:15 +0000http://leancrew.com/all-this/2018/11/screenshooting-on-the-ipad/
the current episode of Upgrade, Myke Hurley and Jason Snell talk about taking screenshots on the new iPad Pro. With the home button gone, the process has become more like that on the iPhone X line: press the top1 and volume up buttons simultaneously. This does seem, as Myke says, a little awkward, but I’m surprised either of them use that method of taking a screenshot very often.]]>
About 55 minutes in to the current episode of Upgrade, Myke Hurley and Jason Snell talk about taking screenshots on the new iPad Pro. With the home button gone, the process has become more like that on the iPhone X line: press the top1 and volume up buttons simultaneously. This does seem, as Myke says, a little awkward, but I’m surprised either of them use that method of taking a screenshot very often.

If you’re using a keyboard with your iPad—as I believe Myke and Jason usually do when they’re working—the traditional Mac keyboard shortcuts of ⇧⌘3 and ⇧⌘4 work, and the difference between the two is an interesting twist on the Mac behavior.

As you probably remember, ⇧⌘3 on a Mac takes a screenshot of the whole screen and ⇧⌘4 turns the cursor into crosshairs so you can select a rectangular portion of the screen to capture.2. On the iPad, ⇧⌘3 captures the whole screen, just like the Mac (and just like capturing with the top and volume up buttons). The ⇧⌘4 shortcut also captures the whole screen, but in a neat analogy to the Mac, it immediately puts you into editing mode so you can crop the capture down to a smaller size.

One oddity about screenshots on iOS that has no analogy with the Mac is that their file format depends on whether they’ve been edited. If you take a screenshot on your iPhone or iPad and save it directly to Photos with no changes, it’s saved as a PNG. But if you crop it or draw on it before saving to Photos, it’s saved as a JPEG. Check the full-screen image above, and you’ll see that its a PNG. This cropped one, though, is a JPEG.

As with many things in the Apple world, I have no idea why this is the case.

What used to be called the sleep/wake button on both machines is now called the top button on the iPad and the side button on the iPhone. ↩

Yes, I know you can also use ⇧⌘4 to capture a window at a time, but I’m focusing on the default behavior here. ↩

]]>
An unzipping shortcuthttp://leancrew.com/all-this/2018/11/an-unzipping-shortcut/
Sun, 11 Nov 2018 19:30:54 +0000http://leancrew.com/all-this/2018/11/an-unzipping-shortcut/
MacBook Air, the Mac mini, and the iPad Pro to download images and went off on another tangent. As usual, I will inflict that tangent on you.]]>
I’ve been planning to write a post about the new Apple products for over a week, but I keep getting distracted. Today, I went to Apple’s PR pages for the MacBook Air, the Mac mini, and the iPad Pro to download images and went off on another tangent. As usual, I will inflict that tangent on you.

Apple provides the product images as zipped archives, so when I clicked on the link in the press release, I was confronted with this “what do I do?” screen in Safari.

The efficient thing would have been to walk ten feet over to my iMac and download the zip files there, where they can be expanded with almost no thought. But I took the procrastinator’s way out, deciding to solve the problem of dealing with zip files on iOS once and for all.

In the past, I’ve tried out a few zipping/unzipping apps, and they’ve all sucked, with user interfaces that are clumsy to navigate and look like something out of Windows 3.1. What I wanted was a clean, one-click solution similar to what we have on a Mac. A shortcut, if you will…

I went to the Shortcuts Gallery and searched on “zip,” “unzip,” and “archive.” There was a shortcut for zipping up a bunch of files and putting them into an email message, but nothing for unzipping and saving. I also couldn’t find anything by Googling. So I made my own.

As you can see, there’s not much to it. You can make it yourself or download it.

You run it as an Action Extension by bringing up the Share Sheet and selecting the Shortcuts Action. After you choose it from your list of Extension shortcuts, you’ll be presented with a Files-like location picker, from which you can choose where the expanded archive will be saved.

Even though “iCloud Drive” is the Service chosen in Step 2 of the shortcut, it can also save locally and into Dropbox. I suspect it can use services like Box and Google Drive, too, but I don’t use those services and haven’t tested them.

There are a few thing to keep in mind:

The Files-like interface isn’t Files-like enough to give you the opportunity to create a new folder. You must save the expansion in an existing folder.

It crashed the first time I tried to run it. I don’t know if that was because of low memory or some other odd reason, but it led me down a path of unnecessary debugging. When I couldn’t figure out what was wrong with it, I ran the shortcut again and it worked perfectly. 🤷🏼‍♂️

The first couple of times I ran it, the Dropbox icon was dimmed and inaccessible. Then it became available. I’m sure I did something in between, but I can’t tell you what it was. 🤷🏼‍♂️🤷🏼‍♂️

You can change the Service in Step 2 to Dropbox if you know you’ll never use iCloud Drive. I prefer to keep it as iCloud Drive, because that gives me the option to use either service.

The Extract archive step can handle more that just zip files. According to the help info, it can also extract rar, tar.gz, tar.bz2, tar, gzip, cpio, cab, and iso archives. The only one missing from the list that I sometimes see is 7-zip.

I make no claim of originality with this. I’m sure plenty of people have written similar shortcuts, but I couldn’t find them. I didn’t even know there was an Extract Archive step in Shortcuts until today. I should spend more time on this page and this one.

Update Nov 12, 2018 6:53 PM
A few more things:

As with the Mac’s Archive Utility and the default behavior of the unzip command, the Extract Files action expands the archive exactly the way it was compressed. Whatever directory structure was zipped up will reappear within the folder you select in Step 2 of the shortcut. This could be a problem, as we’ll discuss below.

As you might expect, Federico Viticci has already made a shortcut to do this, which you can download and install. Federico’s is more complicated than mine. He uses the name of the archive (without the .zip extension) to create a new folder within the iCloud Drive Shortcuts folder and extracts the contents of the archive there.

I’m of two minds on Federico’s shortcut. On the one hand, by creating a folder, it keeps things neat. With my shortcut, when you expand an archive that has lots of top-level files, those files can make a mess of the folder you save them in. On the other hand, Federico’s shortcut puts the expanded archive in a place I’ll never want it to go. It would be easy to edit Federico’s shortcut to put the extracted files somewhere other than the Shortcuts folder, but no matter what, it will go into a fixed location.

As best I can tell, there’s no way to get the best of both worlds: a neat folder of the extracted files and a choice of where that folder will be.

Federico is putting together a massive list of shortcuts he’s built. The list is organized by category and includes both a download link for each shortcut and a brief description of what it does. The list is being continually updated, so it’ll be worth returning to after your first perusal.

]]>
Keeping up with IP number changeshttp://leancrew.com/all-this/2018/11/keeping-up-with-ip-number-changes/
Fri, 09 Nov 2018 14:52:47 +0000http://leancrew.com/all-this/2018/11/keeping-up-with-ip-number-changes/
Prompt to connect to my iMac at home and run a command. It wouldn’t connect. I launched Transmit (which still works well, despite its zombie status) and couldn’t connect there, either. Obviously, my service provider had changed my home IP number. This happens rarely,1 but I didn’t want to be caught like this again.]]>
Last weekend I was at a hotel working on my iPad and launched Prompt to connect to my iMac at home and run a command. It wouldn’t connect. I launched Transmit (which still works well, despite its zombie status) and couldn’t connect there, either. Obviously, my service provider had changed my home IP number. This happens rarely,1 but I didn’t want to be caught like this again.

My first thought was to write a script that would check the IP number periodically and save it in a file on the leancrew.com server. But a bit of searching led me to this script by Charlie Hawker, which checks for the IP number and sends an email if it’s changed, a much better idea.2

There were, however, two things about the script I didn’t like:

It’s written in PHP. I don’t disklike PHP—I use it to build this blog—but it’s not a language I’m deeply familiar with, and I’d prefer a Python script so I can easily make changes if necessary.

It gets the IP number by loading a website (ip6.me) and scraping it. I wanted something a little more direct.

Lines 9–21 set the parameters that are used later in the script. As you can see from Line 9, I save the IP number in the hidden file .ipnumber in my home directory. Line 14 is the dig command we just talked about. Lines 15–21 is the template for the email that the script sends when the IP number change, and Lines 10–13 are the personal settings needed to send the email.

Lines 24–25 run the dig command4 and store its result (after stripping the trailing newline) in the currentIP variable. Lines 26–27 read the .ipnumber file, which contains the IP number from the last time the script was run, and store the contents in oldIP.

Line 30 then compares the two numbers and continues the script only if they differ. Lines 31–32 puts the new IP number into the .ipnumber file, and Lines 34–38 build an email message and send it via GMail. This script works only if you have a GMail account—if you don’t, you’ll have to tweak these lines to get your email service to send the message.

The email it sends is nothing fancy: a subject line telling me the IP number has changed and a body with the new number (which I’ve obscured in this screenshot).

To avoid an error the first time this script is run, create the .ipnumber file and put any old IP number in it. I seeded mine with an incorrect value, 11.11.11.11, so I could make sure the file changed and the email was sent when the script ran.

I decided to have the script run every hour. If I were using Linux, I’d set this up through cron, but the (more complicated) Mac way is with launchd. Here’s the plist file that controls the running of the script. It’s called com.leancrew.checkip.plist and is saved in my ~/Library/LaunchAgents directory:

The key entries here are Line 9, which gives the full path to the checkip script, and Lines 11–17, which tell launchd to run the script at 12 minutes past the hour.5 Because there are no Hour, Day, or Month entries in this section, it runs every hour of every day of every month.

Because of where it’s stored, this Launch Agent gets loaded into the launchd system every time I log in. To get it to load without logging out and logging back it, I ran these two commands:6

With it in the system, the agent will continue to run as long as I’m logged in. For me, this is essentially forever, as I keep this computer running all the time specifically so I can log into it whenever I need to.

I’ve thought of improving the script by adding an error-handling section to alert me when the dig command fails. This would let me know, for example, if OpenDNS has stopped running its service. But the possibility of being inundated by false positive emails has kept me from trying that out.

I managed to get the command run by connecting to my work computer, where the IP number is fixed. ↩

Yes, I know there are services that will do this sort of thing. I don’t want to rely on them. ↩

This does rely on OpenDNS, but if it ever shuts down or curtails this service, there will always be another similar way to get my IP number. I’ll just change my script to use that instead. ↩

Note: I typically write scripts in Python 3 nowadays, where the subprocess module is considerably different. This script was easier to do in the Python 2 that comes with macOS because it gets run by the launchd system, which uses an environment that doesn’t know where my installation of Python 3 is. Rather than telling it, I decided to just write it for Python 2. You could call this the $PATH of least resistance. ↩

Why 12 minutes? No particular reason. Any number under 60 would work just as well. ↩

The load and start subcommands are now considered legacy features of launchctl and will probably be removed in the future. But for now they still work, so I’ll worry about learning the new subcommands later. ↩

]]>
Building a tweet in Shortcutshttp://leancrew.com/all-this/2018/11/building-a-tweet-in-shortcuts/
Sat, 03 Nov 2018 15:14:32 +0000http://leancrew.com/all-this/2018/11/building-a-tweet-in-shortcuts/1]]>
I occasionally tweet links to Kindle books that are on sale. Although I do include my Amazon Associate tag in the link so I get a commission on sales, this is not what you would call a significant money maker. The commission on Kindle books is 4%, which amounts to 8¢ on the typical $2 sale price. I do it because I think the people who follow me might be interested in the book.1

In the past, these tweets were purely functional: such-and-such book is on sale for $2—here’s a link to it. I’d use the Associate app—actually its Share Sheet extension—to get the link. A couple of days ago, I decided it would be fun to jazz up the tweet with an image of the book. I already had some Python code that could use Amazon’s product advertising API to get the URL of a book image; I figured it wouldn’t be too hard to jigger with it to pull out the author and title, too, and combine it with a Shortcuts to build a tweet.

Here’s how it works. While I’m on the web page for the book, I invoke Shortcuts from the Share Sheet and choose the Tweet Kindle Book shortcut. This launches Pythonista to extract the relevant information from the Amazon API. At this point, the shortcut gets stuck with my screen showing Pythonista. To get it unstuck, I tap the ◀︎Safari link in the top left corner.

This little kick to get the shortcut going again is needed because Pythonista is not a particularly good iOS automation citizen. It has a URL scheme, which is what allows Shortcuts to invoke it, but it doesn’t implement callbacks, so it won’t automatically return to the app that called it. Pythonista does have ways to jump to other apps, but I haven’t figured out a way to get it to automatically continue this shortcut.

Anyway, after unsticking the shortcut, it assembles the book information into a tweet that I can edit and send.

Here are the steps of the shortcut.

The Python script (which we’ll get to in minute) takes the URL of the page being shared as input and puts a JSON dictionary of the book information on the clipboard. For this example, the JSON is

The Get Dictionary from Input step parses the JSON and turns it into a Shortcuts dictionary, from which we can extract the values. The first thing we do is get the URL of the book cover image and use Get Contents of URL to get the image itself. The image is saved in the variable Tweet.

Next, we assemble the text of the tweet from the other parts of the dictionary and a few linking words. This text is added to the Tweet variable (yes, you can add text to a variable that contains an image—I was surprised at that, too) and the whole thing is finally sent off to the Tweet step. You’ll need to have the official Twitter app installed for the Tweet step to be available.

The first item given to it on the “command line” (which in Shortcuts is what flows into the Run Script step) is expected to be the URL of the web page for the book. Lines 12–13 slurp it in and extract its unique Amazon ID, the ASIN.

Lines 16–17 get the current date and time and format it for later use with the API. Lines 20–31 put together all the data needed to make an API request. The associateTag is what you get from Amazon when you sign up for the Associates program. It’s attached to the link URLs that earn you a commission. The accessKey and secretKey are ID strings you get when you sign up for the Product Advertising API. The secret key is defined as a byte string rather than a normal Python 3 string because the encoding that’s part of the signing process (see below) requires a byte string.

Your request to the API has to be “signed” by encoding the request with your secret key. That’s done in Lines 34–39. The details of this are a little hairy, but Amazon explains them pretty well. Line 42 puts everything together into a URL to send to the API.

An important part of the request is the ResponseGroup parameter. There are many response groups available for plucking out different bits of information on a product. As best I could tell from the documentation, the only one that provides all the pieces I want is the Large group. That’s why you see it on Line 25.

Lines 45–46 use the Requests module to send the request URL to the API and get the response, which is in XML format. Lines 50–54 use the Beautiful Soup module to parse the XML and build a Python dictionary with the author, title, and image URL. Line 55 uses the ASIN and the associate tag to create the link entry in the dictionary.

Finally, Line 57 uses the JSON module to convert the Python info dictionary into JSON format and put it on the clipboard. This is the result of the first step of the Tweet Kindle Book shortcut.

This was a relatively simple shortcut to put together, mainly because I already had a Python script written to get the image URL. I just had to figure out which response group also included the author and title data and where they fit within the XML hierarchy.

I’m still a little annoyed about the pause at the Pythonista step. Maybe there’s a trick I don’t know about to get it to return to the shortcut. Or maybe I should consider rewriting that step in JavaScript so I can use Scriptable, which I think is more suited for use as a Shortcuts step.

If I’m buying the linked book myself because I don’t already own it, it takes 25 book sales for me to break even. Given how cheapfrugal discerning my Twitter followers are, that many sales is rare. ↩

]]>
Photo location followuphttp://leancrew.com/all-this/2018/11/photo-location-followup/
Fri, 02 Nov 2018 14:34:28 +0000http://leancrew.com/all-this/2018/11/photo-location-followup/
Photo Coordinates shortcut, professional automator Rosemary Orchard tweeted me a link to a cleaner shortcut that uses the Get Details of Images step.]]>
There’s always a better way to do it. Shortly after I posted my Photo Coordinates shortcut, professional automator Rosemary Orchard tweeted me a link to a cleaner shortcut that uses the Get Details of Images step.

As you can see, after extracting the Location property of Get Details of Images, you can further extract the Latitude and Longitude properties. This got me thinking that I could reduce the shortcut to a single step by treating the Shortcut Input magic variable as a Location, not as Photo Media, and then extracting the latitude and longitude from that.

This is a great idea, except it doesn’t work. Presumably, an image can’t be treated like a location because a location is a property of an image—and you can’t jump two levels down the hierarchy in one step.

But it does show I could have written my original shortcut more quickly by taking the Location property of the image instead of the Metadata Dictionary, and then extracting the Latitude and Longitude.

This is no shorter than my original, but if I’d done it this way I wouldn’t have had to screw around with the nested JSON in the Metadata Dictionary. Rosemary’s is still shorter, of course, and easier to read because it doesn’t create an unnecessary variable.

On the other hand, looking into the Metadata Dictionary taught me some things about the GPS metadata in phone images that I’ve never seen in the metadata on standard cameras and that I wouldn’t have learned if I’d done it the easy way right from the start. At some point, I may make use of that. In particular, the direction the camera was pointing when the photo was taken seems like it would be nice to know in some situations.

]]>
Drawing the quartershttp://leancrew.com/all-this/2018/11/drawing-the-quarters/
Fri, 02 Nov 2018 02:03:52 +0000http://leancrew.com/all-this/2018/11/drawing-the-quarters/
the usualsources, Apple announced that today’s quarterly figures will be the last to include unit sales for the Mac, iPhone, and iPad. I’ve been posting plots of units sales since April of 2015, when I shook up the staid world of Apple punditry by introducing it to the four-quarter moving average. It’s a sad day here at Drang Global Headquarters as we post the last of its kind:]]>
As you probably heard on Twitter, or from theusualsources, Apple announced that today’s quarterly figures will be the last to include unit sales for the Mac, iPhone, and iPad. I’ve been posting plots of units sales since April of 2015, when I shook up the staid world of Apple punditry by introducing it to the four-quarter moving average. It’s a sad day here at Drang Global Headquarters as we post the last of its kind:

The dots are the raw sales figures, the thick solid lines are the four-quarter moving averages, and the thin dashed lines connect the same quarters in consecutive years, giving a sense of the year-over-year changes. You can see why Apple isn’t particularly interested in showing these figures anymore—you have to get out a magnifying glass to see any recent growth.

Oddly enough, back in August, after the last set of quarterly results came out, I decided it was time to start plotting revenue. Not because I had any inkling that Apple would stop providing unit sales, but because I wanted to compare these three products to Services and Other Products, the two remaining categories in Apple’s quarterly reports. So I dug back through the reports and added revenue to my data files for the Mac, iPhone, and iPad. This data update and a few small edits to my plotting script allowed me to quickly produce a new version of the chart above, but with this one focused on revenue:

You can see why Apple prefers to talk revenue.

The dominance of the iPhone makes it hard to see the Mac and the iPad down there in the mud, so let’s show them all by themselves:

(Stephen Hackett, feel free to use this the next time your co-hosts talk about the fading Mac platform. Do it quickly, though, as I suspect the iPad will rebound next quarter.)

Of course, in true best-laid-plans style, I didn’t get around to making data files for Services and Other Products, so I can’t make the plots I intended to. Next time.

]]>
Location, location, locationhttp://leancrew.com/all-this/2018/10/location-location-location/
Wed, 31 Oct 2018 04:25:16 +0000http://leancrew.com/all-this/2018/10/location-location-location/
the naive one and the improvement), Vinay Kashyap asked me on Twitter if I knew of a way to get the latitude and longitude of a photo. I didn’t, but with a little JSON exploration, I figured it out. And now I’ll inflict it on you.]]>
After my two posts on extracting photo metadata using Shortcuts (the naive one and the improvement), Vinay Kashyap asked me on Twitter if I knew of a way to get the latitude and longitude of a photo. I didn’t, but with a little JSON exploration, I figured it out. And now I’ll inflict it on you.

First, you can’t use the Location property of the photo.1 Here’s a Share Sheet shortcut that tries that, where the input is restricted to Images and the contents of the Show Result step is the Location property of the Shortcut Input magic variable.

The Location property typically returns a street address, although in some of my tests, on photos taken way out in national or state parks, it returned just a city and state. But whatever it returns, it isn’t the latitude and longitude. For that we need to use the Metadata Dictionary property, which you’ll find if you scroll about two-thirds of the way down the property list.

When you choose the Metadata Dictionary, you’ll get an opportunity to choose which item of this dictionary to return. But in contrast to selecting a photo property, you don’t get a list to select from—you have to know the name (or key) of the dictionary item to return. The key we want is {GPS} (yes, with the curly braces).

How do you know which key name to use? You don’t until you understand the dictionary structure. If we leave the key field blank, this step will return the entire dictionary in JSON format. Here’s an example, where I’ve used indentation to make the dictionary structure easier to see:

As you can see, this is a complex nested data structure. The latitude and longitude are in a subdictionary—a dictionary within a dictionary—whose key is {GPS}.2 The {GPS} dictionary also includes some cool stuff like the altitude and the direction the camera was pointing, but we’ll leave them aside for now.

OK, so now that we know which item of the Metadata Dictionary to select, how do we pull the latitude and longitude out of it? The best way I found was to save the Metadata Dictionary as a variable called GPS and then select the values of that dictionary using the key names I found in the JSON.

Putting it all together, we get this simple three-step shortcut

that returns the latitude and longitude of the photo’s location.

The simplicity of the shortcut stands in contrast to the complexity of the Metadata Dictionary and glosses over the JSON spelunking needed to figure out where the data was hiding. But now that we have one example, we can use it to pull out all kinds of metadata. I’m especially curious about the {MakerApple} subdictionary, with its mysterious numerical key names.

]]>
Replacing regexes in Draftshttp://leancrew.com/all-this/2018/10/replacing-regexes-in-drafts/
Mon, 29 Oct 2018 01:24:05 +0000http://leancrew.com/all-this/2018/10/replacing-regexes-in-drafts/
Drafts works. The Find part is normal, but the Replace is a little different.]]>
If you’re a longtime regular expression user, you may be surprised at how the Find and Replace feature in Drafts works. The Find part is normal, but the Replace is a little different.

Let’s assume we have a set of book titles with subtitles set off by colons1:

The Films of Fritz Lang: Allegories of Vision and Modernity
In Pharaoh's Army: Memories of the Lost War
Understanding Comics: The Invisible Art
A Matter of Interpretation: Federal Courts and the Law
The Digital Dialectic: New Essays on New Media
I Saw Esau: The Schoolchild's Pocket Book

We’d like to reformat these titles by putting each subtitle on an indented line under the main title and then separating them all with blank lines. Like this:

The Films of Fritz Lang
Allegories of Vision and Modernity
In Pharaoh's Army
Memories of the Lost War
Understanding Comics
The Invisible Art
A Matter of Interpretation
Federal Courts and the Law
The Digital Dialectic
New Essays on New Media
I Saw Esau
The Schoolchild's Pocket Book

For compatibility with the formatting here on the blog, I’ve indented the subtitles above with two spaces, but let’s say we really want them indented with a tab.

If we were working in Perl, and had these titles in a text file, we could do the reformatting with this one-liner:

perl -pe 's/^(.+): (.+)$/$1\n\t$2\n/' titles.txt

where the find regex is

^(.+): (.+)$

and the replace regex is

$1\n\t$2\n

Most regular expression engines nowadays take their cues from Perl (Perl 5, anyway), so although Python isn’t really set up for one-liners, the find and replace regexes we’d use in a Python script are the same.

The only difference is the use of backslashes instead of dollar signs to identify the parts captured by parentheses.

So if we wanted to do this reformatting in Drafts, it’s only natural to try this:

As you can see from the lower half of the screenshot, the finding part worked as expected, but if we tap the Replace All button, we get this:

The Films of Fritz LangntAllegories of Vision and Modernityn
In Pharaoh's ArmyntMemories of the Lost Warn
Understanding ComicsntThe Invisible Artn
A Matter of InterpretationntFederal Courts and the Lawn
The Digital DialecticntNew Essays on New Median
I Saw EsauntThe Schoolchild's Pocket Bookn

What’s happened is the \n and \t in the replacement regex have not been interpreted as newline and tab. Instead, the backslashes have been interpreted as “treat the next character as literal, even if it would normally have a special meaning in a regex,” which is why we see an nt between the main titles and subtitles and an n at the end of each line.

So how do we get what we want? Don’t overthink it. If you want a newline in the replacement, type Return; if you want a tab, type Tab. Like this:

It’s hard to see because the Replace field isn’t tall enough to show three lines at once, but there’s a Return after the $2.

This is actually easier, but because of years of using \n and \t, I almost always type it the Perlish way first.

By the way, if you’re wondering whether you should use “real” tabs and newlines or the backslashed metacharacters in the Find field, the answer is Yes. You can use either one.

]]>
Markdown footnotes in Draftshttp://leancrew.com/all-this/2018/10/markdown-footnotes-in-drafts/
Sun, 28 Oct 2018 03:02:48 +0000http://leancrew.com/all-this/2018/10/markdown-footnotes-in-drafts/
Drafts on my iPad. A couple of weeks ago, I decided I wanted to add a bit of automation to avoid retyping the footnote marker. Seemed like an easy task, but it took me three tries to get what I wanted.]]>
Footnotes in Markdown are pretty easy to just type in directly, and that’s what I did for quite a while when writing posts in Drafts on my iPad. A couple of weeks ago, I decided I wanted to add a bit of automation to avoid retyping the footnote marker. Seemed like an easy task, but it took me three tries to get what I wanted.

First, let’s go over what I mean by “footnotes in Markdown.” As defined by John Gruber, Markdown doesn’t support footnotes, but many popular implementations, like MultiMarkdown and PHP Markdown Extra (which I use to build ANIAT pages) do. I’ve even heard tell that Gruber himself uses an off-brand extension to plain ol’ Markdown to handle footnotes on Daring Fireball.

All of these implementations use a slight variation on Markdown’s reference link syntax. Here’s an example:

The low angle feels better when I'm working while sitting
cross-legged on a bed or floor.[^chicago]
[^chicago]: Twenty-five or -six to four.

The idea is to use an reference string that starts with a caret inside square brackets where you want the footnote marker to appear. Then elsewhere in the text (and it could be anywhere, but I like putting it right after the paragraph with the marker) comes that same marker string followed by a colon and the footnote text. The goal of my automation was to type the marker only once and to format the parts on separate lines.

My first thought was to use a TextExpander snippet with a fill-in. Drafts supports TextExpander and so do many other text editors, so this would be a portable solution. Here’s the snippet:

The idea here is to work easily in the most common situation, which is when I’m typing along and think “here’s a good spot for a footnote.” After typing the snippet’s abbreviation, I’m swept away to the TextExpander app, where I fill in the part of the marker string that comes between the caret and the closing bracket.

After typing in the marker text and tapping the Done button, I’m taken back to Drafts, where the snippet has been put in place. And here’s where this solution is less than ideal. Moving from Drafts to TextExpander and back takes Drafts out of edit mode—when I return from the round-trip to TextExpander, there’s no cursor blinking in the draft, so I can’t just start typing in the footnote text. I have to tap after the colon to reestablish editing mode and set the cursor where it needs to be to type the footnote text. The need to shift back into editing mode (which will happen with any TextExpander snippet that uses fill-ins) is annoying and made me search for another solution.

My second solution was a two-step Drafts action that used the Prompt and Insert Text step types. The Prompt step asks for the marker,

and the Insert Text step uses that marker to insert text in a manner very similar to the TextExpander snippet

In practice, there were two problems with this solution, both having to do with Drafts’s mode shifting. As with the TextExpander snippet, after the text is inserted, I need to tap after the colon to put Drafts back into editing mode and set the cursor. But even before that, when the Prompt window appears, the text field in it doesn’t have focus, so I have to reach up from the keyboard to tap in it before typing. So this was actually worse than the TextExpander solution.

To get what I really wanted, automation that didn’t take me away from the keyboard to tap the screen, I needed to do some scripting. What I came up with was a single-step Drafts action that works like this:

When I want to insert a footnote, I type the whole marker string—brackets, caret, and all—where the footnote marker should go.

The low angle feels better when I'm working while sitting
cross-legged on a bed or floor.[^chicago]|

(The vertical bar shows the cursor position.)

Then I invoke the Footnote action, which is in my “Blogging” action set and has both a keyboard button with an asterisk glyph and an external keyboard shortcut of ⇧⌘8 (⇧8 is the asterisk). This adds a blank line, a copy of the marker string, a colon, and a space. And it sets the cursor after the space, so I’m ready to type in the footnote text.

The low angle feels better when I'm working while sitting
cross-legged on a bed or floor.[^chicago]
[^chicago]: |

This solution requires a little bit more typing—I have to type the brackets and caret myself—but requires no tapping on the screen. The action is defined this way,

Line 5 grabs the 25 characters before the cursor and puts that string into the variable nearby.1 Lines 6 and 7 then search that string for the bracket-caret-string-bracket text that defines a Markdown footnote marker and put it into the variable fnMarker.

Lines 11 and 12 insert the blank line and the marker followed by a colon and a space. Line 13 sets the cursor after the space, ready for typing in the footnote text.

This was, clearly, harder to write than the TextExpander and Prompt/Insert solutions, but because it does what I want instead of almost what I want, it was worth it.

I can’t search through all the text before the cursor, because there may be other footnote markers earlier in the post. I chose to look back 25 characters because I don’t expect to ever use a marker string longer than that. ↩

]]>
Tapped outhttp://leancrew.com/all-this/2018/10/tapped-out/
Sat, 27 Oct 2018 06:16:14 +0000http://leancrew.com/all-this/2018/10/tapped-out/
Have I ever mentioned how frustrating I find programming in Shortcuts? I have? Well, I’m going to do it again. This time, I’m going to vent about Magic Variables, which everyone says are great but which I despise. Sort of.

First, let me thank Tim Nahumck for gently telling me on Twitter that my Image Info shortcut was horrifically (my word, not Tim’s) inefficient and could be cut down from sixteen steps to just one.1 This one:

All those green bubbles come from a single Magic Variable and its many parts. I’m going to show how to put them together—partly because it might help you, but mostly in the hope that doing this will reinforce the use of Magic Variables with me.

First, add the Show Result action to a blank shortcut and tap in the text field to start editing.

We want to get a property of the image that’s the input to the shortcut, so we tap on the magic wand button above the keyboard to get a new view of the shortcut that shows where the Magic Variables are. Because this shortcut is so small, there’s only one, the Shortcut Input.

Tap on that green bubble to add it to Show Results. Once you see it in the Show Results text field, tap on it there to bring up a list of its properties.

Since we want the Name property, tap on it, and the property will show up as a sort of extension to the green bubble.

After adding a period after the name, we add that same Shortcut Input Magic Variable a second time, but this time we scroll down to choose the File Extension property.

Keep doing this again and again, each time choosing a different property of the Shortcut Input. When we’re done, we get this, which I’m showing in a wider view, so you can see the line breaks.

This is a far more idiomatic shortcut than my original. Not just because it’s one step instead of sixteen, but because it leverages Shortcuts’s real power, much of which lies in its Magic Variables. Which I hate.

OK, I don’t really hate Magic Variables themselves, what I hate is this hunting around to figure out where they are (in multi-step shortcuts, they appear throughout the workflow) and what they can do. Intellectually, I know this is essentially the same as looking through documentation, but it feels different. Documentation allows you to get a broader view of the capabilities of a language; even when you’re looking up a specific feature, in good documentation you see related features at the same time. Shortcuts treats this process like a game of hide and seek.

And although my inefficiency in building the original version of this shortcut was due to my ignorance, even after Tim cured me of that ignorance, the tap-tap-scroll-tap bullshit of adding each new piece to the Show Results step was maddening. The Shortcuts programming environment doesn’t reward you for knowing what you want to do; you still have to tap and scroll and tap and scroll to get it done.

Maybe I’ll get used to Shortcuts programming. I hope so, as it’s the only game in town. My fear, though, is that it’ll be like AppleScript, a language I’ve been using for over 20 years and have never felt comfortable with.

Had I been checking my email, I would have seen that Matthias Fichtner sent me a similar message before Tim did, and I would have credited him for the improved shortcut. Great minds think alike (and my mind wasn’t one of them). ↩

]]>
Image Info shortcuthttp://leancrew.com/all-this/2018/10/image-info-shortcut/
Fri, 26 Oct 2018 22:01:34 +0000http://leancrew.com/all-this/2018/10/image-info-shortcut/
Update Oct 27, 2018 1:21 AM
This shortcut, with the same functionality, has been completely rewritten in a more idiomatic Shortcuts style. You should probably read that post instead of this one.]]>

Update Oct 27, 2018 1:21 AM
This shortcut, with the same functionality, has been completely rewritten in a more idiomatic Shortcuts style. You should probably read that post instead of this one.

When reviewing images in my iOS Photos library, I often find myself wishing I could see what size they are (both in pixels and in bytes) and what format they are (screenshots start out as PNGs, but when you edit them they turn into JPEGs). And if I’m going to email them or upload them to a server, it’s nice to know their filenames. The Photos app isn’t very helpful with any of those things, so I made a Shortcut that is.

To use the Image Info shortcut, I simply select an image in Photos and run the shortcut to display an information window.

The filename includes the extension, which gives the format. Then comes the size in pixels (width×height) and the size in bytes (kilo or mega). Very handy.

As you can see, Image Info starts by saving the input image to a variable. It then repeatedly queries that image for the various pieces of information, saving each to its own variable. Finally, the last step shows all of the collected information, formated for easy reading.

You might be thinking it’d be nice to include the time and date the image was created. I think so, too, but I haven’t been able to get that to work. Whether I ask for the image’s creation date or modification date, what appears in the results window is the current date and time, which isn’t very helpful. I guess I should file a bug report.

Update Oct 26, 2018 5:24 PM
Instead of Creation Date and Last Modified Date, which are EXIF names I’m used to, I should have tried Date Taken, which does provide the correct date.

]]>
What’s up?http://leancrew.com/all-this/2018/10/whats-up/
Fri, 26 Oct 2018 03:23:23 +0000http://leancrew.com/all-this/2018/10/whats-up/
October Event Draft episode, Myke Hurley and Jason Snell discussed1 the likelihood of Face ID coming to the iPad (high) and what that means for people who use their iPads mostly in landscape mode. They were talking about landscape as a single orientation, but I see it as two.]]>
During the Upgrade podcast’s October Event Draft episode, Myke Hurley and Jason Snell discussed1 the likelihood of Face ID coming to the iPad (high) and what that means for people who use their iPads mostly in landscape mode. They were talking about landscape as a single orientation, but I see it as two.

People have been thinking about this since Face ID came out last year with the iPhone X. Face ID on the X—and, so far, on the X🅂— works only when you point the device toward your face in portrait orientation. While this is fine for phones, which are used overwhelmingly in portrait, it would be a disaster for iPad Pros, which are commonly used as pseudo-laptops in landscape orientation.2

The 2018 iPad Pro will include Face ID with the same image signal processor as the iPhone XS, iPhone XS Max and iPhone XR. Further, we can confirm that Face ID on the new iPad Pro will work in both portrait and landscape orientations, though it won’t work upside down.

So, problem solved, right? I hope so, but I have a nagging doubt. Not whether landscape will be supported, but whether both landscapes will be supported.

I have this Sena Vettra folio case for my current iPad Pro and would like to have something similar for my next one. Like the Apple Smart Cover, the Vettra can position the iPad at an upright angle, similar to a laptop screen,

and at a lower angle

I use both of these. The upright angle feels better when I’m watching a movie or working at a desk. The low angle feels better when I’m working while sitting cross-legged on a bed or floor.3

As you can see from the position of the home button in those two images, there are two landscape orientations, and I use both of them a lot. I’m haunted by the last bit of the Guilherme Rambo quote: “though it won’t work upside down.” If Apple decides that there’s a right-side up and an upside down to landscape orientation—as there is to portrait—I’m screwed.

Because I read a lot on my 9.7″ iPad Pro, I use it in portrait mode fairly often, possibly even as much as I use it in landscape. I think I’m unusual in this, and even I’d hate Face ID in portrait only. ↩