On Sep 2, 8:30 pm, Joe <Mr.Joe.Hew
...@gmail.com> wrote:
> Have anyone figured out a simple way to tag my tiddlers before
> importing into a new monkeyGTD?
I migrated from d-cubed to MonkeyGTD a while ago using the script
below. It worked well enough for me, but you might want to check your
actions and projects nevertheless. At this point let me thank both Tom
and Simon for their work. Although I decided to go (back!) to
MonkeyGTD, d-cubed has also worked well for me.
Bye, Patrick
#! /usr/bin/python
#
# D3 -> MonkeyGTD migration.
# Steps done by this script:
# -> realm 'Work' or 'Personal' as part of tags
# gtd.project='foo bar' -> tags='[[foo bar]]'
# gtd.contect='@waiting' -> tags='[[Waiting For]]'
# gtd.context='foo bar' -> tags=[[foo bar]]'
# action[-archive] -> Action [Next]
# project[-archive] -> Project [Active]
# context -> Context
# done -> Done
# reference -> Reference
#
# Usage:
# - check the CUSTOMIZE parts of the script
# - d3tomgtd.py <d3.html >body.html
# - review body.html
# - import after <div id="storeArea">
# - in browser:
# - Review/Mismatched Realms
# - turn actions with reminders into ticklers
# - "Work/Next & Waiting Actions" -> assign person and context to
waiting actions
import sys
import re
import xml
import xml.dom
import xml.dom.DOMImplementation
import xml.dom.NodeFilter
from xml.dom.ext.reader import Sax2
# create Reader object
reader = Sax2.Reader()
# parse the document
doc = reader.fromStream(sys.stdin)
# D3 project task lists
listentry = re.compile(r'''<<gtdAction.*?>> *\n?|^\.\..+\|.+\n?''',
re.MULTILINE)
# print all tiddlers after transformation to Monkey GTD format
walker = doc.createTreeWalker(doc.documentElement,
xml.dom.NodeFilter.NodeFilter.SHOW_ELEMENT, None, 0)
while 1:
if walker.currentNode.tagName == 'div':
# figure out whether the element is a tiddler based on tags
isTiddler = False
tags = walker.currentNode.getAttribute('tags').split()
for tag in tags:
if tag in ['action', 'action-archive', 'project', 'project-
archive' 'reference', 'context']:
isTiddler = True
break
if isTiddler:
newtags = []
isWork = False
isAction = False
isProject = False
# rename tags (capitalize), check whether we have an
action tiddler
for tag in tags:
if tag in ('action', 'action-archive', 'project',
'project-archive', 'context', 'done'):
active = True
if tag.endswith('-archive'):
active = False
tag = tag.replace('-archive', '')
if tag == 'action':
isAction = True
elif tag == 'project':
isProject = True
if active:
newtags.append('Active')
chars = list(tag)
tag = ''.join([chars[0].upper()] + chars[1:])
newtags.append(tag)
elif tag in ('someday', 'unfiled'):
# CUSTOMIZE: ignore tags which have no further
meaning in MonkeyGTD
pass
else:
# preserve tag unchanged
newtags.append(tag)
# modify a clone of the current tiddler
clone = walker.currentNode.cloneNode(True)
# convert information from special attributes into tags
for gtdtag in ('gtd.context', 'gtd.project'):
attr = clone.getAttribute(gtdtag)
if attr:
clone.removeAttribute(gtdtag)
if gtdtag == 'gtd.context' and attr == '@waiting':
newtags.append('[[Waiting For]]')
elif ' ' in attr:
newtags.append("[[%s]]" % attr)
else:
newtags.append(attr)
# set realm based on context
if gtdtag == 'gtd.context' and attr in '@work':
isWork = True
# actions require a realm to be displayed
# and one of 'Done', 'Next', '[[Waiting For]]'
if isAction:
# CUSTOMIZE: actions are in the 'Work' realm if they
are done in the context @work
if isWork:
newtags.append('Work')
else:
newtags.append('Personal')
if not 'Done' in newtags and \
not '[[Waiting For]]' in newtags:
newtags.append('Next')
elif isProject:
# CUSTOMIZE: all projects are personal by default
newtags.append('Personal')
# remove obsolete attributes
clone.removeAttribute('gtd.projectindex')
# set modified tags
clone.setAttribute('tags', ' '.join(newtags))
# clean up tiddler text
textwalker = doc.createTreeWalker(clone,
xml.dom.NodeFilter.NodeFilter.SHOW_ELEMENT|
xml.dom.NodeFilter.NodeFilter.SHOW_TEXT, None, 0)
while 1:
if textwalker.currentNode.nodeType ==
textwalker.currentNode.TEXT_NODE:
data = textwalker.currentNode.data
# CUSTOMIZE: strip task timer footer (didn't use
it in the end)
data = data.replace(r'''----
|//Description//|//Date//|//Started//|//Stopped//|//Elapsed//|
|/%tasktimer%/|||||
|total||||<<columncalc sum 1 -1>>|''', '')
# strip D3 action lists from body
data = listentry.sub('', data)
data = data.strip()
textwalker.currentNode.data = data
nexttext = textwalker.nextNode()
if nexttext is None: break
xml.dom.ext.PrettyPrint(clone)
elif walker.currentNode.tagName == 'pre' and \
walker.currentNode.parentNode.tagName == 'div':
pass
# print walker.currentNode, walker.currentNode.firstChild
next = walker.nextNode()
if next is None: break