Don't give up so fast
After mentioning Hazel I had another idea: Hazel is able to monitor file system changes, but it won't tell us what (inside a file) has changed. But with the proper script this may be enough!
When you perform any action in Things (e.g. marking something as completed) it will sync immediately and also write the changes to disk immediately. (Note the cloud icon that appears in the upper right corner of the Things window.) That means, after each action in Things there is something that will be registered by FSEvents.
Observing the FSEvents while changing something in Things I figured out that after each action in Things a temporary file "Things.sqlite3-journal" appears and disappears in the folder ~/Library/Containers/com.culturedcode.ThingsMac/Data/Library/Application Support/Cultured Code/Things. (The appearing/disappearing of the file may not be visible in the Finder.[1])
I tried to catch this with Hazel but it didn't really work. However – to my big surprise (thanks @peternlewis) – KM's Folder Trigger is able to catch it quite reliably!
So, here a new macro.
It does this:
- The macro trigger is watching the aforementioned folder for any file additions ("Things.sqlite3-journal")
- Each time the macro is triggered the AppleScript tests for a change of the status of the "Debug Docs" task. The status change must be "open" --> "completed" (and not the contrary)
- In order to do this the script stores the previous status in NSUserDefaults (on disk: in a plist (preferences) file). [2]
- If the required status change is met then it creates the new task in "Work"
[test] Things: Create New Task (Via Folder Monitoring).kmmacros (3.0 KB)
This is the content of the AppleScript:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"aaa.atest.ThingsDebugDocsTrigger"
theDefaults's registerDefaults:{ddStatusLast:"open"}
set newTask to "New To-Do"
set ddStatusPrevious to ddStatusLast of theDefaults as text
tell application "Things3"
set ddStatusCurrent to status of to do "Debug Docs" as text
set ddStatusHasChanged to (ddStatusCurrent ≠ ddStatusPrevious)
if ddStatusHasChanged and ddStatusPrevious is not "completed" then tell area "Work" to make new to do with properties {name:newTask, due date:current date}
end tell
if ddStatusHasChanged then set ddStatusLast of theDefaults to ddStatusCurrent
# For debugging only
--say "changed " & ddStatusHasChanged
Thoughts:
Of course, the macro is – CPU-wise – more expensive than the manual method with the trigger in the task's Notes field. (The macro triggers on every change you make in Things.) But since it is using FSEvents it is way less expensive than having a every 1s and 24/7 looping macro.
That being said, personally, I would always prefer the manual solution (the link in the Notes field), because I don't like stuff running in the background. (There's already enough of it.) But this macro is way more interesting, and, after all, you have asked for full-auto
If things get messed up:
You can always reset the stored status of the "Debug Docs" task by executing this in the Terminal:
defaults delete aaa.atest.ThingsDebugDocsTrigger
(I've named it "aaa…" so that you can easily locate it also in the prefs folder.)
This will reset the stored last status of the task to "open".
Note:
This is a test macro for your exemplary "Debug Docs" task. If it works for you and you decide to use it adjust the names of the variables and the name of the prefs file to something more adequate. If you want to extend the macro to other tasks just add new variables and the appropriate checks. (No need to create multiple macros, and you can store all the statuses in the same prefs file.)
Caveats:
- If you perform your actions in Things too quickly, e.g. checking and immediately unchecking the task the macro may not be able to catch up.
- When the script runs (and the conditions are met) you'll see a slight flickering in the Things window. Take it as a friendly confirmation that the script has run and the new task was created successfully
Edit (2017-09-08):
Optimized the AppleScript and added feedback for debugging. (Uncomment the last line of the script to get audible feedback on status changes of the task.)
[1]: You can conveniently see File System events with filemon (Terminal) or with FSMonitor (GUI)
[2]: You can as well store the status in a KM variable. (Originally the script was meant to be used with Hazel, so I used UserDefaults.)