Scripting the macOS Stickies app

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
3 Likes

Cool script, @peavine,

You can put automated delays instead of hard-coded delay 0.2:


repeat until menu "File" of menu bar 1 exists
delay 0.02
end repeat

repeat until menu "Edit" of menu bar 1 exists
delay 0.02
end repeat

I like this script. What characters are these:

	set thePattern to "(?m)^\\h+|\\h+$" 

Have you seen this handler from KniazidisR?

MacScripter / Automated Rutines, lesson 1. Working with Text.

If you just want spaces and tabs removed you could substitute this:

	set whiteSpaceCharacters to ¬
current application's NSCharacterSet's whitespaceCharacterSet()

Got it, thanks

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

How can I delete the current Sticky and then close the Stickies app? Thank you in advance!

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.

Quitting the Stickies app also has a keyboard shortcut, but the AppleScript equivalent is:

tell application "Stickies" to quit

Thank you for looking into this. I actually want to delete the note, since I only use it for a temporary display. And I always have just one note.

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
1 Like

Thank you, that works.

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

How come?
Screenshot 2024-03-12 at 09.44.52

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
1 Like

Thanks again!

I noticed that when I don’t quit the Stickies app, only one note is created. I can live with leaving the app open. Problem solved.