Skip to content

Instantly share code, notes, and snippets.

@loshlee
Last active March 22, 2024 02:40
Show Gist options
  • Save loshlee/ccdf495009575d1f4d97c1756805f40d to your computer and use it in GitHub Desktop.
Save loshlee/ccdf495009575d1f4d97c1756805f40d to your computer and use it in GitHub Desktop.
This lets you set up a pattern for arranging desktop icons, then generates an AppleScript for arranging desktop icons in that pattern.
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use script "PrefsStorageLib" version "1.1.0"
set customLocation to ""
try
set pashuaLocation to getPashuaPath(customLocation)
set dialogConfiguration to my getDialogConfiguration(pashuaLocation)
set theResult to showDialog(dialogConfiguration, customLocation)
if {} = theResult then
display alert "Empty return value" message "It looks like Pashua had some problems using the window configuration." as warning
else if cb of theResult is not "1" then
assign value iconcol_count of theResult to key "iconcol_count"
assign value firsticon_dist of theResult to key "firsticon_dist"
assign value newcol_dist of theResult to key "newcol_dist"
assign value const of theResult to key "const"
assign value disksort of theResult to key "disksort"
assign value nondisksort of theResult to key "nondisksort"
assign value chk_default of theResult to key "chk_default"
assign value chk1_default of theResult to key "chk1_default"
assign value chkLeft_default of theResult to key "chkLeft_default"
assign value clipsave of theResult to key "clipsave"
tell application "System Events"
tell process "Finder"
set screensize to size of first scroll area where its position is {0, 0}
end tell
end tell
set {_width, _height} to screensize
set iconcol_count to ((value for key "iconcol_count") as integer)
set firsticon_dist to ((value for key "firsticon_dist") as integer)
set newcol_dist to ((value for key "newcol_dist") as integer)
set const to ((value for key "const") as integer)
set disksort to value for key "disksort"
set nondisksort to value for key "nondisksort"
set chk_default to value for key "chk_default" --as text
set chk1_default to value for key "chk1_default" --as text
set chkLeft_default to value for key "chkLeft_default" --as text
set clipsave to value for key "clipsave"
set firstcol_calc to 0.5 * newcol_dist
set firstcol_dist to (round firstcol_calc rounding up)
set iconcol_calc to ((_height - firstcol_dist) / iconcol_count)
set iconcol_dist to iconcol_calc as integer
set heightdistance to (_height - iconcol_dist as integer)
if chkLeft_default is "1" then
set col1 to firstcol_dist
else
set col1 to _width - firstcol_dist
end if
set a to col1
set b to firsticon_dist
tell application "Finder"
set itemlist to (every item of desktop) where its class is not disk
set desktoplist to reverse of itemlist
set startvollist to startup disk as list
set startvolname to (startup disk as text)
set disklist to ((every item of desktop) where its class is disk)
set otherdisklist to {}
repeat with i from 1 to count disklist
set thestring to get disklist's item i as text
if thestring is not startvolname then set otherdisklist to (otherdisklist & {item i of disklist})
end repeat
if disksort is in {"Name"} then
set otherdisklist to sort otherdisklist by name
else if disksort is in {"Modification Date"} then
set otherdisklist to sort otherdisklist by modification date
else if disksort is in {"Creation Date"} then
set otherdisklist to sort otherdisklist by creation date
else if disksort is in {"Kind"} then
set otherdisklist to sort otherdisklist by kind
end if
if chk_default is "1" then
set otherdisklist to reverse of otherdisklist
end if
if nondisksort is in {"Name"} then
set desktoplist to sort itemlist by name
else if nondisksort is in {"Modification Date"} then
set desktoplist to sort itemlist by modification date
else if nondisksort is in {"Creation Date"} then
set desktoplist to sort itemlist by creation date
else if nondisksort is in {"Kind"} then
set desktoplist to sort itemlist by kind
end if
if chk1_default is "1" then
set desktoplist to reverse of desktoplist
end if
set disklist to (startvollist & otherdisklist)
set wholelist to (disklist & desktoplist)
set this_item to 0
log ("_height" & space & _height)
log "iconcol_count" & space & iconcol_count
log "firsticon_dist" & space & firsticon_dist
log "newcol_dist" & space & newcol_dist
log "iconcol_dist" & space & iconcol_dist
log "const" & space & const
log "newcol_dist + const" & space & (newcol_dist + const) as text
log "chk_default" & space & chk_default as text
log "chkLeft_default" & space & chkLeft_default as text
log otherdisklist
log clipsave
repeat with i from 1 to count of wholelist
set this_item to this_item + 1
set diskcount to (count of wholelist)
set desktarg to (item i of wholelist)
if this_item / iconcol_count = (this_item / iconcol_count as integer) then
if this_item = iconcol_count then
set a to col1 - const
set (desktop position of desktarg) to {a, b}
else
if chkLeft_default is "1" then
(((round (this_item / iconcol_count) rounding up) * (newcol_dist - const)) - (firstcol_dist))
else
set a to ((_width - (round (this_item / iconcol_count) * (newcol_dist + const))) + (firstcol_dist))
end if
if b > heightdistance then
set b to iconcol_dist
else
set b to (b + iconcol_dist)
end if
set (desktop position of desktarg) to {a, b}
end if
else if this_item / iconcol_count is not (this_item / iconcol_count as integer) then
if this_item < iconcol_count then
set a to col1 - const
set (desktop position of desktarg) to {a, b}
if b > heightdistance then
set b to iconcol_dist
else
set b to (b + iconcol_dist)
end if
else if this_item = iconcol_count then
set a to col1 - const
set (desktop position of desktarg) to {a, b}
else
if chkLeft_default is "1" then
set a to (((round (this_item / iconcol_count) rounding up) * (newcol_dist - const)) - (firstcol_dist))
else
set a to ((_width - ((round (this_item / iconcol_count) rounding up) * (newcol_dist + const))) + (firstcol_dist))
end if
if b > heightdistance - firstcol_dist then
set b to firsticon_dist
else
set b to (b + iconcol_dist)
end if
set (desktop position of desktarg) to {a, b}
end if
end if
end repeat
end tell
if clipsave = "1" then
set the clipboard to "
use AppleScript version \"2.5\"
use scripting additions
tell application \"System Events\"
tell process \"Finder\"
set screensize to size of first scroll area where its position is {0, 0}
end tell
end tell
set {_width, _height} to screensize
set a to" & space & col1 & space & "
set b to" & space & firsticon_dist & space & "
tell application \"Finder\"
set itemlist to (every item of desktop) where its class is not disk
set desktoplist to reverse of itemlist
set startvollist to startup disk as list
set startvolname to (startup disk as text)
set disklist to ((every item of desktop) where its class is disk)
set otherdisklist to {}
repeat with i from 1 to count disklist
set thestring to get disklist's item i as text
if thestring is not startvolname then set otherdisklist to (otherdisklist & {item i of disklist})
end repeat
if" & space & "\"" & disksort & "\"" & space & "is in {\"Name\"} then
set otherdisklist to sort otherdisklist by name
else if" & space & "\"" & disksort & "\"" & space & "is in {\"Modification Date\"} then
set otherdisklist to sort otherdisklist by modification date
else if" & space & "\"" & disksort & "\"" & space & "is in {\"Creation Date\"} then
set otherdisklist to sort otherdisklist by creation date
else if" & space & "\"" & disksort & "\"" & space & "is in {\"Kind\"} then
set otherdisklist to sort otherdisklist by kind
end if
if" & space & "\"" & chk_default & "\"" & space & "is \"1\" then
set otherdisklist to reverse of otherdisklist
end if
if" & space & "\"" & nondisksort & "\"" & space & "is in {\"Name\"} then
set desktoplist to sort itemlist by name
else if" & space & "\"" & nondisksort & "\"" & space & "is in {\"Modification Date\"} then
set desktoplist to sort itemlist by modification date
else if" & space & "\"" & nondisksort & "\"" & space & "is in {\"Creation Date\"} then
set desktoplist to sort itemlist by creation date
else if" & space & "\"" & nondisksort & "\"" & space & "is in {\"Kind\"} then
set desktoplist to sort itemlist by kind
end if
if" & space & "\"" & chk1_default & "\"" & space & "is \"1\" then
set desktoplist to reverse of desktoplist
end if
set disklist to (startvollist & otherdisklist)
set wholelist to (disklist & desktoplist)
set this_item to 0
repeat with i from 1 to count of wholelist
set this_item to this_item + 1
set diskcount to (count of wholelist)
set desktarg to (item i of wholelist)
if this_item /" & space & iconcol_count & space & "= (this_item /" & space & iconcol_count & space & "as integer) then
if this_item =" & space & iconcol_count & space & "then
set a to" & space & col1 & space & "-" & space & const & space & "
set (desktop position of desktarg) to {a, b}
else
if" & space & chkLeft_default & space & "is \"1\" then
(((round (this_item /" & space & iconcol_count & space & ") rounding up) * (" & space & newcol_dist & space & "-" & space & const & space & ")) - (" & space & firstcol_dist & space & "))
else
set a to ((_width - (round (this_item /" & space & iconcol_count & space & ") * (" & space & newcol_dist & space & "+" & space & const & space & "))) + (" & space & firstcol_dist & space & "))
end if
if b >" & space & heightdistance & space & "then
set b to" & space & iconcol_dist & space & "
else
set b to (b +" & space & iconcol_dist & space & ")
end if
set (desktop position of desktarg) to {a, b}
end if
else if this_item /" & space & iconcol_count & space & "is not (this_item /" & space & iconcol_count & space & "as integer) then
if this_item <" & space & iconcol_count & space & "then
set a to" & space & col1 & space & "-" & space & const & space & "
set (desktop position of desktarg) to {a, b}
if b >" & space & heightdistance & space & "then
set b to" & space & iconcol_dist & space & "
else
set b to (b +" & space & iconcol_dist & space & ")
end if
else if this_item =" & space & iconcol_count & space & "then
set a to" & space & col1 & space & "-" & space & const & space & "
set (desktop position of desktarg) to {a, b}
else
if" & space & chkLeft_default & space & "is \"1\" then
set a to (((round (this_item /" & space & iconcol_count & space & ") rounding up) * (" & space & newcol_dist & space & "-" & space & const & space & ")) - (" & space & firstcol_dist & space & "))
else
set a to ((_width - ((round (this_item /" & space & iconcol_count & space & ") rounding up) * (" & space & newcol_dist & space & "+" & space & const & space & "))) + (" & space & firstcol_dist & space & "))
end if
if b >" & space & heightdistance & space & "-" & space & firstcol_dist & space & "then
set b to" & space & firsticon_dist & space & "
else
set b to (b +" & space & iconcol_dist & space & ")
end if
set (desktop position of desktarg) to {a, b}
end if
end if
end repeat
end tell"
end if
else
display dialog "The dialog was closed without submitting the values"
end if
on error errorMessage
tell me to activate
display alert "An error occurred" message errorMessage --as warning
end try
on getDialogConfiguration(pashuaLocation)
prepare storage for (path to me) default values {iconcol_count:"19"}
prepare storage for (path to me) default values {firsticon_dist:"55"}
prepare storage for (path to me) default values {newcol_dist:"95"}
prepare storage for (path to me) default values {const:"15"}
prepare storage for (path to me) default values {disksort:"Kind"}
prepare storage for (path to me) default values {nondisksort:"Name"}
prepare storage for (path to me) default values {chk_default:"Normal"}
prepare storage for (path to me) default values {chk1_default:"Normal"}
prepare storage for (path to me) default values {chkLeft_default:"Normal"}
prepare storage for (path to me) default values {clipsave:"Normal"}
set iconcol_count to value for key "iconcol_count"
set firsticon_dist to value for key "firsticon_dist"
set newcol_dist to value for key "newcol_dist"
set const to value for key "const"
set disksort to value for key "disksort"
set nondisksort to value for key "nondisksort"
set chk_default to value for key "chk_default"
set chk1_default to value for key "chk1_default"
set chkLeft_default to value for key "chkLeft_default"
set clipsave to value for key "clipsave"
if pashuaLocation is not "" then
set img to "img.type = image
img.x = 435
img.y = 433
img.maxwidth = 128
img.tooltip = This is an element of type “image”
img.path = " & (POSIX path of pashuaLocation) & "/Contents/Resources/AppIcon@2.png" & return
else
set img to ""
end if
return "
# Set window title
*.title = Desktop Wrapper
txt.type = text
txt.default =***************** Destop Wrap **************[return][return][return][return][return][return][return][return]This script will let you make a custom arrangement for icons on the desktop that you can re-apply as needed. Desktop icons will be wrapped into columns according to these settings.[return][return]Experiment with the pop-up menus to get desired placements and spacing. Use View>Show View Options in Finder to customize icon size and icon label appearance.[return][return]Checkboxes:[return][return]Reverse sort disk icons - This will reverse the selected sorting order of disk icons.[return][return]Reverse sort non-disk icons - This will reverse the selected sorting order of non-disk icons.[return][return]Left-align icons - starts icon placement at the left edge of screen.[return][return]Copy static AppleScript to clipboard - places a copy of the generated icon placement commands on the clipboard so that an AppleScript can easily be created to quickly apply the custom icon arrangement.
txt.height = 276
txt.width = 320
txt.x = 340
txt.y = 44
txt.tooltip = This is an element of type “text”
# Add popup menus
iconcol_count.type = popup
iconcol_count.label = Number of icons per column
iconcol_count.width = 64
iconcol_count.option = 9
iconcol_count.option = 10
iconcol_count.option = 11
iconcol_count.option = 12
iconcol_count.option = 13
iconcol_count.option = 14
iconcol_count.option = 15
iconcol_count.option = 16
iconcol_count.option = 17
iconcol_count.option = 18
iconcol_count.option = 19
iconcol_count.option = 20
iconcol_count.option = 21
iconcol_count.option = 22
iconcol_count.default = " & space & iconcol_count & "
iconcol_count.tooltip = Set number of icons per column
firsticon_dist.type = popup
firsticon_dist.label = distance from top of screen to top of icons
firsticon_dist.width = 64
firsticon_dist.option = 43
firsticon_dist.option = 47
firsticon_dist.option = 51
firsticon_dist.option = 55
firsticon_dist.option = 59
firsticon_dist.option = 63
firsticon_dist.option = 67
firsticon_dist.option = 71
firsticon_dist.option = 75
firsticon_dist.option = 79
firsticon_dist.option = 83
firsticon_dist.default = " & space & firsticon_dist & "
firsticon_dist.tooltip = Set distance from top of screen to top of icons
newcol_dist.type = popup
newcol_dist.label = relative column width
newcol_dist.width = 80
newcol_dist.option = 60
newcol_dist.option = 65
newcol_dist.option = 70
newcol_dist.option = 75
newcol_dist.option = 80
newcol_dist.option = 85
newcol_dist.option = 95
newcol_dist.option = 105
newcol_dist.option = 115
newcol_dist.option = 125
newcol_dist.option = 135
newcol_dist.option = 145
newcol_dist.option = 155
newcol_dist.option = 165
newcol_dist.option = 175
newcol_dist.option = 185
newcol_dist.option = 195
newcol_dist.option = 205
newcol_dist.option = 215
newcol_dist.option = 225
newcol_dist.option = 235
newcol_dist.option = 245
newcol_dist.default = " & space & newcol_dist & "
newcol_dist.tooltip = Set relative column width
const.type = popup
const.label = relative horizontal column start position
const.width = 80
const.option = -30
const.option = -25
const.option = -20
const.option = -10
const.option = -5
const.option = 0
const.option = 5
const.option = 10
const.option = 15
const.option = 20
const.option = 25
const.option = 30
const.option = 35
const.option = 40
const.option = 45
const.option = 50
const.default = " & space & const & "
const.tooltip = Set relative horizontal column start position
disksort.type = popup
disksort.label = Sort disk icons by:
disksort.width = 300
disksort.option = Name
disksort.option = Kind
disksort.option = Modification date
disksort.option = Creation date
disksort.default =" & space & disksort & "
disksort.tooltip = Set sorting method
nondisksort.type = popup
nondisksort.label = Sort non-disk icons by:
nondisksort.width = 300
nondisksort.option = Name
nondisksort.option = Kind
nondisksort.option = Modification date
nondisksort.option = Creation date
nondisksort.default =" & space & nondisksort & "
nondisksort.tooltip = Set sorting method for non-disk icons
# Add 3 checkboxes
chk_default.rely = -18
chk_default.type = checkbox
chk_default.label = Reverse sort disk icons
chk_default.tooltip = Check to reverse sort disk icons
chk_default.default =" & space & chk_default & "
chk1_default.rely = -18
chk1_default.type = checkbox
chk1_default.label = Reverse sort non-disk icons
chk1_default.tooltip = Check to reverse sort non-disk icons
chk1_default.default =" & space & chk1_default & "
chkLeft_default.rely = -18
chkLeft_default.type = checkbox
chkLeft_default.label = Left align icons
chkLeft_default.tooltip = Check to align icons on left side of screen
chkLeft_default.default =" & space & chkLeft_default & "
clipsave.rely = -18
clipsave.type = checkbox
clipsave.label = Copy static AppleScript to clipboard
clipsave.tooltip = Check to copy a static AppleScript with current settings to the clipboard
clipsave.default =" & space & clipsave & "
# Add a cancel button with default label
cb.type = cancelbutton
cb.tooltip = This is an element of type “cancelbutton”
db.type = defaultbutton
db.tooltip = This is an element of type “defaultbutton” (which is automatically added to each window, if not included in the configuration)
" & img
end getDialogConfiguration
on showDialog(config, customLocation)
-- Create path for temporary file
set AppleScript's text item delimiters to ""
set tmpfile to ((path to temporary items folder as text) & "Pashua_" & (characters 3 thru end of ((random number) as text)) as text)
-- Write temporary file and fill it with the configuration string
set fhandle to open for access tmpfile with write permission
write (config as text) to fhandle as «class utf8»
close access fhandle
set posixtmpfile to POSIX path of tmpfile
set pashua to getPashuaPath(customLocation)
set pashuabinary to (POSIX path of pashua) & "Contents/MacOS/Pashua"
-- Execute pashua and get the string returned
set pashuaCall to quoted form of pashuabinary & " " & quoted form of posixtmpfile
set pashuaResult to do shell script (pashuaCall)
-- Delete the temporary file
tell application "System Events" to delete file tmpfile -- silently and immediately delete the tempfile
-- Check whether the dialog was submitted at all.
-- If this is not the case, return an empty list
if pashuaResult = "" then
return {}
end if
set AppleScript's text item delimiters to return
set resultLines to text items of pashuaResult
set AppleScript's text item delimiters to ""
set recordComponents to {}
repeat with currentLine in resultLines
set eqpos to offset of "=" in currentLine
if eqpos is not 0 then
set varKey to word 1 of currentLine
try
set varValue to (text (eqpos + 1) thru end of currentLine)
-- Quote any quotation marks in varValue with a backslash.
-- The proper way to do this would be a handler, but as
-- all code for interfacing to Pashua should be as compact
-- as possible, we rather do it inline
set AppleScript's text item delimiters to "\""
set textItems to every text item of varValue
set AppleScript's text item delimiters to "\\\""
set varValue to textItems as text
set AppleScript's text item delimiters to ""
on error
set varValue to ""
end try
copy (varKey & ":\"" & varValue & "\"") to end of recordComponents
end if
end repeat
-- Return the record we read from the tmpfile
set AppleScript's text item delimiters to ", "
set resultList to (run script "return {" & (recordComponents as text) & "}")
set AppleScript's text item delimiters to {""}
return resultList
end showDialog
on getPashuaPath(customFolder)
set myself to (path to me as text)
tell application "Finder"
-- Try to find it by application file id
if exists (application file id "net.bluem.pashua" as alias as text) then
return POSIX path of (application file id "net.bluem.pashua" as alias as string)
end if
error "Could not find Pashua.app" & return & return & "Try double-clicking the Pashua.app application file even though the ensuing dialog box says it's not meant to be used that way."
end tell
end getPashuaPath
@loshlee
Copy link
Author

loshlee commented Mar 6, 2024

Desktop Wrap is an AppleScript Studio application I created several years ago to simplify keeping desktop icons organized in Mac OS X. Recent versions of macOS allow several ways to organize the icons, but I find that they can still end up disorganized, and Desktop Wrap provides some options that the system doesn’t. Also, I like having a preset script that I can run to instantly set things right. The AppleScript solution provided here is an open and editable substitute for that application for use in the current macOS. You can use it to arrange the sorting and placement of desktop icons and to generate any number of custom AppleScripts to quickly set desktop icons into a custom arrangement. It also provides an example of integrated use of two scripting add-ons, Pashua and PrefsStorageLib, which work together to provide a better graphical interface for Desktop Wrap than would be possible otherwise.

Preparation:

Copy the entire AppleScript source from the code block at the bottom of the post, paste it into a window in Script Editor, save as an application anywhere you like using whatever name you choose. (Due to recent security measures, you may have to save the script as an application using Script Editor in order for it to run even in Script Editor.) We’ll call it Wrap.app. (You may have to add Script Editor to the list of apps with access granted in System Settings>Privacy & Security>Accessibility, System Settings>Privacy & Security>Files and Folders, and System Settings>Privacy & Security>Full Disk Access.)
Download Pashua
Download PrefsStorageLib
Adjust Finder preferences to display Hard Disks and other desired items on the desktop.
Steps for installation and use:

(Frankly, the implementation of this AppleScript in the latest version of macOS is confusing and not even fully manageable. You may find that you can’t run it as an app at all. Instead, you may have to open the app you saved in Script Editor in order to run it. But its purpose can still be accomplished, because you can run it in Script Editor, use the Pashua interface to select the option to place the output on the clipboard, then save that output as an app or script. If you make it an app, add it to System Settings>Privacy & Security>Accessibility by dragging.)

• Open and unlock the Security & Privacy prefpane in System preferences. Select the Privacy tab at the top. Select Accessibility from the list on the left, then drag Wrap.app into the list on the right. Then select Full Disk Access from the list on the left, then again drag Wrap.app into the list on the right.

• Put Pashua.app from the Pashua distribution into your Applications folder. (macOS 10.14 Sonoma has made this process more difficult. I’ve had the best success by simply opening System Settings, choosing Privacy & Security, then Accessibility. Then look for any listing for the Pashua app and if it’s there, delete it using the “-“ at the bottom of the window. Then drag the Pashua app into the window.)

• Put the PrefsStorageLib.scptd from the PrefsStorageLib distribution into the Script Libraries folder of the Library folder of your Home folder. If the Script Libraries folder doesn’t exist in the Library folder of your Home folder, create it.

• When you first launch Wrap.app, the system should prompt you to approve its use. Click OK. This may happen more than once, so click OK again if needed. When Pashua opens, the settings will be available in the window along with some guidance. (Note: macOS 10.14 Sonoma has made this process more difficult for me. Save the “Wrap” application to a different location, then drag it to the location where the previous instance of the app was saved, then accept the prompt to replace it. In Script Editor, you can choose a new location for saving by pressing ⇧⌥⌘ S. It may then be necessary to remove Wrap and Pashua from System Settings>Privacy & Security>Accessibility again, then drag them there one more time.)

• Note that there is an option for aligning icons starting from the left, so if you’ve ever wanted your Mac’s desktop to look more like a traditional Windows desktop, here’s your chance. Remember that new icons are always aligned toward the right, so if you want them to stay to the left, you’ll need to run the script again or move new icons manually.

• Note that the last setting option (checkbox: Copy static AppleScript to Clipboard) allows you to place the generated icon wrapping commands onto the clipboard so you can create an AppleScript or AppleScript app that can immediately reset the icons with your customized settings. You need the AppleScript if you want a way to set desktop items using the adjustments you made without causing Pashua to display the settings first.

• After the AppleScript has been saved as an application, the path to me constructs become established so that the script can be run from within Script Editor. That might be useful if you want to customize the options to meet your own requirements.

• There’s no workaround for granting assistive access for both the AppleScript app and the Pashua app. If you use the Pashua window to create the app that will set the Desktop icon positions without opening Pashua, that will need assistive access, too. I’ve run into some problems lately that seem to only be solved by having no more than one version of an AppleScript app with the same name stored on the disk. Usually the problems can be solved by removing the listing for the app in the Accessibility area of Privacy & Security of System Settings, then reading it.

Background

This AppleScript solution is a replacement for an app called Desktop Wrap that I created using AppleScript Studio back in the days when Mac OS X wasn’t very reliable for keeping icons in the same place on the desktop after logging out and back in. I worked out a set of simple but reliable calculations for organizing desktop icons to create Desktop Wrap, and I believe that that functionality combined with an example of the joint use of Pashua and PrefStorageLib might be interesting to some. There are a few reasons I never successfully migrated from AppleScript Studio to AppleScript Obj-C in order to provide a fully functional and current version of Desktop Wrap. The main ones are that transitioning to AppleScript Obj-C presented a fairly steep learning curve for me, and I didn’t really want to pay an annual membership to proliferate what for me has been mostly a hobby.

There’s a good chance that the solution is compatible with Sierra and High Sierra systems, although I haven’t tested (the security measures necessary for making it work with those systems will probably differ from those describe in the installation instructions). I wasn’t able to make it work in El Capitan, so if you figure out how, please let me know. PrefsStorageLib has been updated, so the AppleScript has been updated to specify version 1.1.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment