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

Good structure in a program can bring as much esthetic satisfaction as good structure in a painting. — Duane M. Palyka (Computer Painting)

Regenerate multiple files—Wednesday, October 6th, 2021
Bit pipes

This is sort of a minor codicil to a handful of much more interesting posts about automating the generation of Daredevils RPG character sheets over on the Biblyon Broadsheet.

At a role-playing game convention recently, I had a whole bunch of pregenerated characters, and regularly needed to recreate their character sheets from source files after making changes to either the characters or to how I interpreted the character generation rules. I used a Daredevils pregen calculator to do this. But while the calculator could take multiple inputs and produce a single file with every character in it, I ended up choosing to have a separate output file for each character. It was easier to find any particular character that way.

This meant having to rerun the script for multiple characters every time I made changes. That’s obviously a target for automation. What I needed was a script to check each source file against its generated character sheet—and against the ever-changing daredevils script—and run the script on that source file if it’s newer than the sheet or if the destination is older than the script that generated it.

The “file” command could probably handle this for me. But it is an arcane command which is not amenable to obviousness. It produces long command lines with obscure switches that require, for me at least, reading through the man page every time I need to alter it. I need more obviousness in my automations.1

So I wrote a script that takes files on the command line, a directory for the output files, and a script to run on each file.

The basic requirements are:

  1. a bunch of input files, such as my character stats files for Daredevils;
  2. the same number of output files in a separate but common directory, with the same name (sans any extension) and the extension “.txt”;2
  3. a script that runs on the input files and produces text to standard output; the standard output for an input file is piped to the corresponding output .txt file.

The script checks whether the input file is younger than the output file before running or if the output file is older than the script. In the former case, the data has changed and the output needs to be recreated. In the latter case, the logic has changed, and the output needs to be recreated.

I haven’t needed a --force option yet, but it’s an obvious potential add.

Caption this! Add captions to image files—Wednesday, September 22nd, 2021
Let them eat cake

One of the coolest scripts in 42 Astoundingly Useful Scripts and Automations for the Macintosh takes an image and creates ASCII art from the image. The ability to easily manipulate images at high quality is one of the great features of scripting on macOS. Even when the purpose is to produce a low-quality, retro image, as that script does.

Many of the image manipulation tasks I do, I do almost but not quite the same thing every time; it’s mind-numbingly dull in a GUI app such as GIMP or Inkscape to add a caption, for example, to the bottom or top of an image.

It’s fascinating turned into a script.

That I find things more fascinating when I can manipulate them on the command line than I do playing around with a mouse and menus may be one of the tells that make a weekend scripter. That’s a topic for another day. Today’s script, caption (Zip file, 5.5 KB), takes an image and adds a caption to it. It attempts useful defaults for everything it can, and provides command line switches for those defaults that are either difficult (or dangerous) for a computer to guess or that might need to occasionally deviate from the most likely guess.

I wrote it in Swift because that’s the easiest way to access the image manipulation libraries built in to macOS. The script can add a caption above or below (the default) an image, or layer it over an image. It can add borders, and it can resize the image proportionally, outputting it as PDF, JPG, PNG, or TIFF.

Suppose I want to put the Gettysburg Address as a caption below a photo of the Lincoln Memorial.

[toggle code]

  • caption Lincoln.jpg --output Gettysburg.jpg  < address.txt

The original image is “Lincoln.jpg”. The new file will be named “Gettysburg.jpg”. And it will get its text from the file “address.txt”.

Because this is long text, the script will justify it instead of centering it.

The Gettysburg Address

The origin of this script came when I wanted to caption a photo of the last slice of pie as a joke art piece.1

  • caption pie.JPG --output "Last Slice of Pie.jpg" --align right < pie.txt
Using version control with AppleScripts—Wednesday, July 21st, 2021
Save Clipboard changes in Mercurial

Tracking an AppleScript in Mercurial.

In 42 Astoundingly Useful Scripts and Automations for the Macintosh I devoted one diversion to the importance of version control. One thing I left unmentioned except through omission is that AppleScripts created with Script Editor (as most will be, due to Script Editor’s verification and testing ability) can’t really be tracked in version control. They aren’t text files, so while changes will be noted, what those changes are will not. Change tracking pretty much requires line-oriented text files, and Script Editor files are not text files, at least in any sense meaningful to Mercurial or Git.

I have a lot of AppleScripts in my User Scripts folder for several applications, as well as a handful of AppleScripts in my Finder window toolbars and my Favorites folder. I’ve always been disappointed that I can’t track changes to them in Mercurial. And I’ve always been worried that I don’t have a backup of them in easily-readable text format.

While working on this problem, I noticed that I have a lot of scripts I’ll never read again because the format is no longer valid on macOS.

I’ve considered, and occasionally tried, keeping two copies of every script I write: when I’m done editing a script in Script Editor, copy the text to a text file and save that as a readable, future-proofed version. It always works for a very short period and then I forget, and the two sets of scripts get out of sync. As I was writing this post, I discovered an abandoned .hg folder in my user scripts folder, last touched on September 20, 2014.

It occurred to me while writing the Save Clipboard script that there are so many commands beginning with osa there must be one for getting the text of an AppleScript out of a .scpt file or .app folder.1 And to ask the question is to answer it: osadecompile does exactly that. This makes it trivial to write a script that keeps the two locations—the live location and the text repository—in sync. The text backup can then be tracked easily in any version control system, including Mercurial.

Why should everyone learn to program?—Wednesday, July 14th, 2021
Adapting to computers

Programming for all” is a catch-all term I use for anything about programming that I think is relevant to anyone using a computer. Mostly, I use it for simple scripts such as those in 42 Astoundingly Useful Scripts and Automations for the Macintosh. But there’s a deeper meaning more appropriate to modern life, which is that everyone uses a computer almost nonstop, even if you don’t own a desktop computer, a tablet, or a smart phone. Every time you interact with the larger world, there’s a computer involved. It’s how you get billed, it’s how you leave messages for people, it’s how the lights at the intersection work and how the votes get counted on election day.

If your refrigerator has a water filter, it uses a computer to tell you when it wants you to replace the filter, your car almost certainly has a computer that controls whether your airbag will deploy in an accident, and your washing machine likely has a computer that determines whether you’re allowed to open the lid.

Every time you find out you missed an important post in some social media platform you use, it’s because a computer algorithm did not display it in your feed—and that’s because a programmer decided on that algorithm. Every time you’re asked to reduce your electricity usage, or are forced to endure rolling blackouts, it is because decades ago some programmers used a computer model to argue that unless we switched from reliable, stored energy sources to unreliable, intermittent sources, catastrophic weather changes would ensue.

Computer programming and computer models affect every aspect of our lives, personally and politically. They can even shut down a thriving economy for a year. Understanding the nature of programming is essential to modern life.

When I first got into computers in the late seventies, there was an assumption in the books and magazines I read that schools would soon be required to teach everyone programming. From Larry Gonick’s warning1 that “In the computer age, everyone will be required by law to memorize the powers of two, up to 210” to Peter Laurie’s prediction2 that secretaries would evolve into mini-programmers, writing “small programs in Pascal or BASIC” on the server to manage the office, the assumption was that well into the future if you wanted to use a computer you’d have to write your own software.

Older posts