And now it’s all this I just said what I said and it was wrong. Or was taken wrong. Mon, 28 Jul 2014 05:16:40 +0000 en-US hourly 1 Casting about Mon, 28 Jul 2014 05:16:39 +0000 A few months ago, I got tired of the constant “media file error” messages Downcast was sending me and began looking for another iOS podcatcher.

Downcast media file error

There are certain features I find essential in a podcatcher:

  • Download control. Of the podcasts I subscribe to, some I listen to every episode of and others I listen to only when the guest and topic seem interesting. Of the former, I want every episode downloaded automatically; of the latter, I want episodes downloaded only after I’ve read their descriptions.

  • Playback order control. When I set off on a bike ride or a long drive, I like to have playback set to continuous play and have a series of episodes queued up in a particular order. This allows me to move from one show into another without swiping or tapping at the user interface.

  • Skip ahead/back. As much as I appreciate their sponsorship of podcasts I like, I really don’t need to hear another Squarespace ad.

Other aspects of the user interface will color my opinion of an app, but these trump the rest.

I gave Instacast another shot, and the experience was, if anything, worse than the last time I tried it. Not only is the layout of the app not to my taste, the skip ahead and skip back buttons did absolutely nothing. To be fair, I reinstalled Instacast after it was updated earlier this month, and the skip buttons in the newer version worked just fine. Still, it’s not the app for me.

Pod Wrangler has perhaps the best scrubber in the business, and I have free access to its advanced features because I use Feed Wrangler as my RSS sync service. But it doesn’t give me download or playback order control I want.

Pod Wrangler scrubber

Castro gets points for the pun in its description—high fidelity podcasts—has a scrubber on par with Pod Wranger’s, and has a fun interface overall, with almost all the navigation done by swiping left and right. But the playback order control wasn’t there.

Castro mid-swipe

Pocket Casts was a very strong contender, with all the controls I need. Like Castro, it has a fun user interface. When you turn your phone over in an episode list, for example, the main body of the screen turns in place, but the mini-player strip “falls” from one end of the screen to the other.

Pocket Casts mid-flip

One thing I dislike about Pocket Casts is its sleep timer. Instead of just having a button to set the timer, it forces you tap a button and then move a slider. Not only is this awkward and slow, it’s unnecessarily precise. No one needs to-the-minute resolution on a sleep timer.

Still, because it had most of what I find essential in a podcast app, Pocket Casts had taken Downcast’s spot in my dock. Until I got invited to try the Overcast beta.

By now you’ve probably read several reviews of Overcast, so you don’t need me to tell you about its two killer features: Voice Boost and Smart Speed. I will, however, suggest that you experiment with both of them instead of just turning them on for all podcasts.

If a show tends to be well-recorded, the equalization of Voice Boost is unnecessary and will simply make the overall playback louder. This may not seem like a big deal, but I noticed on a recent car trip that Siri’s turn-by-turn instructions—which are usually at the same volume as whatever I’m listening to—were much quieter than the Voice Boosted podcast she was interrupting and were hard to hear. On the other hand, certain guests on In Our Time are so soft-spoken that even the heroic efforts of BBC’s recording engineers to turn up the gain can’t make them as loud a Melvin Bragg or the other guests. I expect Voice Boost to be a big help with those shows.

And while it’s nice to have dead air reduced, I wouldn’t use Smart Speed on The Bugle, because comedy relies on timing—including pauses. I’ve also found that John Siracusa without pauses is exhausting.

My favorite feature of Overcast is the natural way it allows you to reorder the episodes in any playlist. Just tap the Edit button in the upper right corner and start dragging.

Overcast playback reordering

This is a big advantage over Pocket Casts. In Pocket Casts, smart playlists—which it calls Filters—do not allow arbitrary reordering. Only playlists created by hand allow that. So you have to move episodes into an ad hoc playlist before you can set their order. This is not the greatest burden in the world, but the freedom Overcast gives you to rearrange smart playlists is clearly superior. I haven’t felt the need to make any new playlists in Overcast; I just rearrange episodes in the Unplayed list.

You might be wondering why I’m writing this post a week and a half after Overcast was released. It isn’t because I needed extra time with the app, nor is it because I’m lazy.1 When Overcast came out, I had just shifted back to Pocket Casts as a test. I figured that if I were comfortable with Pocket Casts after using Overcast, then there really wasn’t any reason to switch. But after a week of Pocket Casts, I found myself still missing features in Overcast. That’s when I knew Overcast was going to be my podcast app.

Overcast is by no means perfect. I have, for example, occasionally seen error messages similar to the “media file error” messages that drove me from Downcast. Fortunately, those have been quite rare and they’ve never caused Overcast to crash. So my months-long search for a podcast app I’m happy with is over.

  1. I am lazy, but that has nothing to do with the timing of this post. 

]]> 0
Presentations and expectations Sun, 27 Jul 2014 04:05:57 +0000 You’ve probably heard by now about the latest bestseller from the MacSparky publishing empire: Presentations. In it, David Sparks does his usual thorough job of walking you through the nuts and bolts of building a presentation in Keynote. But Presentations is more than just a software manual. David also hands out good advice on hardware (including preparing for hardware disasters) and putting together a good performance.

David also fights the good fight for better presentations independent of software and hardware. The first two chapters in particular talk about what makes a compelling presentation, but there are nuggets of wisdom regarding pacing, focus, and effective storytelling sprinkled throughout. This is the stuff that’s most likely to be ignored—often because presentations are expected to be bad.

You may remember this article by Paul Ford from a couple of months ago that made fun of presentation slides used by the military. Theses slides violate all the conventional wisdom by being overpacked with words and graphics.

Example military slide

from Medium

Eric Hess had a very nice followup post a few days later. He didn’t defend the look of these presentations, but he did explain their genesis:

Tragically, the military shares a misconception with the rest of the government and much of the business world that the slides should be able to act as a substitute for the speaker. While you’d think this would drive presentation designers towards clarity, it often does exactly the opposite. Diagrams with bulleted annotations can rarely provide the clarity and fidelity of well-written prose supported by a few well-chosen graphics. Yet busy executives don’t want to take the time to read a multipage essay.

I don’t have any experience with the military, but what Eric says matches perfectly with what I’ve seen from manufacturers. When I start a new consulting project, I usually get sent a bunch of paperwork (sometimes on paper, more commonly on disc) with information on the product at issue. Inevitably, as I flip through the stack of drawings, photos, and test data, I’ll run into a series of pages that have to be turned from portrait to landscape: a PowerPoint deck describing some aspect of the product’s development. It’s not a report written with paragraphs that build on each other; it’s a set of graphs and disconnected sentence fragments arranged as bullet points.

It’s never clear to me whether there actually was a live presentation associated with the deck. But it is clear that the deck was expected to stand on its own—a substitute for the speaker, in Eric’s words—and that it was circulated among the relevant engineers and managers in the company and expected to be read as if it had all the information and clarity of a report.1

This is why all the well-intended advice on making good presentations doesn’t get followed. There is an expectation in many places that the slide deck will not simply be an adjunct to a presentation; it will be the only permanent record of the ideas and information contained in that presentation, and it is judged as such by the presenter’s superiors. When a slide deck takes on that burden, both it and the presentation lose the fluidity that David’s book tries to steer you toward.

The answer, of course, is to have both a written report and a presentation. This is the norm in the academic world, where the published paper is one thing and the talk based on it is another. But this is considered inefficient in most businesses, so the poor slide deck has to pull double duty. And ends up being bad at both jobs.

  1. Reports can be poorly written, of course, but they tend to be more disciplined and more coherent than slide decks. The need to write sentences that form paragraphs and paragraphs that form sections imposes a structure on the writer’s thinking. I can’t remember where I heard or saw this, but Andy Ihnatko once said something like “I don’t write to say what I think; I write to figure out what I think.” A bunch of bullet points won’t do that. 

]]> 0
Better window screenshots Fri, 25 Jul 2014 03:28:08 +0000 For some time now, I’ve been using a homemade utility, snapflickr, for taking screenshots and automatically uploading them to Flickr. It worked really well for most screenshots, but there were some, like this one from yesterday’s post,

Character Viewer

that just don’t look right because the desktop background border is either too thin or uneven or both. Today I updated snapflickr to fix that.

The problem arose because I was including the drop shadow in window screenshots. There are some, like Dan Benjamin, who think this is an abomination. I agree that the shadows are too big, but don’t like the “open” edges of window screenshots that don’t have the shadow.

Character Viewer bare

On a white background, it looks like contents of the window are going to fall out.

As a compromise, snapflickr took screenshots with the shadow, cropped them down to a more reasonable size, and then composited them on top of a Solid Dark Aqua Blue background color. This worked fine for most windows, which have standard sized shadows, but palette and other utility windows often have smaller shadows. Cropping that looked fine on a normal window looked like shit on a palette window. I tried less cropping for palette windows, but apparently they don’t all use the same size shadow. As you can see from the top screenshot, the lesser cropping didn’t always lead to nice results.

So now snapflickr takes a different approach to window screenshots. It doesn’t include the shadow but adds a 16-pixel border around the outside to provide definition.

Character Viewer with background border

This looks good with any type of window and is what I should have done from the beginning.

Because I sometimes use snapflickr to take screenshots of a rectangular area instead of a window, I needed to add an option not to include the border. That wasn’t too hard.

snapflickr dialog

The border is selected by default, because that’s what I want most often, but it can be turned off if necessary.

The snapflickr source code is in this GitHub repository. It requires the Python Imaging Library to add the border, Carsten Blüm’s Pashua application/library to display the dialog, and Sybren Stüvel’s Flickr API module to do the uploading.

]]> 0
Scripting your scripting Thu, 24 Jul 2014 04:22:37 +0000 A couple of days ago, Rob Trew tweeted a link to a shell script he wrote that prints out an emoji clock face based on the time it’s given.

Simple bash .sh gets emoji clockface (stdout|clipboard) with specified time (to nearest preceding half hour)…

ComplexPoint (@ComplexPoint) Jul 22 2014 10:31 AM

It sounded like a fun little programming project and possibly even useful.1 Because I wanted to round to the nearest half hour instead of the nearest preceding half hour, and because my shell scripting is abysmal, I decided to rewrite it in Python.

I knew immediately that the key feature of my script would be a dictionary that mapped a time written as text, like “8:30,” to the corresponding emoji, 🕣. The rest of the script would just be input, output, and rounding. Here’s the script:

 1:  #!/usr/bin/python
 2:  # -*- coding: utf-8 -*-
 4:  from sys import argv
 5:  from time import strftime
 7:  clocks = {'12:00': '🕛', '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
 8:             '2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
 9:             '4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
10:             '6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
11:             '8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
12:            '10:00': '🕙', '10:30': '🕥', '11:00': '🕚', '11:30': '🕦'}
14:  # Get the argument, which should be a time string, like "8:10."
15:  # If there's no argument, use the current time.
16:  try:
17:    oclock = argv[1]
18:  except IndexError:
19:    oclock = strftime('%I:%M')
21:  hour, minute = [ int(x) for x in oclock.split(':') ]
23:  # Round to the nearest half-hour, because there are no
24:  # emoji clockfaces for other times.
25:  rminute = int(round(float(minute)/30)*30)
26:  if rminute == 60:
27:    rminute = 0
28:    hour = 1 if hour == 12 else hour + 1
30:  print clocks['%d:%02d' % (hour, rminute)]

The dictionary is defined in Lines 7–12. By including the encoding line at the top of the script, I was able to include the clock faces directly in the source code instead of messing around with hex character codes.

But the script itself isn’t the point of this post. What I really want to talk about is how I wrote it. I knew what Lines 7–12 were going to look like, and I really didn’t want to type it out. Not only would it be tedious, I’d almost certainly make an error somewhere. So I used a combination of IPython and BBEdit’s search-and-replace tools to build Lines 7–12 step by step.

Step 1 was generating a list of times. I used these commands in an IPython session to print a list of times, one per line:

for h in range(1, 13):
  print "'%d:00'\n'%d:30'" % (h, h)

I copied this into a BBEdit window, moved the last two lines, 12:00 and 12:30, to the top, and did this find-and-replace:

BBEdit replacement dialog

This gave me a single line that looked like this,

12:00', '12:30', '1:00', '1:30', '2:00', '2:30', '3:00', '3:30',
'4:00', '4:30', '5:00', '5:30', '6:00', '6:30', '7:00', '7:30',
'8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00', '11:30', '

which I’ve broken up here for ease of reading. I cleaned up the front and rear to turn it into a Python list assignment,

times = ['12:00', '12:30', '1:00', '1:30', '2:00', '2:30', '3:00',
'3:30', '4:00', '4:30', '5:00', '5:30', '6:00', '6:30', '7:00',
'7:30', '8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00', '11:30']

which I entered into my IPython session.

Step 2 was to do a similar thing for the clock faces. I “typed” them in, one per line, using the Character Viewer,

Character Viewer

and then converted them into a list assignment that I entered into IPython.

faces = ['🕛', '🕧', '🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓',
'🕟', '🕔', '🕠', '🕕', '🕡', '🕖', '🕢', '🕗', '🕣', '🕘', '🕤',
'🕙', '🕥', '🕚', '🕦']

Now comes the fun part. With times and faces defined, it was easy to generate most of the dictionary assignment statement with

print ",  ".join("'%s': '%s'" % (t, f) for t, f in zip(times, faces) )

That gave me this string

'12:00': '🕛',  '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
'2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
'4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
'6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
'8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
'10:00': '🕙',  '10:30': '🕥',  '11:00': '🕚',  '11:30': '🕦'

where, again, I’ve added line breaks here to make it easier to read.

A few quick edits turned that string into

clocks = {'12:00': '🕛', '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
           '2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
           '4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
           '6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
           '8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
          '10:00': '🕙', '10:30': '🕥', '11:00': '🕚', '11:30': '🕦'}

which is the nicely formatted dictionary assignment statement you see in Lines 7–12.

Does this seem like more work than just typing it out? It wasn’t. One of the great things about writing scripts frequently is that you become fluent enough to know instinctively how cobble together little bits of code like this. You also learn that some things, like the beginning and end of a list assignment statement, are more efficiently done by typing than by programming, so you don’t waste time trying to script those parts.

Sometimes your first instinct is a little off. I initially wrote the line that built the dictionary string this way:

print ", ".join("'%s': '%s'" % (t, f) for t, f in zip(times, faces) )

Do you see the difference? There’s only one space after the comma in the joining string instead of two. When I saw the output of this statement, I realized that to get the times lined up nicely I’d need a mixture of one and two spaces, depending on whether the hour was a one- or two-digit number. Since there are nine one-digit hours and only three two-digit hours, it would be faster to put two spaces everywhere and delete one in front of the two-digit hours. I reran the line with two spaces after the comma and saved myself twelve edits.

I’m sure there are still better ways to do this, further tricks that would have saved me even more typing. But even though I didn’t save as much time as I might have, I still saved a lot, mainly because I automated all the quotes, colons, and commas that I tend to mistype.

  1. It is useful for Rob. He makes links in FoldingText to his timed Reminders and includes the appropriate clock face in the link text. 

]]> 0
Customer service Mon, 21 Jul 2014 01:51:14 +0000 Level One

I put my mom on a plane this afternoon to fly back home after a visit. She’s been having cognitive problems for a while and airports—especially one as big as O’Hare—are not a familiar environment for her, so I wanted to make sure I could take her to the gate and see her off. Other relatives would be picking her up at the other end—a very small airport that’s only a few steps from gate to baggage claim.

To be allowed through security without a ticket or boarding pass requires something called a gate pass. The airline’s website said that gate passes were available for people accompanying travelers who need assistance, and I called the airline a few days ago to confirm that I’d be able to get one at the ticket desk when we checked her bag.

You will not be surprised to hear that the people at the ticket desk—both our initial agent and his superior—had no idea how to issue me a gate pass. Curiously, the agent did ask for my photo ID, even though he had no idea what to do with it. Force of habit, I guess. Eventually, the supervisor hit upon the idea of sending us to the Special Services desk, where we would become someone else’s problem.

The agent at the Special Services desk knew everything about gate passes and told me right away that I wouldn’t be able to get one. “They’re being very tight with those.”

When I explained to the agent that I’d been told by the airline that I could get a gate pass, she told me with great confidence that the people manning the airline’s 800 number didn’t know anything. But she took my driver’s license, typed my information into her computer, and my gate pass printed out immediately.

“Do you know which gate you’re going to?” she asked sharply as she handed it over.

“No, I haven’t checked yet. I wasn’t sure until just now that I was going to get in.”

“Well, it’s F6A. It’s right on the pass.” There was a note of triumph in her voice, as it was clear she had bested me.

The rest of our visit to O’Hare went smoothly. We didn’t even use up all the extra “snafu time” I’d put into our schedule, so we were able to walk slowly to the gate. Most important, Mom got home safely and wasn’t stressed.

Level Two

Once Mom was on the plane, I drove to my office to knock off a few todos before leaving tomorrow morning on a weeklong business trip. One of the items on my list was to write down our network’s new IP numbers.

Earlier in the week, our company’s service provider had reworked our connections and installed a new router and interface hardware. In the process, our block of IP numbers was changed. I asked the installer why we couldn’t keep the old numbers—they are, after all, under the control of the provider, and we weren’t switching providers. He gave one of those syntactically convoluted answers that’s easily translated to “I don’t know, but I don’t want you to know that I don’t know.” I didn’t pursue it because

  1. it wouldn’t do any good; and
  2. it’s not a big deal to work with the new numbers.

I’d probably want access to company network while I was out of town, so I needed to write down the new numbers to take with me. But doubt—partly from the installer’s word jumble, partly from my still-fresh experience at O’Hare, but mostly from too many disappointing experiences with IT professionals—made me decide to test the new IP numbers before I left the office.

None of them worked. Not a single one.

After some network inquiry, diagnosis, and testing, I learned what the new numbers really were. They weren’t even close to what the installer had given us. Not a single octet was the same, nor was there any chance that digits had been transposed. What we’d been given was just thoroughly wrong, as if it had come from a random number generator.


As I sit here typing and enjoying a beverage, I don’t feel angry or outraged, nor am I disheartened by the sad state of the world. I’m just happy I planned for these mistakes and for others that didn’t happen. It’s something I wouldn’t have done when I was younger, and I would have ended this day upset. Now I see my interactions with customer service as a sort of strategy game: can I plan my way around the obstacles the game will put in my way? Today I came out on top. Tomorrow is another round.

]]> 0
Quicker Markdown linking with TextExpander Wed, 16 Jul 2014 05:15:41 +0000 I listened to the Mac Power Users TextExpander episode today and noticed that I come off as a bit of a dick, always correcting others. This was surprising only inasmuch as I wasn’t on the show. Normally, I have to be present to demonstrate my dickishness, but David and Katie have dealt with me enough to limn my essence without me. Still, as Marvin and Tammi say, ain’t nothing like the real thing, baby. Let me demonstrate by explaining why I think David’s Markdown link snippet could use some improvement.

He describes it starting at about 38:30. The snippet uses the Mac clipboard to paste a URL into the proper spot in a Markdown link structure. To use it, David

  1. Switches to Safari, presumably through ⌘-Tab.
  2. Selects the URL of the current page with ⌘L.
  3. Copies it to the clipboard with ⌘C.
  4. Switches to his text editor with ⌘-Tab again.
  5. Invokes his snippet by typing its abbreviation.

He saves a little time by keeping the ⌘ key pressed through some of the steps, but there’s still too much context shifting and too many repeated keystrokes. With a little AppleScript, all he’d need is Step 5.

Here’s my first attempt,

Markdown link TE snippet

and here’s the AppleScript it uses:

 1:  tell application "System Events"
 2:    set numSafari to count (every process whose name is "Safari")
 3:    set numChrome to count (every process whose name is "Google Chrome")
 4:  end tell
 6:  if numSafari > 0 then
 7:    tell application "Safari" to set fURL to URL of front document
 8:  else
 9:    if numChrome > 0 then
10:      tell application "Google Chrome"
11:        set frontIndex to active tab index of front window
12:        set fURL to URL of tab frontIndex of front window
13:      end tell
15:    end if
16:  end if
18:  get "[%|](" & fURL & ")"

Lines 1-16 get the URL of the current page in either Safari or Chrome. These lines were stolen directly from my trusty ;furl snippet, whose history can be traced back to this old AppleScript I used to invoke through Quicksilver.

Line 18 does something pretty cool. It returns a string that looks something like this


where what’s inside the parentheses is the URL of the current page. The cool part, though, is the %| inside the brackets. This is the TextExpander code for “put the cursor here after the expansion,” which is exactly what happens when this snippet is run. So this snippet gets the URL, creates the Markdown inline link and positions the cursor right where you want it to type the link text. No context shifting, no fiddling with the clipboard.

This, by the way, is why TextExpander is such a great tool. Not only can you use it to run scripts, but the output of those scripts will then be interpreted as TextExpander variables.

In fact, that last line could be written this way,

18: get "[%filltext:name=link text:default=link text:width=32%](" & fURL & ")"

which would use a single-line TextExpander fill-in to get the link text. Unfortunately, TextExpander shows you the whole script while you’re doing the fill-in:

Fill-in in AppleScript

This works, but… blech. There’s a better way.

If you look through the popup menu that shows the TextExpander variables you can embed in a snippet, you’ll notice that all of your previously defined snippets are available, which means you can nest one snippet inside another. The best way to use a fill-in for the link text is this way:

Nested snippet for Markdown link

The content of this snippet is

[%filltext:name=link text:default=link text:width=32%](%snippet:;furl%)

where the thing in the parentheses is a call to my ;furl snippet.

When this is invoked, you see a much cleaner interface with the desired URL already in place:

Fill-in and nested snippet

Now we’re talkin’. No context shifting, no fiddling with the clipboard, and a clean fill-in interface. All you need to type is the abbreviation and the link text.

Maybe you don’t want to link to the current tab. No problem. Similar snippets can use the URLs of other tabs. I have snippets that will get the URLs of the first through the sixth tabs (counting left to right) of the frontmost Safari or Chrome window. Those could be nested just like ;furl:

[%filltext:name=link text:default=link text:width=32%](%snippet:;1url%)

What would be really nice is if these could be put into a popup menu, but TextExpander doesn’t allow that much magic yet.

I should mention that despite my love of script-driven snippets, David and Katie are exactly right when they say that TextExpander’s greatest value comes from simple, text-only snippets. There is so much repetition in business writing, especially correspondence, you’ll get your money’s worth from TextExpander even if you never exercise the AppleScript parts. (But you’ll have more fun if you do.)

]]> 0
Path Finder trial Sat, 12 Jul 2014 05:37:46 +0000 I’ve tried out Path Finder a half-dozen times over the years, but I’ve always gone back to the Finder, mainly because Cocoatech never seemed to be able to prevent the Finder from worming its way back onto my screen. I started another Path Finder trial at the beginning of this week, and I’m surprised to say that I’m still using it on both of my machines. This is longer than any attempt. But that doesn’t mean I’m completely sold on it.1

The most frustrating part of Path Finder is the behavior of its bottom drawer—a feature I both love and hate. I have it set to act as a terminal, which is the default behavior, and I’ve set up a keyboard shortcut, ⌃⌥⌘B, to toggle it. It’s nice to have instant access to shell commands in the directory I’m viewing.

PathFinder Terminal drawer

Which is the first problem: the terminal access isn’t quite instant. When the bottom drawer appears, focus is not switched from the file browser to the terminal. This is inexplicable. I open the drawer because I want to type a shell command right now, and I have to believe that’s the common use case. By not handling the focus correctly, Cocoatech is creating an inefficiency in a feature that should be all about efficiency.

The aesthetics of the drawer are weird, too. The bottom edge of the file browser casts a deep shadow on the drawer, as if the drawer were far behind the browser—even when the drawer has focus. Worse, the shadow falls on the top two or three lines of the drawer, reducing the contrast between the text and the background. If I wanted to read gray on gray, I’d visit Daring Fireball.

Path Finder also seems to think that what I’m doing in one window is what I want to do from now on. I’m used to certain Finder window characteristics, like the size and the sorting order, being “sticky,” but Path Finder takes that too far. If, for example, I have the drawer open on the current window, every subsequent window I create will start with the drawer open. I don’t understand why anyone would want that.

Today I ran into the worst example of Path Finder’s drawer/terminal behavior. A USB thumb drive was attached to my iMac and a Path Finder window was showing its root directory. I needed to run a couple of shell commands in that directory, so I opened the bottom drawer and typed them in.2 Some time later I closed the window and tried to eject the drive. No dice.

PathFinder fuckup

The instance of bash that was still using that directory was the one that had been running in the bottom drawer of the window I’d closed. It should have been killed by Path Finder when I closed the window, but because it wasn’t, I was stuck with an unejectable drive. I opened Activity Monitor and rummaged through the list of processes until I found the instance of bash that was causing the trouble. I had to Force Quit it to be able to eject the thumb drive.

After some experimenting tonight, I’ve learned that in some cases I can eject the thumb drive after opening a Path Finder terminal drawer in it. It depends, bizarrely enough, on whether I close the drawer before closing the window: if I close the window without closing the drawer first, I can eject the drive; but if I close the drawer first, I can’t. This is the kind of bug that should have been wrung out of a program before it gets to version 6.5.

So I’m torn. Path Finder has become quite good at fending off the Finder, but now that I’m able to use it for an extended period, I’m running into annoyances I’d never seen in my earlier, shorter tests. On the other hand, the Finder has plenty of annoyances and limitations that Path Finder doesn’t. I’ll probably give Path Finder another week of continuous use and then return to the Finder. If the Finder seems unusable to me, I’ll know that Path Finder has won me over.

  1. Strictly speaking, I am sold. I bought it as part of some bundle last year. But you know what I mean. 

  2. After changing the focus, of course. 

]]> 0
Evaluating LaTeX with Eddie and Alpha Fri, 11 Jul 2014 05:29:40 +0000 If you work in LaTeX and write numerical equations,1 this post by Eddie Smith will cause all sorts of bells to go off in your head. He shows how Wolfram Alpha will evaluate an expression given to it in LaTeX form. In other words, you can paste something like this into the Alpha expression field

\frac{\sin{\pi/4} + \sqrt{2}}{1.625^2}

and Alpha will calculate it for you.

Alpha evaluating LaTeX

Unfortunately, the Result is presented as an image rather than text,2 so you can’t just select and copy it, but you can click the “Copyable plaintext” link to have Alpha pop up a text field that you can copy the answer out of.

As Eddie says, the advantage of this is that you don’t have to keep track of two parallel sets of equations: one in LaTeX for typesetting and the other in your calculator for getting the answers. The opportunities for a typo to sneak in are greatly reduced.

Even better than copying and pasting LaTeX expressions into a web page is to use some form of automation to do it for you. Eddie shows a simple Alfred workflow that cuts out a few steps, but I don’t use Alfred. Because I do all of my LaTeX writing in BBEdit, I wanted a way to jump to the computed answer straight from there.

The key is to recognize that the URL of Alpha page looks like this

where everything after the ?i= is a URL-encoded version of the LaTeX expression you want to calculate. With that bit of information in hand, I wrote the following Python script to use as a BBEdit Text Filter:

 1:  #!/usr/bin/python
 3:  from urllib import quote_plus
 4:  from sys import stdin
 5:  from subprocess import call
 7:  latex =
 8:  alphaURL = "" % quote_plus(latex)
 9:  print latex + ' = '
10:  call(['open', alphaURL])

The URL encoding is handled by the quote_plus function of the urllib module, and the web page is opened in the default browser through the magic of Apple’s open command.

I called the script Alpha and saved it in BBEdit’s Text Filters folder. The Text‣Apply Text Filter submenu is kind of clumsy to negotiate, so I assigned it the keyboard shortcut ⌃=.

BBEdit keyboard shortcut for Text Filter

Now when I’m writing an equation, I can select it (which usually means hitting ⌘⇧← to select back to the beginning of the line) and type ⌃=. This puts an equals sign after the expression and opens Alpha in my browser. Within a second or two—and with no further work on my part—the expression is evaluated and waiting for me to copy and paste into my document.

I am, of course, not entirely satisfied with this solution. What I’d really like is to automate the copying and pasting of the answer. Wolfram’s page structure doesn’t make that easy, but it’s something I want to explore.

In the meantime, I have a new tool that will save me time and frustration. Thanks, Eddie!

Update 7/11/14
It’s nice to go to bed with an unfinished problem and wake up with solutions in your Twitter feed and inbox. The solution I found most appealing was Alex Chan’s. He used the Wolfram Alpha API to get an XML version of the Alpha output and extracted the plain text answer from that.

I can think of a couple of tweaks to Alex’s script that I’m going to try:

  1. Including the lines from my script that open the Alpha web page. Seeing the page will allow me to check that Alpha interpreted the LaTeX expression the way I expected.
  2. Passing a couple of extra query parameters to the API that will limit the mass of XML output to just the results I want. This isn’t strictly necessary, but I feel bad using bandwidth for results I discard.

Thanks, Alex!

Updated update 7/11/14
My tweak of Alex’s code can be found in this Gist. Turns out™ I had a Wolfram Alpha developer ID from some time ago but had completely forgotten about it. Your memory is the second thing to go.

  1. As opposed to symbolic. Lots of people do math with no numbers. 

  2. It’s an image because, in general, the result will be an equation or a graph or something else that isn’t normally expressed as plain text. 

]]> 0
The personal touch Thu, 10 Jul 2014 05:30:42 +0000 A couple of weeks ago, my old rant against stacked area charts got linked on Hacker News, resulting in a bunch of traffic and, somewhat surprisingly, generally favorable comments from the Hacker Newsies. I’m going to take this as evidence of my authority on data visualization—which we used to just call graphing—and inflict more of my opinions on you.

First, though, you should go read this wonderful post by Dr. Bunsen. The main topic is a pair of dynamic, interactive graphs he made from the split and final times of the top runners in the last five Boston Marathons. Each part of each graph is quite simple, but the way he combines the parts leads to a result that’s both dense in the data it presents and crystal clear in how it presents it. It’s a nice piece of work, and he gives you behind-the-scenes access to how it works through this GitHub repository.

Late in the post, Seth reveals the inspiration for his dynamic graphs: this chart by Henry Gannett from the 1890 Statistical Atlas of the United States.


It’s a timeline of state population ranking from census to census. You’ll get a better sense of how it works by looking at this detail from the right side of the chart.


Several things struck me about this graph:

  1. There’s no key or other explanation. Everything you need to know can be found by reading the title and looking at the chart.
  2. Gannett chose to run his time from right to left. I think he’s using our convention of reading from left to right to make us think of this as a stepwise look back through our past from today’s (1890) point of view.
  3. The lozenges Gannett uses for the states. He can’t just use color—the gradations would be too fine and printing costs would skyrocket—so he combines color and pattern to make each state distinct and easy to follow back to its first appearance in the census.
  4. The placement of the state labels is inconsistent, but purposely so. Most often, a state or territory’s first appearance is near the bottom of the ranking, so the name is off to the side of the lozenge. But in some instances—Kentucky and Vermont in 1800, for example—the state comes in near the middle and to putting its name off to the side would be messy. In those cases, the label goes in the lozenge.

It’s hard to imagine a chart made today looking like this because—in a graphical version of the Sapir-Whorf hypothesis—the software we use to make our charts directs and limits our design decisions. How often do you see timelines that run from right to left? Or patterns instead of color to distinguish items?1

And inconsistency, even inconsistency with a purpose, is antithetical to software-driven graphing. If you use graphing software a lot, or if there’s a graphing program or package that’s common in your business, I’ll bet you can instantly identify charts made with it because there is a sameness to them. That sameness isn’t necessarily a bad thing, but sometimes the conventions get in the way of communication. And there are ways to improve our graphs, to make them look less mechanical and to tell our stories more clearly.

The easiest way is to import a plot into a drawing program and add the sort of customization that used to be common back when graphs were done by hand. Tweak the positions and orientations of labels so they don’t interfere with each other or with the rest of the plot. Change the points of your scattergraph to a symbol that evokes the item that’s being plotted. Adjust the lengths of unlabeled tickmarks to make it easier to read the axis subdivisions (think of how rulers are marked). Tweak the widths of lines so the data are more prominent than the chrome around the edges of the plot. In general, think about what you wish you could do in your plotting program and do it “by hand” in a drawing program.

For years, I’ve been using OmniGraffle to enhance the graphs I put in my reports and presentations. It’s great for adding items like labels and arrows to a plot, but it’s limited in that a PDF you add to an OmniGraffle document comes in as a single monolithic object—you can draw on top of it, but you can’t change its internals. Recently I’ve been playing with iDraw, which is a little squirrelly but doesn’t have OmniGraffle’s limitation: when you import the PDF of a chart into iDraw, each object within the chart is individually selectable and editable. I can change, for example, the style of a line within the plot or grab an existing label and rotate it to match the slope of the trend line it’s captioning.

The harder way to make better graphs is to use a more powerful graphing program, preferably one that’s programmable or is a plotting package for a programming language you already know.2 This gives you more flexibility than a canned program like Excel or (God help you) Numbers in formatting the parts of your plot. It’s certainly harder to write a program that makes a plot than to just select a column of numbers and click a few options, but that time and effort is repaid when you need to make dozens of plots of the same type. Once that program is tweaked to output exactly what you want, you can apply it to dataset after dataset.

After many years of using Gnuplot, I switched to Matplotlib and have been very happy with the results. But I still do some tweaks “by hand” instead of in Matplotlib. If I know I’m only making one or two graphs and the tweaks I want to make are easy to do in iDraw, I’ll accept Matplotlib’s defaults and make the changes in iDraw. If, on the other hand, I know I’ll be making essentially the same plot over and over again, I’ll spend the time with the Matplotlib documentation to program in all the stylistic refinements so I can crank out plots with no effort later.

I confess that the plots I occasionally post here don’t get the attention suggested in the previous paragraphs. This might be because I know you’re all so smart you don’t that kind of hand holding. Or it might be because you don’t pay my bills.

  1. In the early days of the Mac, patterns were common because that’s all we had on our little black-and-white screens and Bill Atkinson’s QuickDraw gave programmers easy access to many fill patterns. But those patterns were pretty ugly, and because they were bitmapped, they didn’t translate well to the LaserWriter. 

  2. Or you could go super hardcore and program your plots from drawing primitives, which seems to be what Seth did in his Boston Marathon graphs. 

]]> 0
Displaying multiple images in Twitter Sat, 05 Jul 2014 19:46:54 +0000 The Tapbots crew beat me to it by a couple of days, but I did manage to update Dr. Twoot to handle Twitter’s new multiple image format. And I have to say I prefer my display of multiple images to both Tweetbot’s and Twitter’s.

This isn’t to say that Dr. Twoot is truly comparable to a full-featured Twitter client like Tweetbot, but the great advantage of making your own software is that you can customize it to match your own idiosyncrasies. Thus, Dr. Twoot

  • displays tweets in chronological rather than reverse chronological order;
  • uses background colors to distinguish tweets by me and replying to me from the general stream;
  • gives me one-click blocking and spam reporting;
  • shows the Twitter client used to write every tweet;
  • has a popup for displaying information about the tweeter;
  • has an edit (really delete-and-rewrite) button for fixing typos in tweets that have already been posted; and
  • shows the full frame of included images instead of cropped versions.

Tweetbot follows Twitter’s own convention of displaying only a portion of the attached image unless the aspect ratio of the image happens to match the roughly 9:5 frame Tweetbot uses. For most images Tweetbot crops off the top and bottom, which often leaves you wondering what’s really there. Dr. Twoot, on the other hand, shows the whole image. It’s resized to fit in the space, but it’s all there. No need to open it in another window just to see what you’re missing.

Tweetbot vs. Dr. Twoot single image

In this, Tweetbot follows Twitter’s lead. On the Twitter web page, you see only cropped images until you click on the Expand button or the image itself.

There’s a certain neatness to the Twitter/Tweetbot approach. An individual tweet will never get so tall as to take up the entire window. Still, I prefer to see the whole image right away and am willing to sacrifice vertical uniformity to get it.

Similarly, in the display of multiple images, I prefer to show them full frame and stack them one on top of the other, even if that means I have to scroll to see them all.

Tweetbot vs. Dr. Twoot multiple images

Again, there’s nothing wrong with what Tweetbot does—it’s a perfectly valid way to lay things out and is a clever way to pack more images into a single frame. I just have a different preference. And because I’m Dr. Twoot’s only user, my preference wins.

Update 7/5/14
Both paullu and Stephen Hackett pointed out on Twitter that I could change Tweetbot’s Image Thumbnail setting from Large to Small, which changes the aspect ratio from 9:5 to 1:1 and makes the cropping of most images—and portrait images in particular—less severe. That’s true, but it makes the images too small for comfort, especially on the non-Retina screens of my iMac and MacBook Air. I like my images the way I like my men: large and fully framed.

]]> 0
Extracting coordinates from Apple Maps Sat, 05 Jul 2014 13:50:18 +0000 A couple of years ago, I wrote a script called coordinate that inserted latitude and longitude into the metadata of photographs I took with my regular, non-GPS-equipped, camera. I set it up to work two ways:

  1. If I had a photo that already included GPS coordinates (one taken with an iPhone, for example), the script would extract that information and apply it to the non-GPS photos.
  2. If I didn’t have such a photo, I could provide the latitude and longitude on the command line.

At the time, the easiest way for me to get latitude and longitude (if I didn’t have an iPhone photo with it) was to go to Google Maps, find the spot where the photos were taken, and right click on it. Both the Drop LatLng Marker (enabled through Maps Labs) and the What’s Here context menu items will show the coordinates.

Google Maps context menu

The thing is, I’ve come to hate Google Maps. I know it has more and better information than Apple Maps, but its user interface has gotten worse over the years as Google has tried to squeeze more functionality into what is, when all is said and done, still just a web page. And I’m sick of having Google+ pushed at me.

So I’d prefer to get the coordinates from Apple Maps. Apple, of course, likes to hide such complicated technical information from its users, but there’s a way around the obfuscation. Here are the steps to get the latitude and longitude:

  1. Right click to drop a pin at the spot you’re interested in.
  2. Click the little info button on the pin’s flag.
  3. Click the share button on the info window that pops up and choose Messages from the context menu.
  4. Right click on the Map link in the message window and choose Copy Link from the context menu.

Dropped pin location in Apple Maps

You now have a URL on your clipboard that looks something like this:,-88.150383&sspn=0.002885,0.006427&sll=41.772891,-88.149888

The coordinates of the pin in lat,long form is the value of the q field in the query string.

Even if I could remember this series of steps flawlessly, it still doesn’t give me the raw coordinates of the point. I have to paste the URL somewhere and select the coordinates.

I’d like to write an AppleScript to extract the coordinates of the pin, but the AppleScript library for Maps is, for all practical purposes, empty, and UI scripting is never going to work with all the clicking that’s necessary.

Keyboard Maestro to the rescue. I put together a macro that does all of the above steps and pulls out just the pin coordinates from the URL. It solves the problem of where to click by allowing you to specify an image to aim at. Here, for example, is the step for clicking on the pin to show its flag:

KM click at center of pin image

By restricting the target image to just the inside portion of the pin, this works in Standard, Satellite, and Hybrid view—the clutter around the pin doesn’t screw up Keyboard Maestro’s “aim.”

The extraction of the coordinates from the URL is done through a simple shell pipeline at the end of the macro:

KM extract coordinates

The pipeline is

pbpaste | sed -E 's/^.+\?q=([0-9.,-]+).+/\1/'

which grabs the two comma-separated numbers after the q= and puts them on the clipboard. Passing the -E option to sed makes its regular expression syntax more like the Perl/Python syntax I’m used to. If it weren’t for that option, I’d find sed completely unusable.

If you’re interested in this macro, I put a zip file of it on my server. A few of the click actions are on popups that don’t appear instantly, so there are pauses at certain steps to insure the popups’ presence. You may need to adjust the lengths of these pauses to make the macro run smoothly on your system.

]]> 0
Afghanistan, June 2014 Fri, 04 Jul 2014 15:09:44 +0000 Most US military deaths in a year.

Afghanistan, June 2014

]]> 0