I’ve attached the two templates, one for project notes as an OmniOutliner .ooutline
file, the other as a MindNode .mindnode
file. The former is a simplified version of OO’s built-in “Stylish with Level Style” and the latter is pre-populated with David Allen’s project trigger list which I copied from Getting Things Done.
These two get stored in the script bundle. For posterity (and because only about 0.05% of it is my own work), I’m pasting the current script I use here. There are some comments at the top which I have not updated (references to DTPO v2, for instance):
property pblnJustFolder : false
property pblnUseSyncAsRoot : true
property pblnPreferFTToOmniOO3 : false
-- Robin Trew
-- ver .204 June 19 2011
-- ver .205 [corrects a bug in which a newly created folder was not immediately displayed]
-- ver .206 [unifies the folder and notes scripts, differing only by value of
-- the property pblnJustFolder at the top of the script]
-- Aug 22 2011
-- Ver .208 Still defaults to the DT Database named in pstrDTDB (below)
-- but can use different DT databases for different OF folders
-- (will use the first existing DT database whose POSIX path is found in the note of an enclosing OmniFocus folder
-- [a script for editing OF folder notes can be found at
-- http://forums.omnigroup.com/showthread.php?t=21942]
-- ver .211 Sep 12 2011
-- Adds option, above - top of script, to make the Sync group the root of all new folders
-- Ver .214 Nov 19 2012 Uses www.FoldingText.com rather than OO3 if pblnPreferFTToOmniOO3=true
-- Ver .216 Now creates .ooutline files.
-- Ver .218 Rich text RTF Link in OF Project Notes
-- Ver .222 Gabriel added MindNode template creation within DTP group
-- Disclaimer
-- This is just a rough draft of something which I have sketched for my own personal use,
-- and which is provided purely as an illustration of possible approaches to coding.
-- You are free to adapt and reuse any part of it, without any warranties, implied
-- or explicit, as to its behaviour or suitability for use
-- IF property pblnJustFolder : **false** (see top of script)
-- CREATES/OPENS A PROJECT NOTES FILE (STORED IN DEVONthink 2) FOR THE SELECTED OMNIFOCUS PROJECT.
-- 1. The project notes file is an OmniOutliner 3 document stored in DEVONthink 2 folder
-- 2. The Devonthink record contains a hyperlink back to the OmniFocus project
-- 2. The script ensures that a DT hyperlink to the document in DevonThink is placed in the note field of the project
-- 3. In the absence of a link to existing notes in DevonThink,
-- the script will seek or create the 003 file in a DevonThink folder which matches
-- the folder path of the project in OmniFocus
-- (and add the hyperlinks from project to notes, and from folder and notes to project)
-- OR - IF property pblnJustFolder : **true** (see top of script)
-- JUST CREATES/OPENS A PROJECT MATERIALS FOLDER (IN DEVONthink 2)
-- FOR THE SELECTED OMNIFOCUS PROJECT.
-- 1. The script ensures that a DT hyperlink to the document in DevonThink is placed in
-- the note field of the project
-- 2. In the absence of a link to an existing folder in DevonThink,
-- the script will add the hyperlinks from project to folder, and from folder to project)
-- Acknowledgements
-- Inspired by Jim Harrison's excellent scripts, which use the Finder rather than DEVONthink 2
-- http://jhh.med.virginia.edu/main/OmniFocusScripts
-- The icon attached to this file is from the Float collection by Corey Marion
-- http://iconfactory.com/freeware/preview/flot
-- GLOBAL CONSTANTS
-- Initially assumes that project folders will be maintained in
-- a database named [UserName]/DEVONthink Databases/Omnifocus.
-- Edit the name and path below to change the location and/or name
--of the main Projects folder that will contain the individual project folders
property pstrDTDB : "OmniFocus" -- name of default Devonthink Database
property pstrDTsuffix : ".dtBase2"
property pstrDocsPath : "Macintosh HD:Users:YOUR_USERNAME:Databases:" -- (path to documents folder as string) -- path to ~/Documents
property pstrSync : "Active Projects"
property pstrTemplate : "Default"
property pstrMindMapTemplate : "Default"
property pstrOO3Suffix : ".ooutline"
property pstrFTSuffix : ".ft"
property pstrMNSuffix : ".mindnode"
property pstrOFPrefix : "omnifocus:///task/"
property pstrXMLPrefix : "<value key=\"link\">"
property pstrRunDelim : "</lit></run>"
property pstrDTPrefix : "x-devonthink-item://"
property pstrDBPath : "/Users/YOUR_USERNAME/Library/Containers/com.omnigroup.OmniFocus3/Data/Library/Application Support/OmniFocus/OmniFocus Caches/OmniFocusDatabase"
property pstrFolderLinkTitle : "[DEVONthink group]"
property pstrNoteLinkTitle : "[OmniOutliner notes]"
property plngURLchars : 36
on run
-- IS A PROJECT (OR ONE OF ITS TASKS) SELECTED IN OMNIFOCUS ?
set {oProject, strProjName, strProjID} to GetSeldProject()
if oProject is missing value then return
-- IS THERE A RELEVANT LINK IN THE NOTE FIELD OF THE PROJECT ?
set {strFolderURL, strNotesURL} to DTLinksInNote(oProject)
-- AND IF SO, DOES IT LEAD ANYWHERE ?
if pblnJustFolder then
if strFolderURL ≠ "" then if FollowDTLink(strFolderURL) then return
else
if strNotesURL ≠ "" then if FollowDTLink(strNotesURL) then return
end if
-- IN THE ABSENCE OF A LIVE DT LINK, CREATE OR FIND A MATCHING FOLDER PATH IN DT
tell application id "DNtp"
set oDTFolder to my GetParallelFolder(oProject)
set group_name to name of oDTFolder
set group_reference_URL to reference URL of oDTFolder
if pblnJustFolder then
set strDTLink to reference URL of oDTFolder
else
-- WHICH NOTE APP ARE WE USING - FOLDINGTEXT OR OO3 ?
set blnFT to pblnPreferFTToOmniOO3 and my isAppInstalled("com.foldingtext.FoldingText")
if blnFT then
set strNoteSuffix to pstrFTSuffix
else
set strNoteSuffix to pstrOO3Suffix
end if
set strMindMapSuffix to pstrMNSuffix
-- CREATE OR FIND A NOTE FILE FOR THIS PROJECT
set strNoteName to "• " & strProjName
set recNotes to my GetNotes(oDTFolder, strNoteName, strNoteSuffix, strMindMapSuffix, strProjID)
set strDTLink to reference URL of recNotes -- FIX
end if
my UpdateOFNote(oProject, group_name, group_reference_URL, strNoteName, strDTLink) -- MODIFICATION
end tell
-- PLACE AN RTF-FORMATTED DT LINK TO THE NEW OR PRE-EXISTING NOTES IN THE NOTES FIELD OF THE PROJECT
if pblnJustFolder then
set strLinkTitle to pstrFolderLinkTitle
else
set strLinkTitle to pstrNoteLinkTitle
end if
-- AND FOLLOW THE LINK TO THE FOLDER OR NOTES DOCUMENT IN DT2
FollowDTLink(strDTLink)
tell application id "DNtp" to activate
end run
-- MODIFICATION
on UpdateOFNote(the_project, group_name, group_url, rec_name, rec_url)
-- BUILD NOTE
set the_note to "[DEVONthink group] " & group_name & linefeed & linefeed & "[OmniOutliner notes] " & rec_name & linefeed & linefeed & "================================================================================"
tell application "OmniFocus"
tell front document
set note of the_project to the_note
tell (note of the_project)
set value of attribute "link" of style of paragraph 1 to group_url
set value of attribute "link" of style of paragraph 3 to rec_url
end tell
end tell
end tell
end UpdateOFNote
-- Check whether an app is installed e.g. isAppInstalled("com.foldingtext.FoldingText")
-- for http://www.foldingtext.com
on isAppInstalled(strBundleCode)
try
tell application "Finder"
name of (application file id strBundleCode) ≠ ""
end tell
on error
return false
end try
end isAppInstalled
-- Return the first project selected in the Omnifocus GUI
on GetSeldProject()
tell application id "OFOC"
tell front document
-- GET THE FIRST SELECTED PROJECT (CONTENT OR SIDEBAR)
if (count of document windows) < 1 then return {missing value, "", ""}
tell front document window
set oProject to missing value
repeat with oPanel in {content, sidebar}
set lstSelns to (value of selected trees of oPanel where (class of value = task) or (class of value = project))
if (count of lstSelns) > 0 then
set oProject to first item of lstSelns
exit repeat
end if
end repeat
if oProject is missing value then return {missing value, "", ""}
if class of oProject = task then set oProject to containing project of oProject
tell oProject to return {it, name, id}
end tell
end tell
end tell
end GetSeldProject
on DTLinksInNote(oProject)
tell application id "OFOC"
-- DOES ITS NOTE CONTAIN A DEVONTHINK URL ?
set strQuery to "select CAST(notexmldata as text) from task where persistentIdentifier = \"" & (id of oProject) & "\""
set strNoteXML to do shell script "sqlite3 " & quoted form of pstrDBPath & space & quoted form of strQuery
set strLink to pstrXMLPrefix & pstrDTPrefix
set blnOpened to false
if strNoteXML contains strLink then
set {strDlm, my text item delimiters} to {my text item delimiters, pstrRunDelim}
set lstRuns to text items of strNoteXML
set my text item delimiters to "<lit>"
set {blnFolder, blnNote} to {false, false}
set {strFolderURL, strNotesURL} to {"", ""}
set strStart to text 1 thru 2 of pstrNoteLinkTitle
repeat with oRun in lstRuns
set lstSections to text items of oRun
if length of lstSections > 1 then
set strLabel to item -1 of lstSections
set strPreamble to item -2 of lstSections
if strLabel begins with strStart then
if not blnFolder then
if strLabel contains "folder" then
set strFolderURL to my parseLink(strPreamble)
if strFolderURL ≠ "" then set blnFolder to true
end if
end if
if not blnNote then
if strLabel contains "notes" then
set strNotesURL to my parseLink(strPreamble)
if strNotesURL ≠ "" then set blnNotes to true
end if
end if
end if
if blnFolder and blnNote then exit repeat
end if
end repeat
set my text item delimiters to strDlm
return {strFolderURL, strNotesURL}
else
if note of oProject = "" then set note of oProject to space -- (seems to prepare note for easier opening later)
return {"", ""}
end if
end tell
end DTLinksInNote
on parseLink(strXML)
set {strDlm, my text item delimiters} to {my text item delimiters, pstrXMLPrefix & pstrDTPrefix}
set lstParts to text items of strXML
set strURL to ""
if length of lstParts > 1 then
set my text item delimiters to "</value>"
set strURL to first text item of item 2 of lstParts
if length of strURL = plngURLchars then
set strURL to pstrDTPrefix & strURL
else
set strURL to ""
end if
end if
set my text item delimiters to strDlm
return strURL
end parseLink
on FollowDTLink(strURL)
if strURL ≠ "" then
set blnOpened to (do shell script "open " & quoted form of strURL) = ""
if blnOpened then
tell application id "DNtp" to activate
return true
else
return false
end if
else
return false
end if
end FollowDTLink
on GetParallelFolder(oProject)
set {strPath, strFolderDB, strProject} to GetProjPath(oProject)
tell application id "DNtp"
-- CHOOSE THE TARGET DATABASE
-- EITHER FROM A PATH IN THE ENCLOSING FOLDER, OR FROM THE DEFAULT
if strFolderDB ≠ "" then
set strDb to strFolderDB
else
set strDb to (POSIX path of pstrDocsPath) & pstrDTDB & pstrDTsuffix
end if
set oDb to open database strDb
if oDb is missing value then
set oAnswer to display dialog "Create new Devonthink database at \"" & strDb & "\" ?" buttons {"Cancel", "OK"} default button 1
if the button returned of oAnswer is "Cancel" then return
set oDb to create database strDb
end if
-- DEPENDING ON GLOBAL SETTING, OPTIONALLY CREATE NEW FOLDER WITHIN SYNC GROUP
if pblnUseSyncAsRoot then
set oLocn to create location pstrSync & strPath in oDb
else
set oLocn to create location strPath in oDb
end if
set URL of oLocn to pstrOFPrefix & (id of oProject)
return oLocn
end tell
end GetParallelFolder
on GetProjPath(oProject)
tell application id "OFOC"
set strProject to name of oProject
set strPath to strProject
set oContainer to container of oProject
set blnFolderFound to false
set strFolderDB to ""
set cClass to the class of oContainer
repeat while cClass is not document
if not blnFolderFound then
if cClass is folder then
set strFolderDB to note of oContainer
if ((strFolderDB ends with pstrDTsuffix) and my FileExists(strFolderDB)) then set blnFolderFound to true
end if
end if
set strPath to name of oContainer & "/" & strPath
set oContainer to container of oContainer
set cClass to the class of oContainer
end repeat
return {"/" & strPath, strFolderDB, strProject}
end tell
end GetProjPath
on GetNotes(oDTFolder, strNoteFile, strNoteSuffix, strMindMapSuffix, strProjectID)
tell application id "DNtp"
set lstNoteRecs to children of oDTFolder where name = strNoteFile
if length of lstNoteRecs > 0 then
return first item of lstNoteRecs
else
-- IMPORT A FRESH TEMPLATE FILE FROM THE SAME FOLDER AS THIS SCRIPT
set strScriptFolder to POSIX path of (path to me)
--tell application id "MACS" to set oScriptFolder to container of oThisScript
set strTemplate to strScriptFolder & pstrTemplate & strNoteSuffix
set strMindMapTemplate to strScriptFolder & pstrMindMapTemplate & strMindMapSuffix
-- Check if OO Template Exists
if my BundleExists(strTemplate) or my FileExists(strTemplate) then
set oRec to import strTemplate to oDTFolder
else
-- OR FROM INSIDE THE SCRIPT BUNDLE
set strTemplate to POSIX path of (path to me) & pstrTemplate & strNoteSuffix
try
set oRec to import strTemplate to oDTFolder
on error
display alert strTemplate & " not found in this script bundle"
return missing value
end try
end if
-- Check if MindNode Template Exists
if my BundleExists(strMindMapTemplate) or my FileExists(strMindMapTemplate) then
set mnRec to import strMindMapTemplate to oDTFolder
else
-- OR FROM INSIDE THE SCRIPT BUNDLE
set strMindMapTemplate to POSIX path of (path to me) & pstrTemplate & strNoteSuffix
try
set mnRec to import strMindMapTemplate to oDTFolder
on error
display alert strMindMapTemplate & " not found in this script bundle"
return missing value
end try
end if
tell oRec
if it is missing value then return it
set its name to strNoteFile & " notes" & strNoteSuffix
set its URL to pstrOFPrefix & strProjectID
end tell
tell mnRec
if it is missing value then return it
set its name to strNoteFile & " trigger list" & strMindMapSuffix
set its URL to pstrOFPrefix & strProjectID
end tell
return oRec
end if
end tell
end GetNotes
on FileExists(strPath)
(do shell script ("test -e " & quoted form of strPath & "; echo $?")) = "0"
end FileExists
on BundleExists(strPath)
(do shell script ("test -d " & quoted form of strPath & "; echo $?")) = "0"
end BundleExists
The script I use in the OF toolbar to jump to the OO notes in DTP once I’ve run the above bundle:
tell application "OmniFocus"
tell front document
tell front document window
set lst_values to (value of selected trees of content) whose (class of value = task) or (class of value = project)
if (count of lst_values) = 0 then
set lst_values to (value of selected trees of sidebar) whose (class of value = task) or (class of value = project)
if (count of lst_values) = 0 then
display notification "Select a project or task"
return
end if
end if
set the_value to item 1 of lst_values
if class of the_value = task then
set the_project to containing project of the_value
else
set the_project to the_value
end if
end tell
set note_ref to a reference to (note of the_project)
tell note_ref
set oo_link to value of attribute "link" of style of paragraph 3
end tell
end tell
end tell
tell application "System Events"
open location oo_link
end tell
The script I use in the OF toolbar to jump to the DTP group once I’ve run the above bundle:
tell application "OmniFocus"
tell front document
tell front document window
set lst_values to (value of selected trees of content) whose (class of value = task) or (class of value = project)
if (count of lst_values) = 0 then
set lst_values to (value of selected trees of sidebar) whose (class of value = task) or (class of value = project)
if (count of lst_values) = 0 then
display notification "Select a project or task"
return
end if
end if
set the_value to item 1 of lst_values
if class of the_value = task then
set the_project to containing project of the_value
else
set the_project to the_value
end if
end tell
set note_ref to a reference to (note of the_project)
tell note_ref
set oo_link to value of attribute "link" of style of paragraph 1
end tell
end tell
end tell
tell application "System Events"
open location oo_link
end tell
OO MN templates.zip (147.5 KB)