Automation Documentation: Hooking Apple Shortcuts
01 Jun 2022Earlier this week I wrote about how I was using Hook and Obsidian to support my documentation of automations. In this post I will aim to explain how I am using this set up to help me access documentation for my Apple Shortcuts automations.
Shortcuts
Apple’s Shortcuts application came to the Mac in 2021 and provided Mac users with the latest functionality in native Apple automation. Shortcuts is a natural successor to Automator - or in effect, what Automator could easily have become if the investment had been there at the time. While statistically most shortcuts are probably less than a half-dozen actions, there are inevitably more complex ones. Some people build shortcuts with hundreds of actions. Personally I break my shortcuts down into smaller more reusable shortcuts - a typical developer approach; but this does mean that these multi-shortcut solutions are not as easily shared with others.
Regardless, the complexity of such Shortcuts solutions inevitably leads to a need to document in order to fully support its use and maintenance. As a result, like my other automations, I document some of my Apple Shortcuts automations in Obsidian, and my preference is to use the Hook application to support that.
Apple Shortcuts Integration Script
Hook allows me to create bidirectional links between resources to associate them. To do this it relies on access to unique identifiers, URL schemes and a way to programmatically reference these through Hook’s integration scripts.
Pro subscribers of Hook can create their own integration scripts that allow Hook to work with any app capable of supporting hyperlinking to a specific resource. While I have a pro subscription, and Shortcuts does support using URLs for open a shortcut for editing, Shortcuts is somewhat ironically not particularly scriptable.
After applying a little thought to the situation, I was able to put together an AppleScript that interacts with the Shortcuts application’s user interface, which then enabled me to allow an address to be generated by Hook for a particular shortcut. It utilises the system clipboard to grab the name of the shortcut and build the edit URL from that - so it is doubly important to ensure that your shortcuts are uniquely named. The script also makes use of some helpful scripted solutions from others, which have been included verbatim and include references back to their creators and websites.
The script is added via the script editor in Hook’s preferences. It should be added in the Get Address section as the script returns a Markdown link.
-- `menu_click`, by Jacob Rus, September 2006
-- Accepts a list of form: `{"Finder", "View", "Arrange By", "Date"}`
-- Execute the specified menu item. In this case, assuming the Finder
-- is the active application, arranging the frontmost folder by date.
on menu_click(mList)
local appName, topMenu, r
-- Validate our input
if mList's length < 3 then error "Menu list is not long enough"
-- Set these variables for clarity and brevity later on
set {appName, topMenu} to (items 1 through 2 of mList)
set r to (items 3 through (mList's length) of mList)
-- This overly-long line calls the menu_recurse function with
-- two arguments: r, and a reference to the top-level menu
tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬
(menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
end menu_click
on menu_click_recurse(mList, parentObject)
local f, r
-- `f` = first item, `r` = rest of items
set f to item 1 of mList
if mList's length > 1 then set r to (items 2 through (mList's length) of mList)
-- either actually click the menu item, or recurse again
tell application "System Events"
if mList's length is 1 then
click parentObject's menu item f
else
my menu_click_recurse(r, (parentObject's (menu item f)'s (menu f)))
end if
end tell
end menu_click_recurse
-- Encoding functions from macosxautomation.com
-- https://www.macosxautomation.com/applescript/sbrt/sbrt-08.html
on encode_char(this_char)
set the ASCII_num to (the ASCII number this_char)
set the hex_list to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
set x to item ((ASCII_num div 16) + 1) of the hex_list
set y to item ((ASCII_num mod 16) + 1) of the hex_list
return ("%" & x & y) as string
end encode_char
on encode_text(this_text, encode_URL_A, encode_URL_B)
set the standard_characters to "abcdefghijklmnopqrstuvwxyz0123456789"
set the URL_A_chars to "$+!'/?;&@=#%><{}[]\"~`^\\|*"
set the URL_B_chars to ".-_:"
set the acceptable_characters to the standard_characters
if encode_URL_A is false then set the acceptable_characters to the acceptable_characters & the URL_A_chars
if encode_URL_B is false then set the acceptable_characters to the acceptable_characters & the URL_B_chars
set the encoded_text to ""
repeat with this_char in this_text
if this_char is in the acceptable_characters then
set the encoded_text to (the encoded_text & this_char)
else
set the encoded_text to (the encoded_text & encode_char(this_char)) as string
end if
end repeat
return the encoded_text
end encode_text
-- Now the scripting that uses those functions to return a Markdown link to Hook
tell application "Shortcuts" to activate
menu_click({"Shortcuts", "File", "Rename…"})
delay 0.2
tell application "System Events"
keystroke "c" using command down
delay 0.2
keystroke return
delay 0.2
end tell
return "[Shortcuts Action - " & (the clipboard as text) & "](" & ¬
"shortcuts://open-shortcut?name=" & encode_text((the clipboard as text), true, true) & ")"
Once in place, this will allow you to generate an edit shortcut link when you are editing a shortcut in Apple Shortcuts. This then allows Hook to do its association “magic”.
Summary
Being able to bidirectionally link to a note in Obsidian to create documentation for my shortcuts is very useful to me. As you might have guessed from the details above, I do not feel the need to document every single Shortcut, but through use, I have found I am documenting some of the simpler shortcuts as well as the more complex ones. This is because it then gives me a more capable way of identifying shortcuts than just by the name of the shortcut.
Much like being able to cross-reference subroutines in Keyboard Maestro, for multi-part solutions where one shortcut calls another, it makes it really easy for me to link up to the documentation of those other shortcuts. I can even put together a quick Mermaid diagram in Obsidian to show me those more complex flows.