There’s only two threads on MacScripter’s regarding the Stickies app, and they are both dated. So, I thought I would provide a few script suggestions. Please note that:
The Stickies app is not scriptable and, as a result, everything has to be done with System Events.
I intentionally omitted any error correction, which the user can add when required.
A new Stickie note can be created from a selection in an app with the Shift-Command-Y keyboard shortcut.
-- Position and resize frontmost note
tell application "System Events" to tell process "Stickies"
set frontmost to true
set position of window 1 to {50, 50}
set size of window 1 to {450, 300}
end tell
-- Position and resize every note to one location
tell application "System Events" to tell process "Stickies"
set frontmost to true
set position of every window to {50, 50}
set size of every window to {450, 300}
end tell
-- Resize and cascade notes
set {x, y} to {50, 50} -- initial position of notes
set {w, h} to {450, 300} -- initial size of notes
set windowOverlap to 40
tell application "System Events" to tell process "Stickies"
set frontmost to true
set windowCount to (count windows)
repeat with i from windowCount to 1 by -1 -- from old to new
-- repeat with i from 1 to windowCount -- from new to old
set position of window i to {x, y}
set size of window i to {w, h}
set {x, y} to {x + windowOverlap, y + windowOverlap}
end repeat
end tell
-- Resize and tile notes (revised 2022.10.10)
set {w, h} to {450, 300} -- user set size of notes
set wB to 10 -- user set buffer between notes
set {x1, y1, x2, y2} to {0, 25, 1920, 1080} -- user set usable screen bounds
set windowsPerRow to ((x2 - x1) - wB) div (w + wB) -- do not change
tell application "System Events" to tell process "Stickies"
set frontmost to true
set xOriginal to x1
repeat with i from 1 to (count windows)
set position of window i to {x1 + wB, y1 + wB}
set size of window i to {w, h}
if i mod windowsPerRow = 0 then
set x1 to xOriginal
set y1 to y1 + h + wB
else
set x1 to x1 + w + wB
end if
end repeat
end tell
-- Backup notes to text file on desktop (revised 2022.10.18)
set homeFolder to (path to home folder as text)
set stickieFolder to homeFolder & "Library:Containers:com.apple.Stickies:Data:Library:Stickies:"
set targetFile to homeFolder & "Desktop:" & "Stickie Notes.txt"
tell application "Finder"
set stickieFiles to (files in folder stickieFolder whose name extension is "rtfd")
set stickieFiles to sort stickieFiles by creation date
end tell
set text item delimiters to "/"
repeat with aFile in stickieFiles
set aPosixFile to POSIX path of (aFile as alias)
set aNote to do shell script "textutil -stdout -convert txt " & quoted form of aPosixFile
set contents of aFile to "---" & linefeed & text item -2 of aPosixFile & linefeed & "---" & linefeed & linefeed & aNote & linefeed & linefeed
end repeat
set text item delimiters to ""
set stickieFiles to stickieFiles as text
set openedFile to (open for access file targetFile with write permission)
try
set eof openedFile to 0
write stickieFiles to openedFile as «class utf8»
close access openedFile
on error errMsg number errNbr
close access openedFile
end try
-- Trim whitespace, create new note, and paste clipboard
use framework "Foundation"
use scripting additions
trimClipboardText()
createNote()
on trimClipboardText()
set thePattern to "(?m)^\\h+|\\h+$" -- user can edit to change characters removed
set theString to the clipboard -- user can edit for desired class type
set theString to current application's NSMutableString's stringWithString:theString
(theString's replaceOccurrencesOfString:thePattern withString:"" options:1024 range:{0, theString's |length|()})
set the clipboard to (theString as text)
end trimClipboardText
on createNote()
tell application "Stickies" to activate
tell application "System Events" to tell process "Stickies"
repeat until menu "File" of menu bar 1 exists
delay 0.02
end repeat
click menu item "New Note" of menu "File" of menu bar 1
repeat until menu "Edit" of menu bar 1 exists
delay 0.02
end repeat
click menu item "Paste" of menu "Edit" of menu bar 1
end tell
end createNote
Since using shell commands or AsObjC takes time to bootstrap, I usually use the more efficient plain-AppleScript handler for none very large text. Stickies - just the case when the text should not be large.:
on trimClipboardText()
set theText to the clipboard as text
-- removes Trailing and Leading Spaces and Tabs in the Clipboard text
script o
property aList : missing value
end script
set {ATID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {" ", tab}}
set o's aList to theText's text items
repeat with anItm in (get o's aList)
if contents of anItm is "" then set contents of anItm to missing value
end repeat
set the clipboard to o's aList's text as text
set AppleScript's text item delimiters to ATID
end trimClipboardText
set the clipboard to " This is test text with spaces and tabs "
trimClipboardText()
set trimmedText to the clipboard --> "This is test text with spaces and tabs"
.
Here is a very basic handler (variation of the handler above) without involving the clipboard:
on removeTrailingAndLeadingSpacesAndTabs_ATID(theText)
script o
property aList : missing value
end script
set {ATID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {" ", tab}}
set o's aList to theText's text items
repeat with anItm in (get o's aList)
if contents of anItm is "" then set contents of anItm to missing value
end repeat
set theText to o's aList's text as text
set AppleScript's text item delimiters to ATID
return theText
end removeTrailingAndLeadingSpacesAndTabs_ATID
.
Three do shell script solutions I know at the moment:
on removeTrailingAndLeadingSpacesAndTabs_sed(theText)
do shell script "echo " & quoted form of theText & " | sed -E 's/[[:space:]]+/ /g ; s/^[[:space:]]|[[:space:]]$//g'"
end removeTrailingAndLeadingSpacesAndTabs_sed
on removeTrailingAndLeadingSpacesAndTabs_xargs(theText)
do shell script "echo " & quoted form of theText & " | xargs"
end removeTrailingAndLeadingSpacesAndTabs_xargs
on removeTrailingAndLeadingSpacesAndTabs_tr(theText)
do shell script "echo " & theText & " | tr -s ' ' | sed -E 's/^ | $//g'"
end removeTrailingAndLeadingSpacesAndTabs_tr
.
AsObjC solution (one more):
use framework "Foundation"
use scripting additions
on removeTrailingAndLeadingSpacesAndTabs_AsObjC(theText)
set theString to current application's NSString's stringWithString:theText
set stringLength to theString's |length|()
set theString to theString's stringByReplacingOccurrencesOfString:" +" withString:" " options:(current application's NSRegularExpressionSearch) range:{location:0, |length|:stringLength}
set theWhiteSet to current application's NSCharacterSet's whitespaceCharacterSet()
return (theString's stringByTrimmingCharactersInSet:theWhiteSet) as text
end removeTrailingAndLeadingSpacesAndTabs_AsObjC
mactranslator. As you probably know, you delete the frontmost note by selecting File > Close from the Stickies menu, or use the command + W keyboard shortcut. The AppleScript equivalent is:
tell application "System Events" to tell process "Stickies"
set frontmost to true
click menu item "Close" of menu "File" of menu bar 1
end tell
You next receive the following dialog. I assume you could use GUI scripting to click on the Delete Note button. However, if the wrong note is frontmost, you would loose its contents and apparently would not be able to retrieve it.
mactranslator. The following script does what you want and worked on my Sonoma computer without issue. The script contains 0.5 second delays but 0.1 second delays worked in testing.
-- this script closes the frontmost Stickie note
-- the contents of the note are not saved and cannot be retrieved
tell application "System Events" to tell process "Stickies"
try
set frontmost to true
on error -- the Stickie app is not running
return
end try
click menu item "Close" of menu "File" of menu bar 1
delay 0.5 -- test smaller values
try
click button "Delete Note" of window 1
end try
delay 0.5 -- test smaller values
click menu item "Quit Stickies" of menu "Stickies" of menu bar 1
end tell
Perhaps you can help me with one other thing. I get two stickies by running this script:
tell application "Stickies" to activate
tell application "System Events" to tell process "Stickies"
repeat until menu "File" of menu bar 1 exists
delay 0.02
end repeat
click menu item "New Note" of menu "File" of menu bar 1
repeat until menu "Edit" of menu bar 1 exists
delay 0.02
end repeat
set frontmost to true
set position of window 1 to {100, 100}
set size of window 1 to {450, 100}
click menu item "Paste" of menu "Edit" of menu bar 1
end tell
mactranslator. I tested your script on my Sonoma computer, and I only get the blank note if there are no existing notes. Given the use scenario you described earlier, I assume that is the case.
One solution, which worked reliably on my computer, is to use the blank note if it exists:
tell application "Stickies" to activate
tell application "System Events" to tell process "Stickies"
delay 0.3 -- not required on my computer
set windowCount to count (every window whose title is "Untitled")
if windowCount is not 1 then
click menu item "New Note" of menu "File" of menu bar 1
repeat until menu "File" of menu bar 1 exists
delay 0.02
end repeat
end if
set position of window 1 to {100, 100}
set size of window 1 to {450, 100}
click menu item "Paste" of menu "Edit" of menu bar 1
end tell
It occurred to me that there might be another approach to close/delete a note without the save dialog. I suspect the numerous delays are not necessary, but they are good for testing.
tell application "System Events" to tell process "Stickies"
set frontmost to true
delay 0.2
key code 0 using command down -- select all text
delay 0.2
key code 51 -- delete text
delay 0.2
key code 13 using command down -- close note
end tell