Update to Exporting OmniFocus to iThoughtsHD

In a recent post, I described some of the changes that I've been making to my core OmniFocus 2 Applescripts. This work happened to coincide with a shout out for help I saw on Twitter:

I knew I had a script that did this, but I hadn't used it in a while, so I dusted it off and looked at what changes needed to be made to run it against a current version of OmniFocus.

Origin Story

The original script came from work Rob Trew(@complexpoint) had done to get OmniFocus tasks in to a hierarchal OPML file format. 5 Rob took his work and built up an Applescript that would output active OmniFocus tasks into an iThoughts mind map. The script I have is a copy of the one that was originally posted to the OmniFocus forums by Rob Trew (GitHub copy here).

One part of the Applescript used to export OmniFocus to iThoughts, was that it used a Python script to do most of the work.

Since the Python script is what did most of the heavy lifting, that's what I wanted to focus on first.

Updates to the Original Version

Federico Viticci(@viticci], at MacStories, did a great write up about visualizing your OmniFocus tasks in a mind map. In his article, Federico did basically the same thing I've done and pulled out the Python script6 to convert his OmniFocus task list to an iThoughts mind map file. One part of Federico's article stood out to me:

So here's what I did. I got the Python script from the Resources inside the .scptd bundle. I moved the .py file to my Home directory alongside the map.itm template I'm using. In Hazel, I set up a "Run shell script" action that does the following:

python $HOME/ofoc_to_mindmap_018.py --format=itmz --output=$HOME/Dropbox/Maps/ActiveTasks -m map.itm -c '0'

That was more than I wanted to remember to run the script, so I cleaned up the need for so many switches to run the OmniFocus to iThoughts conversion. Some of the tweaks included:

  • Changing the default output format to iThoughts' .itmz file format.
  • Added a line to copy a base map.itm file from a dedicated location.
  • Updated the default file location for the exported mind map file to ~/Desktop.

The main change, from the original version, was telling the script where the OmniFocus 2 database was located. This starts on line 742 of the script:

def get_flat_omnifocus(var_root):
"""Read Omnifocus cache data into flat ordered list"""
# Where is the ofoc cache ?
ofoc_container = os.path.expanduser('~/Library/Containers/com.omnigroup.OmniFocus2')
if not os.path.exists(ofoc_container):
    ofoc_container = ofoc_container + '.MacAppStore'
ofoc = ofoc_container + '/Data/Library/Caches/com.omnigroup.OmniFocus2'
if not os.path.exists(ofoc):
     ofoc = ofoc + '.MacAppStore'

cache_db = ofoc + '/OmniFocusDatabase2'

A special thanks to Ken Case (@kcase) for giving me some guidance on the OmniFocus database changes from OmniFocus 1 to OmniFocus 2 for MAS vs direct purchase versions. 1

Getting OmniFocus to iThoughts HD

There are two files you will need to export your OmniFocus task list into iThoughts HD.

  1. OF_to_iThoughts_R25.py: This is the Python script that will read your OmniFocus database and convert the tasks, contexts and notes into an iThoughts mind map.
  2. map.itm: This is an uncompressed iThoughts map file that's used as a template to convert the OmniFocus tasks into a iThoughts mind map.

The OF_to_iThoughts_R25.py script can be stored anywhere. 3 The file/folder paths have been set up in the script to be relative to a User's home directory - e.g. ~/Desktop. The map.itm file needs to be stored in the ~/Library/Scripts/Applications/OmniFocus folder.2

Running the script

Once you've found a home for the script, locate the script's folder in a Terminal window and run the following command ./OF_to_iThoughts_R25.py. 4

This will run the Python script and put a copy of the mind map on to your Desktop.

From there you can just double click on the file and open it in iThoughts HD.

Now you can trim, modify, update, etc. your current task list in iThoughts HD as a mind map file.

Caveats to script

There are a couple of caveats you need to be aware of:

  1. This script was created against a version of OmniFocus purchased directly from Omni Group. The code in the script should take into account a Mac App Store version of OmniFocus. Since I only have the direct purchase version of OmniFocus, I'm not 100% sure it will work with MAS version.
  2. The default formatting of the iThoughts HD map that is generated by the script may not be to your tastes. You may have to play around with your own version of the map.itm file to get it the way you want it.
  3. As the notice says in the script, this script is provided 'as is'. It works for me and does everything I need it to. I may add new functionality in the future, but I don't have anything planned yet.
  4. If you're running Python 3 as your default Python version, I have no idea what will happen with the script.

Script Switches

The Python script originally had a set of optional switches you could run to make more specific conversions of your OmniFocus task list. Here is a list of the switches used in the script:

-h, --help
    show this help message and exit
-a ROOT, --root=ROOT  
    Specify a sub-tree by the OmniFocus id of its root node.
    Defaults to None.
-x FORMAT, --format=FORMAT
    Set the export format [itmz | itm | opml | txt | md | ft]. 
    Defaults to .itmz mind map. md is simple Markdown, 
    ft is Markdown with the addition of FoldingText's 
    .todo mode tags for checkboxes and struck-through done items
-o OUTPUT, --output=OUTPUT
    Set the export filepath.
    Defaults to file named Omnifocus_tasks + date
-c COLLAPSE, --collapse=COLLAPSE
    List the outline levels to collapse. Defaults to 2,4
-m TEMPLATE, --template=TEMPLATE
    The pathname of an .itm or .itmz template for
    iThoughtsHD. Defaults to same directory as script.
-l, --links
    Include OmniFocus task/folder links. Defaults to false
-n, --notes
    Include OmniFocus notes. Defaults to false
-r, --recurinfo
    Add any repetition information to start of notes.
    Defaults to false
    SQL clause[s] to limit which FOLDERS are exported.
    Defaults to effectiveActive=1
-s SINGLES_SQL, --singlelists=SINGLES_SQL
    SQL clause[s] to limit which SINGLE ACTION LISTS are exported. 
    Defaults to status=active, folderEffectiveActive=1, 
    dateCompleted is null
    SQL clause[s] to limit which PROJECTS are exported.
    Defaults to status=active, folderEffectiveActive=1,
    dateCompleted is null  
    Use a comma for AND (OR is not supported) 
    e.g. -p 'childrenCount > 0, blockedByFutureStartDate = 0'
-t TASK_SQL, --tasks=TASK_SQL
    SQL clause[s] to limit which TASKS are exported.
    Defaults to dateCompleted is null,
    SQL clause[s] to limit which INBOX TASKS are exported.
    Defaults to all inbox tasks

The sections in the Python script related to the switches used above hasn't been altered from the original version, so they appear to be working still as is. Your results may vary.

  1. I think the script works with MAS OmniFocus 2. 

  2. If you don't, then you need to update the script to know where the map.itm file has been saved.  

  3. I'm keeping my in the ~/Library/Scripts/Applications/OmniFocus folder. 

  4. If it doesn't work, you may need to chmod u+x the file again. 

  5. For OmniOutliner. 

  6. Do you sense a pattern here?