A deliberately inefficient automation
July 31, 2024 at 2:31 PM by Dr. Drang
I automate computer tasks for one of four reasons:
- Speed. This is the obvious one, the reason everybody thinks of as the main reason for automation.
- Accuracy. When I have to do a series of steps over and over again, my mind tends to wander, and I make mistakes. A well-written script or macro prevents those kinds of errors.
- Focus. When I’m writing, I like to keep my mind on what I’m trying to say, not on formatting or other side issues. Using Markdown helps for this, but so does using scripts and Typinator (or TextExpander) snippets for certain boilerplate text.
- Learning. Sometimes I take far more time to create an automation than I will ever get back. I do it anyway because I want to learn an automation technique that might come in handy later. Or I just want to learn it because learning is fun.
I recently had a close encounter with an automation of the fourth kind.
In the latest episode of the Sophomore Lit podcast, John McCoy and Jelani Sims covered A Canticle for Leibowitz, the post-apocalyptic science fiction novel by Walter M. Miller, Jr. During the episode, they mentioned a National Public Radio dramatization of the book, and I told myself I should go find that and listen to it. Of course, I immediately forgot, but luckily Kieran Healy had me covered. He posted a link to the dramatization on Mastodon, and this time I didn’t forget to download the files.
The dramatization was presented over 15 episodes, each about half an hour long. When I downloaded the MP3s, they had the unhelpful file names 01.mp3
, 02.mp3
, and so on up through 15.mp3
. I used the Finder’s command to change their names to the more useful Canticle-01.mp3
through Canticle-15.mp3
. Then I sideloaded them into Castro and listened to them as a podcast.
But I found a problem. A Canticle for Leibowitz is organized into three sections that are separated by several centuries. The ID3 tags of the MP3 files use these sections in the track titles, and Castro uses the track titles as the names of sideloaded episodes. Here’s the organization:
File name | Track title |
---|---|
Canticle-01.mp3 | 500 Years After, part 1 |
Canticle-02.mp3 | 500 Years After, part 2 |
Canticle-03.mp3 | 500 Years After, part 3 |
Canticle-04.mp3 | 500 Years After, part 4 |
Canticle-05.mp3 | 1100 Years After, part 1 |
Canticle-06.mp3 | 1100 Years After, part 2 |
Canticle-07.mp3 | 1100 Years After, part 3 |
Canticle-08.mp3 | 1100 Years After, part 4 |
Canticle-09.mp3 | 1100 Years After, part 5 |
Canticle-10.mp3 | 1100 Years After, part 6 |
Canticle-11.mp3 | 1100 Years After, part 7 |
Canticle-12.mp3 | 1800 Years After, part 1 |
Canticle-13.mp3 | 1800 Years After, part 2 |
Canticle-14.mp3 | 1800 Years After, part 3 |
Canticle-15.mp3 | 1800 Years After, part 4 |
Unfortunately, the track titles of seven of these files are incorrect. Canticle-05.mp3
is Part 5 of the “500 Years After” section, not Part 1 of the “1100 Years After” section. And the following six files are off by one in their part numbers.
So I wanted to fix the names.1 I have the Python Mutagen module installed on my Mac, and it comes with a command-line tool, mid3v2
, that lets you view, set, and delete ID3 tags. Fixing Canticle-05.mp3
was easy
mid3v2 -t "500 Years After, part 5" Canticle-05.mp3
I could, of course, repeat this command with minor edits to change the track titles of Canticle-06.mp3
through Canticle-11.mp3
, but where’s the fun in that? No, I wanted to do it all at once with a single shell command.
After quite a while, I came up with a solution that used looping, brace expansion, and arithmetic expansion. Here it is, spread out over three lines:
for n in {1..6}; do
printf "mid3v2 -t \"1100 Years After, part %d\" Canticle-%02d.mp3\n" $n $((n+5))
done
The key is the placeholders %d
and %02d
in the second line. The printf
command replaces them with $n
and $((n+5))
each time through the loop, so the result is
mid3v2 -t "1100 Years After, part 1" Canticle-06.mp3
mid3v2 -t "1100 Years After, part 2" Canticle-07.mp3
mid3v2 -t "1100 Years After, part 3" Canticle-08.mp3
mid3v2 -t "1100 Years After, part 4" Canticle-09.mp3
mid3v2 -t "1100 Years After, part 5" Canticle-10.mp3
mid3v2 -t "1100 Years After, part 6" Canticle-11.mp3
which are the six commands needed to change the track titles of those files. Once I saw that these were correct, I could run them all by piping this output to bash
:2
for n in {1..6}; do
printf "mid3v2 -t \"1100 Years After, part %d\" Canticle-%02d.mp3\n" $n $((n+5))
done | bash
Thus concludes the retitling.
Given that’s it’s unlikely that I’ll listen to A Canticle for Leibowitz again, you might consider this even more a waste of time than I originally suggested. Not only did I spend more time figuring out how to change the ID3 tags in a single command than I would have just writing out six commands, I made the changes on files that I’ll never use again.
But I did learn some shell scripting techniques, and I got the satisfaction of solving a problem in a language I’ve never been comfortable with.
-
We won’t get into another problem I have with the names, which is that I think the time peroids should be 600, 1200, and 1800 years after the Flame Deluge. Or that the parts should have the names “Fiat Homo,” “Fiat Lux,” and “Fiat Voluntas Tua,” as they do in the book. ↩
-
I should mention here that I’m using version 5.2.26 of
bash
, installed via Homebrew, not the old version that comes with macOS. Some of the features used in this command may not work with oldbash
. I could have piped the output tozsh
and it would have worked (I just checked), but I’m just not in the habit of usingzsh
. ↩
Tot shopping
July 29, 2024 at 9:13 AM by Dr. Drang
I’m finding Tot to be a really good app for shopping lists. It has checklists for items, bold formatting to separate the lists for different stores (I often go to more than one store on a shopping trip), and its seven-note limitation encourages the reuse of notes for ephemeral stuff. Most recently, I learned that its Markdown support and Shortcuts actions provide a simple way to wipe out a used list and replace it with a template for a new one.
I keep my shopping list in Tot’s first dot, where it looks like this:
(For those of you from the Midwest, the Casey’s in this list is not the gas station/convenience store you’re used to seeing along state highways. It’s a local grocery store within walking and biking distance of my house.)
Tapping an item as I put it in my cart fills the open rectangle. When I’m done shopping, I want the list to be replaced by this empty template:
Putting the open squares in below the store names saves me a little time when making the next list. I tap next to a square to add the first item to a new list, and when I type Return, a new line appears with an open square already in place for the next item.1
The template is made by a simple Shortcut called download it or build it yourself. Here are the steps with a short description of what they do:
. You canStep | Action | Comment |
---|---|---|
1 | Get the current text of Dot 1. | |
2 | Show the current text of Dot 1 in an alert that asks if the user wants to reset it. If the user taps the Cancel button, the Shortcut is aborted. This protects against accidentally resetting a list that’s partially written. | |
3 | The template for a new list. Markdown is used to make the store names bold. | |
4 | Replace the current contents of Dot 1 with the template. |
Steps 3 and 4 are executed only if the user agrees to reset the list. The template in Step 3 is this:
**Trader Joe’s**
□
**Casey’s**
□
**Costco**
□
**Target**
□
Here’s where we see the value of Tot’s limited implementation of Markdown. The double asterisks will make the store names bold, but because we’re not using full Markdown, the blank lines are preserved—they aren’t reduced to a single blank space as they would be if Tot were converting the text to HTML and rendering that.
appears in a Shortcuts widget on my home screen.
When I tap the button, I get an alert that lets me either proceed with the reset or cancel it.
I often forget that I’ve already started a new list, so this extra step gives me a chance to avoid wiping out a partially written list.
Tot may not be the right app for your shopping lists. In particular, if you want to build a list cooperatively with someone else in your household, you’ll find Apple Notes better because it allows notes to be shared. But Tot’s features are just right for me.
-
I’m not suggesting Tot is special in automatically adding new items to a list—most text editors will do this. I just want you to know that Tot does it, too. ↩
Obscuring my location more than necessary
July 24, 2024 at 3:06 PM by Dr. Drang
In yesterday’s post, I obscured my location by covering up the latitude and longitude after the decimal point.
How good is this? How big is the area that could be covered by these truncated coordinates?
Well, you could cheat by using, say, ArcGIS to create a map of the Chicago area bounded by lines of latitude (parallels) at 41°N and 42°N and lines of longitude (meridians) at 88°W and 89°W. Like this:
That’s obviously a pretty big area, and ArcGIS has measuring tools so you can get the lengths of the parallels and meridians. But you don’t need all this fancy stuff; you can get an estimate much more quickly with some simple calculations in your head or on a calculator.
The primary thing to know is that a nautical mile was originally defined as the distance on the Earth’s surface along one minute of arc. One degree is sixty minutes, so a very quick (and rough) estimate of the area would be a square that’s 60 miles on each side.
For some purposes—like my desire to obscure my location—this estimate is good enough. I’ve never made a secret of the fact that I live in Naperville, so I’ve already given up a more precise indication of my location than a 60-mile by 60-mile square, even if those two 60s are way off.
But if you need a significantly better estimate, you can calculate one with just a little more effort. The two biggest sources of error in the calculation above are:
- Nautical miles aren’t statute miles, they’re about 15% longer.
- Meridians converge as you get further from the equator. The convergence goes with the cosine of the latitude.
So our 1° long meridian is about 69 miles long. That takes care of the north-south distance. To get a better estimate of the east-west distance, we can multiply that 69 miles by the cosine of the average latitude,
to get 51.7 miles. This is why a 1° by 1° “square” looks more like a rectangle on a map.
I first thought I’d leave the first decimal place visible in the latitude and longitude figures. That would give me a rectangle of uncertainty of about 5 by 7 miles—good enough for my purpose. But as I was drawing the little checkerboard areas on the Tot screenshot, I found it much easier to use the decimal points as the left edges.
Tot Notes
July 23, 2024 at 5:50 PM by Dr. Drang
Against my better judgment, I decided to write a Shortcut today. Even worse, I wanted it to be able to run on my Apple Watch. After several iterations, all of which looked to me to be functionally identical, I finally hit upon one that worked.
The goal was to have a complication on my watch that I could tap, dictate a short note to, and have the note saved to Tot with time and location stamps. Like this (but without the checkerboards to obscure my location):
The complication that runs the Shortcut is at the bottom center of the Modular face, which is the one I normally use. This makes it handy for whatever ideas or observations I want to record when I’m out hiking or kayaking.
I can, of course, run it from my phone, too, but the main point of writing this Shortcut was to have a quick way of making notes like this when the phone isn’t handy.
You can download the Tot Notes Shortcut from its iCloud link. Here’s an annotated view of all the steps:
Step | Action | Comment |
---|---|---|
1 | Ask the user to dictate some text. This will be the note. | |
2 | Get today’s date and time. | |
3 | Format the date and time as yyyy-mm-dd HH:MM:SS. | |
4 | Get the current location. | |
5 | Get the latitude of the current location. | |
6 | Truncate the latitude to 6 decimal places. | |
7 | Get the longitude of the current location. | |
8 | Truncate the longitude to 6 decimal places. | |
9 | Put the date, time, latitude, longitude, and note into a paragraph with a trailing newline. | |
10 | Add the paragraph to the end of Tot dot #7. |
As I said at the top, this is what I came to after quite a lot of backing-and-forthing with code that should have worked exactly like this version. Every earlier version did work when run from my phone; it was only this version that finally worked when run from the watch. That’s Shortcuts for you.
You may be wondering why I’m using Tot instead of Drafts. First, I bought Tot when it was on sale a few weeks ago, so it’s at the top of my mind right now. Second, while it’s nice that Drafts isn’t limited to just seven documents, I was worried that my notes would get lost in its infinitude. Tot’s limitations impose (I hope) a discipline that will have me going through my dictated notes and clearing them out frequently.