Skip to content
Michael Butscher edited this page Jan 23, 2021 · 1 revision

WikidPad and Getting Things Done

Getting Things Done is a personal information management system described by '''David Allen''' in his books "Getting Things Done: The Art of Stress-Free Productivity" and "Ready for Anything: 52 Productivity Principles for Work and Life". Some of the main points are to remain flexible and to keep things simple. In these two issues WikidPad can help you.

  • Flexibility with WikiWord automatic linking
  • Simplicity with free-format text entry

Beware, not compatible with 1.6beta

Just so that no-one else wastes an hour or two trying to get these scripts working with 1.6beta - work is needed especially with the interface to the editor to make it work properly with 1.6beta.

Next Actions by Erik Neumann

  • Create '''user_extensions''' directory under your WikidPad directory
  • Copy there "WikidPadHooks.py" and "WikiSyntax.py" from '''extensions''' directory
  • Never edit original files in '''extensions''', only copies in '''user_extensions''' directory
  • Create '''NextActions''' and '''WaitingFor''' pages in your wiki
  • Edit '''WikiSyntax.py''' file: add '''wait''' into ToDoRE, ToDoREWithContent and ToDoREWithCapturing lists
  • Edit '''WikidPadHooks.py''' file: add following script into '''openedWikiWord''' function
  • '''CLOSE AND RESTART''' WikidPad to activate the changes
#!python
def openedWikiWord(wikidPad, wikiWord):
    if wikiWord == "NextActions":
        # editor = wikidPad.editor
        editor = wikidPad.getActiveEditor()
        todos = wikidPad.wikiData.getTodos()
        todos.sort()
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Actions from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        for todo in todos:
          if str(todo[1]).startswith("todo"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")
    elif wikiWord == "WaitingFor":
        # editor = wikidPad.editor
        editor = wikidPad.getActiveEditor()
        todos = wikidPad.wikiData.getTodos()
        todos.sort()
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Collected from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        for todo in todos:
          if str(todo[1]).startswith("wait"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")        

Possible Problems

Make sure your python code indentation is correct

Next Actions (Take Two) -- <icosahedral at gmail dot com>

Thanks Eric! I've edited the above function to organize by context instead of by project name. If you were to enter an entry as "todo.work", it will now show up under a header entry of "@work". Forgive the code, I'm new to python. (Although -- now that I've played with it -- I do see the appeal!)

#!python
def openedWikiWord(wikidPad, wikiWord):
    if wikiWord == "NextActions":
        # editor = wikidPad.editor
        editor = wikidPad.getActiveEditor()
        todos = wikidPad.wikiData.getTodos()
        todos.sort(key=lambda x:x[1])
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Actions from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        pt = re.compile('todo\.(.+?):')
	context1t = "."
        for todo in todos:
          context2t = context1t
          mt = pt.search(str(todo[1]))
          if mt != None:
            context1t = mt.group(1)
          if context1t != context2t:
            editor.AddText("\n++ @")
            editor.AddText(context1t)
            editor.AddText("\n")
          if str(todo[1]).startswith("todo"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")
    elif wikiWord == "WaitingFor":
        # editor = wikidPad.editor
        editor = wikidPad.getActiveEditor()
        todos = wikidPad.wikiData.getTodos()
        todos.sort(key=lambda x:x[1])
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Collected from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        pw = re.compile('wait\.(.+?):')
	context1w = "."
        for todo in todos:
          context2w = context1w
          mw = pw.search(str(todo[1]))
          if mw != None:
            context1w = mw.group(1)
          if context1w != context2w:
            editor.AddText("\n++ @")
            editor.AddText(context1w)
            editor.AddText("\n")
          if str(todo[1]).startswith("wait"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")  

Is there a non programmer solution ?

I just do not know where to put "wait" in the python file exactly. Wikipad is giving a syntax error.

The location for the added "wait"

I'm new to WikidPad and Python too, but I think it should be added like here:

ToDoREWithContent = re.compile .... ... (?:todo|done|wait|action|track|issue|question|project|wait)(?:\.[^:\s]+)?)"

A small fix: No need to add 'wait' twice (Reinhard Engel):

ToDoREWithContent = re.compile .... ... (?:todo|done|wait|action|track|issue|question|project)(?:\.[^:\s]+)?)"

One more fix

I had to add

import pwiki.srePersistent as re

in the begining of WikidPadHooks.py

Mods from Mike Crowe

Email me at mike at mikeandkellycrowe dot com

I based mine to get categories on SortedTodos. Breaks up by tags, which is what I wanted. ''Notes'':

  • For dumb people like me, make sure you put it in __openedWikiWord__ and not ''openWikiWord''. Big Difference ;)
  • This is compatible with 1.7a.
  • In your main page, enter a link of ![Todo] to activate Code:
#!python
def openedWikiWord(wikidPad, wikiWord):
    """
    Called when a new or existing wiki word was opened successfully.

    wikiWord -- name of the wiki word to create
    """
    if wikiWord.upper().startswith("TODO"):
        # tags contains the (Tag, TagHeader) pairs - customize the list of sort categories here:
        # TagHeaders are the descriptive headings that will be shown for each category.
        tags = [('High','Tagged HIGH !'),
                ('_spec.SPACER',''),
                ('Next','Next Actions'),
                ('ThisWeek','Tagged for This Week'),
                ('_spec.SPACER',''),
                ('SomeDay','SomeDay / Maybe'),
                ('_spec.SPACER',''),
                ('TimeToTime','Tagged for from time to time'),
                ('_spec.SPACER',''),
                ('Low','Tagged as LOW'),
                ('_spec.SPACER',''),
                ('VeryLow','Tagged as Very LOW')]
        
        # MikeCrowe -- Untagged always at end of list
        tagEnd = [
                ('_spec.SPACER',''),
                ('_spec.NOTAGS','Untagged Todos')]


        srchstr = wikiWord[4:]
    
        # get all todos with 'todo' in them to seperate list to be used here:
        todosFull = wikidPad.wikiData.getTodos()
        todos = [todo for todo in todosFull if 'todo' in todo[1] ] # and srchstr in todo[1]) ]

        #clean the page code - and insert the harvested todos after placemark = '++ auto-harvested todos:'
        editor = wikidPad.getActiveEditor()
        st = editor.FindText(0, editor.GetLength(), "++ auto-harvested todos:", 0)
        st = editor.PositionFromLine(1+editor.LineFromPosition(st))
        editor.SetSelection(st, editor.GetLength())
        editor.ReplaceSelection("\n")

        # handle the page by displaying all keywords with srchstr  -> list all todos :
        tagAdded = True    #used to stop two spacers in a row
        checkTags = [tag[0] for tag in tags]

        # MikeCrowe -- code to search for tags not in above list and automatically add
        for todo in todos:
            allTodo = todo[1].split(":")
            words = allTodo[0].split(".")
            for word in words[1:]:
                if word not in checkTags:
                    tags.append( ("_spec.SPACER","") )
                    tags.append( (word,"Tagged "+word) )
                    checkTags.append(word)
        tags += tagEnd

        for tag in tags:
            wroteHeader = False   #used to make sure that header is written only once - in a non-empty category
            
            # handle special tag '_spec.SPACER' by writing SPACERs in the tag list:
            if tag[0] == '_spec.SPACER' and tagAdded:
                editor.AddText('\n' + ('-'*70) + '\n')
                tagAdded = False
    
            # handle special NOTAG in the tag list
            # This displays all untagged todos   :
            elif tag[0] != '_spec.NOTAGS':
                for todo in todos:
                    if tag[0] in todo[1]:
                        if not wroteHeader:
                            editor.AddText('\n++ ' + tag[1] + ' :\n')
                            wroteHeader = True
                        s = str(todo[1])
                        editor.AddText(' * '+ str(todo[0]) + ': '+  s[s.find(':')+1:] + '\n')
                        todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                        tagAdded = True
            # handle normal Tags - write the todos for that tag:
            else:
                for todo in todos:
                    foundTag = False
                    for t in tags:
                        if t[0] in todo[1]:
                            foundTag = True
                            break
                        
                    if not foundTag and todo[0] != 'DEL':
                        if not wroteHeader:
                            editor.AddText('\n++ ' + tag[1] + ' :\n')
                            wroteHeader = True
                            s = str(todo[1])
                            editor.AddText(' * '+ str(todo[0]) + ': '+  s[s.find(':')+1:] + '\n')

                        todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                        tagAdded = True

Adding Default Icon

I learned quickly using the above script, that since the page is dynamically created every time you open it, any icon assigned to distinguish it disappears.

I added the following line to the end of the above script:

        editor.AddText('[icon: eye]')

This adds my preferred icon back into the tree view to assist me in distinguishing it. (It's simple, but it took me longer than it should have to figure out where to locate it, not knowing Python.)

Fix for Mike's Code

As far as I see the following snippet of the code above:

#!python
                    if not foundTag and todo[0] != 'DEL':
                        if not wroteHeader:
                            editor.AddText('\n++ ' + tag[1] + ' :\n')
                            wroteHeader = True
                            s = str(todo[1])
                            editor.AddText(' * '+ str(todo[0]) + ': '+  s[s.find(':')+1:] + '\n')

                        todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                        tagAdded = True

should read like this (fixed indention for 2 lines):

#!python
                    if not foundTag and todo[0] != 'DEL':
                        if not wroteHeader:
                            editor.AddText('\n++ ' + tag[1] + ' :\n')
                            wroteHeader = True
                        s = str(todo[1])
                        editor.AddText(' * '+ str(todo[0]) + ': '+  s[s.find(':')+1:] + '\n')

                        todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                        tagAdded = True

to list all untagged todos and not only the first one.

Another idea for Mike's code

Add color to different tags. for example if you define:

#!python
        tags = [
                ('Tickler','Things to Remember','#0000ff'),
                ('_spec.SPACER',''),
                ('Active','Active - On Work Now','#ff00ff'),
                ('_spec.SPACER',''),
                ('Next','Next Actions','#ff0000'),
                ('_spec.SPACER',''),
                ('Highest','HIGHEST Priority!!!','#cc0000'),
                ('_spec.SPACER','',''),
                ('High','HIGH Priority!','#800000'),
                ('_spec.SPACER','',''),
                ('ThisWeek','Tasks for This Week','#808000'),
                ('_spec.SPACER','',''),
                ('Later','To be done Later','#008080'),
                ('_spec.SPACER','',''),
                ('TimeToTime','To be Done from time to time',''),
                ('_spec.SPACER','',''),
                ('Low','LOW Priority',''),
                ('_spec.SPACER','',''),
                ('VeryLow','Lowest Priority',''),
                ('_spec.SPACER','',''),
                ('SomeDay','SomeDay / Maybe','')
                ]

you can change Mike's code as follows:

#!python
            elif tag[0] != '_spec.NOTAGS':
                addedColor=0
                for todo in todos:
                    if tag[0] in todo[1]:
                        if not wroteHeader:
                            if len(tag)>2 and tag[2] != '':
                                addedColor=1
                                editor.AddText("\n<font color="+tag[2]+">\n")
                            editor.AddText('\n++ ' + tag[1] + ' :\n')
                            wroteHeader = True
                        s = str(todo[1])
                        s1=s[:s.find(':')]
                        s1=re.sub(r'(todo|Active|Highest|High|Next|ThisWeek|Later|SomeDay|TimeToTime|Low|VeryLow|Tickler).','',s1)
                        editor.AddText(' * '+ s1+ ' -> [' +str(todo[0]) + ']: ' +  s[s.find(':')+1:] + '\n')
                        todos[todos.index(todo)] = ('DEL','DEL') #marks that todo to be ignored
                        tagAdded = True
                if addedColor:
                    editor.AddText("\n</font>\n")
                    addedColor=0

and you'll get your different priorities colored...

would somebody put up everything here into downloadable files for dummies to easily download the files instead wrong editing that cause more troubles. tia.

Version that's compatible with v1.9beta17

#!python
def openedWikiWord(docPagePresenter, wikiWord):
    if wikiWord == "NextActions":
        # editor = wikidPad.editor
        editor = docPagePresenter.getActiveEditor()
        wikiData = docPagePresenter.getWikiDocument().getWikiData()
        todos = wikiData.getTodos()
        todos.sort()
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Actions from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        for todo in todos:
          if str(todo[1]).startswith("todo"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")
    elif wikiWord == "WaitingFor":
        # editor = wikidPad.editor
        editor = docPagePresenter.getActiveEditor()
        wikiData = docPagePresenter.getWikiDocument().getWikiData()
        todos = wikiData.getTodos()
        todos.sort()
        #FindText returns start position or -1 if not found
        s = editor.FindText(0, editor.GetLength(), "+++Collected from projects:", 0)
        s = editor.PositionFromLine(1+editor.LineFromPosition(s))
        editor.SetSelection(s, editor.GetLength())
        editor.ReplaceSelection("\n")
        for todo in todos:
          if str(todo[1]).startswith("wait"):   # filter out others (like done:)  should not include 5th char = ':'
            editor.AddText(str(todo[0]))
            editor.AddText("  ")
            editor.AddText(str(todo[1])[5:])
            editor.AddText("\n")        

Be efficient with wikipad

I wrote 2 articles to this day about GTD and the use of wikipad : [http://simplicityroad.livejournal.com The main page of the blog] | [http://simplicityroad.livejournal.com/730.html Article on wikipad] | [http://simplicityroad.livejournal.com/970.html Article about the GTD inbox]

Clone this wiki locally