Here’s the latest stuff in Bunch 1.3.1!

This is all the result of a combination of new (better) ADHD meds (I refer you to the last couple episodes of Overtired) and the fact that the latest developer seed of Big Sur fixed the blurry PDF issue that I’ve been dedicating an inordinate amount of time to working around, so I suddenly have a little extra time in my day. Thank you Apple. For fixing what you broke, I mean. But still, I’m grateful.

(I’ll do an official announcement post on the Marked bug when this fix makes it into the stable release and is available to everyone.)

So what’s new with Bunch?

Do Not Disturb for Big Sur

First, I think I’ve come up with a solution for Do Not Disturb commands under Big Sur. This needs further testing but—to the best of my knowledge—Bunch doesn’t break anything in the process. It’s a more complicated trick than it was in earlier versions of the OS. It used to just be a boolean stored in the preferences. Now it’s a plist stored as data in a preference key and modifying it gently has proven difficult.

The end result is a kind of brute force hack that seems to be working. So now using (dnd on) or (dnd off) in your Bunch should once again function under Big Sur. Please let me know if you run into any issues.

I have to include a standard disclaimer here: I am not responsible for anything Bunch breaks on your system, or any damages suffered as a result1. I will work to fix anything wrong, though, serious or not.

Clear Single Checkmarks

If you have “Toggle Bunches” or “Single Bunch Mode” enabled under Preferences, Bunch adds a checkmark in the menu when you launch a Bunch. Clicking a checked item will then close the Bunch. Mostly for the sake of debugging Bunches, I have an option in the menu to Clear Checkmarks, allowing you to launch a Bunch again without quitting it.

I’ve expanded this to allow clearing a single checkmark by Option-clicking a checked Bunch in the menu.

AppleScript “Raw” Bunch Text

There’s a new AppleScript command for directly processing text as if it were read from a Bunch file. The command is process text "YOUR TEXT" and correlates to the raw URL method.

This can be used for sending simple commands or reading text in, modifying it, and then executing it.

Optional Snippets

I saved my favorite bit for last: a new feature I’m calling “optional snippets.” I wanted to add some interactivity to a Bunch so that I didn’t have to make two different bunches when only one part of it was different. I’ve started this process by allowing simple Yes/No choices when loading snippets. I may expand this at some point to allow more complex dialogs, but this approach fits well with the spirit of Bunch syntax2.

This does mean that if you want to make a single app or script optional, you have to create a snippet with a single item, but you can just add a fragment for that.

You just put a query at the end of a snippet import line, like so:

<MySnippet.snippet ?"Load My Snippet?"

When you open the Bunch, it will pop up a dialog that asks you “Load My Snippet?” (text defined by what’s in the quotes). If you click “Yes,” then the contents of the snippet load. If not, it’s skipped. This dialog will appear each time the Bunch is launched.

Focusing this feature on snippets allows a single dialog to affect a whole block of Bunch items without having to pollute the syntax with a whole logic system. You can simply make any part of the Bunch optional by extracting it into a snippet and adding a query.

There are cases where I’d like to be able to select from a list, but the complexity of adding syntax for that is a non-starter. There are options, though, as you’ll see in the “Alternative Interactivity” section of this post.

An Optional Snippet Example

Ok, so here’s an example Optional Snippet using a range of Bunch features.

I have a “Coding” bunch that launches the basics like Tower, Xcode, Sublime Text, and iTerm. Within that Bunch, I have an optional snippet for playing background music. Depending on my mood and state of mind, music is either going to be the best idea or the worst. So I’d like the option to go either way when switching to the Coding context.

In Coding.bunch

In Coding.bunch I have a line like this:

<useful.snippets#Coding Spotify ?"Play Coding Music?"

When I open this Bunch, it asks me “Play Coding Music?”. If I confirm, it executes the “Coding Spotify” fragment of my useful.snippets file.

In the Snippet

Here’s the Coding Spotify fragment of useful.snippets:

#[Coding Spotify]
& workflows/Play Spotify URL
- URL=spotify:playlist:3cSpIL4Q0H3uqdBMbT6c9x
- Autoplay=true
!* tell application "Spotify" to pause

The & line calls an Automator Workflow, and the !* runs an AppleScript command only when the Bunch closes.

The Workflow

Here’s the “Play Spotify URL” workflow:

Play Spotify URL Workflow

View image full size

The Workflow has variables set up for URL and Autoplay. URL is where I pass the Spotify URI for a playlist, and Autoplay can be set to false to prevent the music from starting immediately. (You’ll also note a Bunch variable, which is required for any Bunch workflow.)

The above snippet passes parameters to the URL (in this case the Spotify URI for my Coding Music playlist) and Autoplay variables (set to true because I’ve made the interactive choice to play music). Using variables in this way makes the workflow easily reusable and allows me to play different playlists for different Bunches.

Bonus, the script also does a nice fade in if Autoplay is true.

Here’s a copy of the Play Spotify URL Workflow if you just want to download it and play with it yourself.

The AppleScript

The last line of the snippet tells Bunch to run an AppleScript when closing the Bunch to pause Spotify. Alternatively, I could have Spotify launch and quit with the Bunch by just including Spotify on a line. If I’m in the mood for music, though, I probably want Spotify to stay open, but I still want that particular playlist to pause when I leave the Coding context.

Hope that makes sense.

Alternative Interactivity

It is, of course, feasible to have a Bunch call your own AppleScript with more complex dialogs, and have that script call other Bunches based on selections using AppleScript or the URL handler.

If you wanted to fork a Bunch to load another Bunch selected from a list, you could write an AppleScript like this:

set bunchChoices to {"Coding", "Comms", "Podcasting"}
    set theBunch to choose from list bunchChoices with prompt "Select a Bunch:" default items {"Comms"}

tell application "Bunch" to open bunch theBunch

Then call that AppleScript from the main Bunch using a * command. Or build the choices out to execute raw text, which happens to work with snippets and variables…

tell application "Bunch"
        process text "<useful.snippets#Spotify\n- url=spotify:playlist:37i9dQZF1E35F7NsH3aWbs"
    end tell

Enough for Now

That’s the Bunch news for now. See all the latest and download Bunch on the project page.

  1. Probably worst case: If something goes wrong, you might have to obliterate your notification preferences, which can lead to having to allow a bunch of apps to send notifications again. But that probably won’t happen.

  2. Which is to say “complicated enough that even I have to frequently reference the docs, yet still somehow elegant in its simplicity.”