42 Astounding Scripts

MacOS uses Perl, Python, AppleScript, and Automator and you can write scripts in all of these. Build a talking alarm. Roll dice. Preflight your social media comments. Play music and create ASCII art. Get your retro on and bring your Macintosh into the world of tomorrow with 42 Astoundingly Useful Scripts and Automations for the Macintosh!

Jerry Stratton

The best book on programming for the layman is “Alice in Wonderland”; but that’s because it’s the best book on anything for the layman. — Alan J. Perlis (Epigrams on Programming)

Safari 14 disables Automator Quick Actions in text fields—Saturday, September 26th, 2020
Bug Alert

There appears to be a bug in Safari 14, released for macOS Catalina on September 17, that makes Automator Quick Actions fail. This was extremely annoying. In the morning, I was able to write in markdown on blog comments, and in the afternoon I was not.

What happens is that, if you select text in a text field in Safari and choose to run a Quick Action from the Services menu, the Quick Action runs—if it does anything outside of Safari, you’ll see those actions happen—but it replaces the text with nothing rather than with the output of the service.

You can undo to get your raw text back.

This will affect any of the simple BBCode and HTML verification/conversion scripts in 42 Astounding Scripts that are meant to be run in forum posts or blog comments.

I’m writing this in Brave, so as to be able to use markdown while writing this post. I’ve verified that Google Chrome also still works with Quick Actions. Another option would be to write it in a text editor, run the conversion, and then copy and paste it into Safari.

I’ve also used pbpaste and pbcopy as a stopgap, since most of my Quick Actions are command-line scripts.

  • pbpaste | moronify | pbcopy

will take whatever text I just copied, run it through the “moronify” script, and then copy it to the clipboard so that I can manually paste it back into the text field it came from.

You can test that Quick Actions are half-working in Safari with a simple two-step “Hello, World” Quick Action. In Automator, create a new Quick Action. Make the first step a “Run Shell Script” that pipes the selected text to a text file on the Desktop.

  • cat >> ~/Desktop/test\ services.txt

Make the second step a “Get Specified Text” that produces the text “HELLO WORLD”.

Hello World Service

A simple Quick Action in Automator to test Services in Safari.

Save it as “Hello, World”.

In any text editor or word processor, or an editable text field in any web browser other than Safari, selecting some text and running Hello, World from the Services menu will (a) write the selected text to the test file on the Desktop, and then (b) replace the selected text with “HELLO WORLD”. In Safari, it will write the text, but it will replace the selection with nothing.

Check42 for verifying Astounding Scripts—Friday, September 18th, 2020
Check42 example run

As I wrote in the intro to 42 Astoundingly Useful Scripts and Automations for the Macintosh, there are two ways to get a script from the book to your computer. You can copy and paste it from the ebook. Or, you can go the traditional route and type it. It was old-school books with the latter sensibility that inspired me to write 42 Astounding Scripts, but I recognized that there were serious issues with that model, mainly to do with catching typos.

The best old-school computer magazine I read back in the day was The Rainbow for the TRS-80 Color Computer. Content-wise, it was very much like 80-Micro, which was the second-best: filled with amazingly cool BASIC programs, tutorials, and hardware projects. But unlike every other computer magazine that included BASIC code, The Rainbow had a program called rcheck and later, rcheck+.

Typos were inevitable typing in even short programs; the rcheck programs were designed to tell you not only that you had a typo but where the typo was, within a defined block of BASIC lines.

The rcheck+ program was so useful I’ve rewritten it in Perl, partly for the old-school community but mainly for myself.

It’s much more difficult to write something like that for modern scripting languages. BASIC had line numbers, which meant there were no blank lines. BASIC didn’t have indentation, which meant there was no worry about tabs vs. spaces. It didn’t even have tab characters in the code, at least on the Color Computer. And because memory was so tight, there weren’t very many spaces, either. There wasn’t even upper and lower case for the most part.

Still, I very seriously considered including a program like rcheck in 42 Astounding Scripts. Ultimately, I decided that it was likely to cause more problems than it solved. But last week I had the epiphany that an rcheck-style script could provide a literal line-by-line checksum, in fact a series of checksums that separate indentation from code, and that I could provide a zip file of those checksums.

Thus was check42 (Zip file, 107.4 KB) born. This script takes a script name as an argument and checks each line of that script against a corresponding line in a checksum file. It looks at (a) the level of indentation, (b) the number of characters in that line of code, (c) the sum of the ASCII values of those characters, and (d) an md5 hash of those characters.

Catalina vs. Mojave for Scripters—Wednesday, September 16th, 2020
Swift conditional at end

As the author of a book filled with scripts for the Macintosh, I was worried about the differences between scripting for Mojave and scripting for Catalina. When testing the Catalina update of the book, it turned out there wasn’t much difference. For the most part, what worked in Mojave worked in Catalina.

The most obvious changes, of course, were those having to do with iTunes. Catalina broke the iTunes app into several apps. The new app for music is called Music. This means that AppleScript scripts need to change from:

  • tell application "iTunes"

to

  • tell application "Music"

The application id has also changed, from “com.apple.iTunes” to “com.apple.Music”.

The application id is useful if, for example, you want to do some stuff if the Music app is running, but skip out if the Music app is not running. The normal means of talking to an application in AppleScript will start the application up, which means it can’t be used to check whether the application is running: it always will be, after using “tell” on it. The application id can check the status of the app without opening the app:

[toggle code]

  • property iTunes : "com.apple.Music"
  • if application id iTunes is running then
    • display dialog "Music is running"
  • end if

The other new iTunes successor apps—Podcasts and TV—don’t seem to be scriptable via AppleScript.

NSSound.currentTime

Within other scripting languages, there’ve been more interesting, if obscure, changes. In 42 Astounding Scripts I have a Swift script for playing alert sounds.

[toggle code]

  • //wait until the sound is done before going on
  • while sound.currentTime < sound.duration {
    • usleep(100000)
  • }

Waiting is necessary because if the script exits before the sound is finished, the sound will stop. The obvious method of checking if the sound is still playing—NSSound.isPlaying—doesn’t work for alert sounds as it does for audio files. It remains true until calling NSSound.stop(), which makes it useless for deciding when to call NSSound.stop().

Play music faster in the Music App—Friday, September 11th, 2020
Photos Scripts menu

Every app on macOS has a Scripts Folder, and you can open it from the scroll-iconed Scripts Menu in the menu bar.

When I updated 42 Astoundingly Useful Scripts and Automations for the Macintosh for Catalina, I removed this script. Its purpose was to speed podcast playback, and the Podcast app, in Catalina, has that ability built in. That made this script less useful and less astounding, so I removed it and replaced it with a backmasking script, that is, one that plays music backward to reveal hidden messages.

But I promised to make the speed playback script available, and here it is. You may find it useful if you’re still on Mojave or earlier, for example, and are still listening to podcasts through iTunes. Or you may just find it enjoyable to turn your favorite music into Alvin and the Chipmunks.

I’m not judging.

Much.

This is a very simple script. It takes the currently-playing (or currently-paused) track in iTunes, gets both the file location and the current play position, and then opens the track in QuickTime Player to start playback from that position at the higher speed. I have it set to play back 60% faster (1.6x). Change the preferredSpeed property at the top of the script if you prefer a different speed.

AppleScript Editor: Enable Script Menu

To enable the Scripts Menu, you’ll need to check the appropriate boxes in AppleScript Editor’s preferences.

Paste this code into AppleScript Editor and save it as “Speed Playback” in your iTunes Scripts Folder. It will appear in iTunes under the scroll-iconed script menu in the menu bar.

Here are the important variables in the scripts:

alreadyPlayedHow much of the track we’ve already listened to in iTunes.
preferredSpeedThe multiplier to playback speed.
trackLocationThe filepath to the track.

And here is the script code:

Older posts