OmniPlan links to specific task(s)

Out of the box, Hook can already create and support links to particular OmniPlan files.

The following pair of scripts (Open Item and Get Address) enable Hook to link to one or more specific tasks in OmniPlan:

  • The Hook name and link created is based on the task(s) selected in the OmniPlan GUI,
  • and the link created opens the specified file, and also restores selection of one or more particular tasks.

Get Address and Open Item scripts below

(Note that Get Name can be left blank - its function is covered within the Get Address script)

Get Address

(Copy the whole script, all the way down to "end map")

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

tell application "OmniPlan"
    set ds to documents as list
    if 0 < length of ds then
        set fp to "omniplan://localhost" & my encodedPath(POSIX path of ((file of (item 1 of ds)) as alias))
        set ws to (windows as list)
        if 0 < length of ws then
            set seln to (selected tasks of (item 1 of ws))
            if missing value is not seln and 0 < length of seln then
                script go
                    on |λ|(x)
                        id of x
                    end |λ|
                end script
                set taskIDs to "task/" & my intercalate(",%2520", my map(go, seln))
                script titles
                    on |λ|(x)
                        name of x
                    end |λ|
                end script
                "[" & my intercalate(", ", my map(titles, seln)) & ¬
                    "](" & fp & taskIDs & ")"
            else
                "[" & name of item 1 of ds & "](" & fp & ")"
            end if
        else
            "[" & name of item 1 of ds & "](" & fp & ")"
        end if
    else
        ""
    end if
end tell


-- encodedPath :: FilePath -> Percent Encoded String
on encodedPath(fp)
    tell current application
        set charSet to URLPathAllowedCharacterSet of its NSCharacterSet
        (stringByAddingPercentEncodingWithAllowedCharacters_(charSet) of ¬
            stringWithString_(fp) of its NSString) as string
    end tell
end encodedPath

-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, delim}
    set str to xs as text
    set my text item delimiters to dlm
    str
end intercalate

-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    -- 2nd class handler function lifted into 1st class script wrapper. 
    if script is class of f then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    -- The list obtained by applying f
    -- to each element of xs.
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

Open Item

tell application "OmniPlan"
    activate
    GetURL "$0"
end tell
1 Like

It’s great to see fine-grained linking! That’s a very important direction. And I’m sure omniplan users will love that ability.

(I personally don’t use OmniPlan yet, but it’s been on my wish list for a long time, and I use the other OmniOutliner and OmniFocus on a daily basis, and OmniGraffle for most of my diagramming needs.)

Thanks, Rob!!