Commit f423ed4e authored by Bram Schoenmakers's avatar Bram Schoenmakers

Handle items that should appear in more than one group

For example, when grouping by project, a todo item in two groups will be
added to each applicable project.
parent 185e08a6
......@@ -16,6 +16,7 @@
""" This module provides functionality to sort lists with todo items. """
from collections import OrderedDict
from itertools import groupby
import re
from datetime import date
......@@ -34,33 +35,14 @@ def get_field_function(p_field):
access that property. If the property could not be located, return the
identity function.
"""
def priority_key(p_todo):
priority = p_todo.priority()
return (priority or 'ZZ', priority or '')
def projects_key(p_todo):
projects = sorted(p_todo.projects())
return ([p.lower() for p in projects], ", ".join(projects))
def contexts_key(p_todo):
contexts = sorted(p_todo.contexts())
return ([p.lower() for p in contexts], ", ".join(contexts))
def get_tag_key(p_todo):
if p_todo.has_tag(p_field):
return ("0" + p_todo.tag_value(p_field), p_todo.tag_value(p_field))
else:
return ("1", "")
# default result
result = lambda a: a
if is_priority_field(p_field):
# assign dummy priority when a todo has no priority
result = priority_key
result = lambda a: a.priority() or 'ZZ'
elif p_field == 'context' or p_field == 'contexts':
result = contexts_key
result = lambda a: sorted([c.lower() for c in a.contexts()])
elif p_field == 'creationdate' or p_field == 'creation':
# when a task has no creation date, push it to the end by assigning it
# the maximum possible date.
......@@ -76,14 +58,15 @@ def get_field_function(p_field):
elif p_field == 'length':
result = lambda a: a.length()
elif p_field == 'project' or p_field == 'projects':
result = projects_key
result = lambda a: sorted([c.lower() for c in a.projects()])
elif p_field == 'text':
result = lambda a: a.text()
else:
# try to find the corresponding tag
# when a tag is not present, push it to the end of the list by giving
# it an artificially higher value
result = get_tag_key
result = (lambda a: "0" + a.tag_value(p_field) if a.has_tag(p_field)
else "1")
return result
......@@ -138,17 +121,25 @@ class Sorter(object):
Groups the todos according to the given group string. Assumes that the
given todos have already been sorted with self.sort().
"""
result = [([], p_todos)]
result = OrderedDict([((), p_todos)])
for function, _ in self.groupfunctions:
oldresult = result
result = []
for oldkey, oldgroup in oldresult:
result = OrderedDict()
for oldkey, oldgroup in oldresult.items():
for key, group in groupby(oldgroup, function):
newkey = oldkey + [key]
newgroup = list(group)
result.append((newkey, newgroup))
if not isinstance(key, list):
key = [key]
for subkey in key:
newkey = oldkey + (subkey,)
if newkey in result:
result[newkey] = result[newkey] + newgroup
else:
result[newkey] = newgroup
return result
......@@ -191,12 +182,12 @@ if __name__ == '__main__':
Todo('Foo +A @A type:a'),
Todo('Foo +A @B type:b'),
Todo('Bar +B @B type:b'),
Todo('Baz +A @B'),
Todo('Baz +A +B @B'),
]
s = Sorter('desc:context', 'project,type')
for key, group in s.group(todos):
for key, group in s.group(todos).items():
print(key)
for item2 in group:
print(item2.source())
......@@ -79,7 +79,7 @@ class PrettyPrinter(Printer):
def print_groups(self, p_groups):
result = []
for key, todos in p_groups:
for key, todos in p_groups.items():
result.append(TopydoString(''))
result.append(TopydoString(key))
result.append(TopydoString("==="))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment