PDA

View Full Version : Context Search and Replace script


davidamis
2008-01-29, 12:36 PM
Note: You don't need a script to do this, see post below.

This script will find all tasks with a context that you select from a list, and change the context of those tasks to another one that you also select from a list. The lists show the hierarcy of contexts, i.e. "Home:Upkeep (8)" optionally (default is on) showing a count of tasks for each context.

I orginally wrote this to clean up the lingering Import:whatever contexts from my GTD import, but it can also be used to consolidate contexts.

The Applescript code:

(*
OmniFocus context search and replace script
User selects a search context and a replace context from lists of all contexts in the document. Script then
finds all tasks with the search context and changes the context to the replace context.

To Do:
also change the default context for projects?

v1.1, 1/28/08, for OmniFocus 1.0, tested on Mac OS X 10.5.1
by David A of Mentor Software, Inc.
*)
global contextNameList
global contextIDList
property showTaskCount : true -- include the count of tasks for each context in the list of contexts

main()

on main()
global contextNameList, contextIDList
local searchContextName, replaceContextName, searchContextID, replaceContextID, searchTasks, aTask, taskCount

-- Make two equal-length parallel lists, contextNameList has the names and contextIDList holds the IDs of every context in the document
MakeContextLists()

--Ask the user which context to search for, and what it will be replaced with in each matching task.
set searchContextName to item 1 of (choose from list contextNameList with title "Context Search and Replace" with prompt "Choose a context to be replaced:")
set replaceContextName to item 1 of (choose from list contextNameList with title "Context Search and Replace" with prompt "Choose a context to replace with:")

-- convert the task name to a task ID string
set searchContextID to ContextNameToID(searchContextName)
set replaceContextID to ContextNameToID(replaceContextName)

if (searchContextID is "") or (replaceContextID is "") then -- bug check
display dialog "Error in the code"
return
end if

--Do the replace
set taskCount to 0
tell first document of application "OmniFocus"
tell context id searchContextID
set searchTasks to every task
repeat with aTask in searchTasks
set context of aTask to context id replaceContextID
end repeat
set taskCount to count of searchTasks
end tell
end tell
display dialog ("Changed " & taskCount as text) & " tasks from " & searchContextName & " to " & replaceContextName buttons {"OK"} default button "OK"
end main

on ContextNameToID(theContextName)
-- lookup the ID in contextIDList that coresponds to the name theContextName in contextNameList
global contextNameList, contextIDList
local i, aName

set i to 1
repeat with aName in contextNameList
if theContextName = (aName as text) then exit repeat
set i to i + 1
end repeat
if i is less than or equal to (count of contextNameList) then
return item i in contextIDList
else
return 0
end if
end ContextNameToID

on MakeContextLists()
-- fills in contextNameList, contextIDList
global contextNameList, contextIDList
local aContext, aContextID, taskCount, i

set contextNameList to {}
set contextIDList to {}
tell first document of application "OmniFocus"
repeat with aContext in contexts
GatherContexts of me from aContext below ""
end repeat
end tell

if showTaskCount then
set i to 1
tell first document of application "OmniFocus"
repeat with aContextID in contextIDList
tell context id aContextID
set taskCount to count of every task
end tell
if i = 1 then
set item i of contextNameList to ((item i of contextNameList & " (" & taskCount as rich text) & " tasks)")
else
set item i of contextNameList to ((item i of contextNameList & " (" & taskCount as rich text) & ")")
end if
set i to i + 1
end repeat
end tell
end if
end MakeContextLists

on GatherContexts from aContext below parentContexts
--This is recursively called to gather the name and ID of every context
global contextNameList, contextIDList
local childContext

tell first document of application "OmniFocus"
if parentContexts is "" then
set parentContexts to name of aContext
else
set parentContexts to parentContexts & ":" & name of aContext
end if
copy parentContexts to the end of contextNameList
copy (id of aContext) to the end of contextIDList
repeat with childContext in contexts of aContext
GatherContexts of me from childContext below parentContexts
end repeat
end tell
end GatherContexts

librarymonkey27
2008-01-29, 07:01 PM
super duper
thanks

davidamis
2008-01-31, 12:26 PM
Doh! not really needed.

As Ken Case pointed out (in an email to me), you don't really need a script to do this. You can go go to context mode, select all of the tasks in a given context, and drag them to another context. Oh well. I did find out how to script OmniFocus. Perhaps parts of the code can be used in another script.

David