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 @@ ...@@ -16,6 +16,7 @@
""" This module provides functionality to sort lists with todo items. """ """ This module provides functionality to sort lists with todo items. """
from collections import OrderedDict
from itertools import groupby from itertools import groupby
import re import re
from datetime import date from datetime import date
...@@ -34,33 +35,14 @@ def get_field_function(p_field): ...@@ -34,33 +35,14 @@ def get_field_function(p_field):
access that property. If the property could not be located, return the access that property. If the property could not be located, return the
identity function. 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 # default result
result = lambda a: a result = lambda a: a
if is_priority_field(p_field): if is_priority_field(p_field):
# assign dummy priority when a todo has no priority # 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': 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': elif p_field == 'creationdate' or p_field == 'creation':
# when a task has no creation date, push it to the end by assigning it # when a task has no creation date, push it to the end by assigning it
# the maximum possible date. # the maximum possible date.
...@@ -76,14 +58,15 @@ def get_field_function(p_field): ...@@ -76,14 +58,15 @@ def get_field_function(p_field):
elif p_field == 'length': elif p_field == 'length':
result = lambda a: a.length() result = lambda a: a.length()
elif p_field == 'project' or p_field == 'projects': 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': elif p_field == 'text':
result = lambda a: a.text() result = lambda a: a.text()
else: else:
# try to find the corresponding tag # try to find the corresponding tag
# when a tag is not present, push it to the end of the list by giving # when a tag is not present, push it to the end of the list by giving
# it an artificially higher value # 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 return result
...@@ -138,17 +121,25 @@ class Sorter(object): ...@@ -138,17 +121,25 @@ class Sorter(object):
Groups the todos according to the given group string. Assumes that the Groups the todos according to the given group string. Assumes that the
given todos have already been sorted with self.sort(). given todos have already been sorted with self.sort().
""" """
result = [([], p_todos)] result = OrderedDict([((), p_todos)])
for function, _ in self.groupfunctions: for function, _ in self.groupfunctions:
oldresult = result oldresult = result
result = [] result = OrderedDict()
for oldkey, oldgroup in oldresult: for oldkey, oldgroup in oldresult.items():
for key, group in groupby(oldgroup, function): for key, group in groupby(oldgroup, function):
newkey = oldkey + [key]
newgroup = list(group) 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 return result
...@@ -191,12 +182,12 @@ if __name__ == '__main__': ...@@ -191,12 +182,12 @@ if __name__ == '__main__':
Todo('Foo +A @A type:a'), Todo('Foo +A @A type:a'),
Todo('Foo +A @B type:b'), Todo('Foo +A @B type:b'),
Todo('Bar +B @B type:b'), Todo('Bar +B @B type:b'),
Todo('Baz +A @B'), Todo('Baz +A +B @B'),
] ]
s = Sorter('desc:context', 'project,type') s = Sorter('desc:context', 'project,type')
for key, group in s.group(todos): for key, group in s.group(todos).items():
print(key) print(key)
for item2 in group: for item2 in group:
print(item2.source()) print(item2.source())
...@@ -79,7 +79,7 @@ class PrettyPrinter(Printer): ...@@ -79,7 +79,7 @@ class PrettyPrinter(Printer):
def print_groups(self, p_groups): def print_groups(self, p_groups):
result = [] result = []
for key, todos in p_groups: for key, todos in p_groups.items():
result.append(TopydoString('')) result.append(TopydoString(''))
result.append(TopydoString(key)) result.append(TopydoString(key))
result.append(TopydoString("===")) 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