0
votes

I am working to outline a workflow in AppleScript. The script takes the next task I need to do from Omnifocus and requires me to determine if I can do it in 2 minutes or less. If I can, it starts a timer and I want it to wait until I actually do the task. Right now I have a dialog box pop up and I can mark the task complete when I am done with it. Unfortunately, some of the tasks I need to do are in Omnifocus and I can't do anything in Omnifocus with the dialog box open.

I would like to avoid using the dialog box so I can work in Omnifocus while the script is running. I'd like to be able to tell the script I'm done so it can stop the timer, tell me how long it took to do the task and then go on to mark the task complete in Omnifocus. I initially thought the best way to do this would be by entering a key combination. After a bit of research, I don't think I can do this in AppleScript. I am open to any idea of how to allow me to work in the middle of my script and then tell the program I am done with the task.

Here's my code:

on run {}
    with timeout of (30 * 60) seconds
        tell application "OmniFocus"
            activate
        end tell
        tell application "OmniFocus"
            tell default document to tell front document window
                set perspective name to "Daily Wrap-Up"
                tell content to set TreeList to (value of first leaf)
                repeat with ListItem in TreeList
                    set ProjectName to name of containing project of ListItem as text
                    set TaskName to " - " & name of ListItem
                    set NoteName to " - " & note of ListItem
                    display dialog "The task is:" & return & ProjectName & TaskName & NoteName & return & "Can you do this in 2 minutes or less?" buttons {"Yes", "No"} default button "Yes"
                    set Button_Returned to button returned of result
                    if Button_Returned = "Yes" then

                        say "Get to work!"


                        set T1 to minutes of (current date)

                        set T1s to seconds of (current date)


                        display dialog "Click when done." buttons {"Complete", "Cancel"} default button "Complete"
                        set Button_Returned to button returned of result

                        if Button_Returned = "Complete" then



                            set T2 to minutes of (current date)

                            set T2s to seconds of (current date)

                            set TT_ to ((T2 * 60) + T2s) - ((T1 * 60) + T1s)

                            say "that took you" & TT_ & "seconds to complete"
                            display dialog ProjectName & TaskName & NoteName buttons {"Complete", "Defer", "Cancel"} default button "Complete"
                            set Button_Returned to button returned of result
                            if Button_Returned = "Complete" then
                                mark complete ListItem
                                tell application "OmniFocus"
                                    compact default document
                                end tell
                            else if Button_Returned = "Defer" then
                                display dialog "Defer for how long (in minutes)?" default answer "60"
                                set TimeAdd to text returned of result
                                set defer date of ListItem to ((current date) + (TimeAdd * minutes))
                                tell application "OmniFocus"
                                    compact default document
                                end tell
                            else if Button_Returned = "Cancel" then
                                tell application "OmniFocus"
                                    compact default document
                                end tell
                            else if Button_Returned = "No" then
                                tell application "OmniFocus"
                                    compact default document
                                end tell
                            end if
                        else if Button_Returned = "No" then
                            display dialog "Breakdown task."

                            set perspective name to "Projects"


                        end if
                    end if
                end repeat
            end tell
        end tell
    end timeout
end run

Thanks in advance for any help.

1
Regular AppleScript can't really do it, but AppleScriptObjC can be used to create a display window or put a statusItem in the menu bar to show elapsed time. Is the timer just an honor kind of thing that you start/stop manually? - red_menace
Yes. It’s just to keep me accountable. I’m trying to break down tasks to small chunks. The timer gives me feedback to make sure I am succeeding and am focused on what I am supposed to be doing. - Will McLemore
I don't use OmniFocus, but looking at your script, it appears highly scriptable. As this sounds like something for personal use that would only be running whilst you are focussed on doing these tasks, it's not unreasonable to create a Stay Open app that idles in the background and polls every few seconds to check whether a particular task in your project list has been ticked off as complete in OmniFocus. Might be better than a dialog box ? - CJK
You can do this with a stay-open script application, even with vanilla AppleScript, though if you want bells and whistles you'll need to go to applescriptobjc. I'll post a basic example a bit later today. - Ted Wrigley

1 Answers

0
votes

I don't have OmniFocus on my machine, so I can't properly compile this much less test it, but in vanilla AppleScript you can do something like the following:

global start_time, end_time, TreeList, current_task_index, TaskName, NoteName

on run
    tell application "OmniFocus"
        tell default document to tell front document window
            set perspective name to "Daily Wrap-Up"
            tell content to set TreeList to (value of first leaf)
        end 
    end
    set current_task_index to 1
    beginTask()
end

on reopen
    -- inserted try block to aid debugging
    try
        set end_time to (current date)
        set elapsed_time to end_time -start_time
        say "that took you " & elapsed_time & " seconds to complete"
        display dialog ProjectName & TaskName & NoteName buttons {"Complete", "Defer", "Cancel"} default button "Complete"
        set Button_Returned to button returned of result
            if Button_Returned = "Complete" then
                mark complete ListItem
                tell application "OmniFocus"
                    compact default document
                end tell
            else if Button_Returned = "Defer" then
                display dialog "Defer for how long (in minutes)?" default answer "60"
                set TimeAdd to text returned of result
                set defer date of ListItem to ((current date) + (TimeAdd * minutes))
                tell application "OmniFocus"
                    compact default document
                end tell
            else if Button_Returned = "Cancel" then
                tell application "OmniFocus"
                    compact default document
                end tell
            else if Button_Returned = "No" then
                tell application "OmniFocus"
                    compact default document
                end tell
            end if
        else if Button_Returned = "No" then
            display dialog "Breakdown task."
            set perspective name to "Projects"
        end if
        set current_task_index to current_task_index + 1
        if current_task_index <= count of TreeList then
            beginTask()
        else
            quit
        end
    on error errstr number errnum
        display alert "Error " & errnum & ": " & errstr
    end try
end

on idle
    (*
        you can use this handler if you want the app to give you a countdown, or 
        announce a time limit, or anything that needs doing while you're working on the task
    *)
end

on beginTask()
    tell application "OmniFocus"
        tell default document to tell front document window
            set perspective name to "Daily Wrap-Up"
            set ListItem to item current_task_index of TreeList
            set ProjectName to name of containing project of ListItem as text
            set TaskName to " - " & name of ListItem
            set NoteName to " - " & note of ListItem
            display dialog "The task is:" & return & ProjectName & TaskName & NoteName & return & "Can you do this in 2 minutes or less?" buttons {"Yes", "No"} default button "Yes"
            set Button_Returned to button returned of result
            if Button_Returned = "Yes" then
                say "Get to work!"
                set start_time to (current date)
            end if
        end tell
    end tell
end

Copy this into the script editor, debug it, and save it as an application with the 'Stay open after run handler' checkbox checked. Operation is as follows:

  1. When OmniFocus is ready, run this script application. It will prompt you to begin the first task.
  2. When you have finished the first task, double-click the script application icon again to invoke the reopen handler. The script will present you with the elapsed time for the first task, give you the choices you outlined, and then prompt you to begin the second task.
  3. After the last task is complete, the script will automatically quit.

The global variable at the beginning allow necessary data to be passed between handlers as the script progresses.

If you want something more complex — e.g., a floating window or menu bar item that gives you more fine-grained control — then you'll need to start using ASOC to build that up. But that's fine-tuning; this should give you a general structure.