Commit afcf61cb authored by Bram Schoenmakers's avatar Bram Schoenmakers

Add preliminary support to grouping to the pretty printer

parent a6e3dc95
......@@ -24,7 +24,9 @@ from topydo.lib.Filter import HiddenTagFilter, InstanceFilter
from topydo.lib.printers.PrettyPrinter import pretty_printer_factory
from topydo.lib.prettyprinters.Format import PrettyPrinterFormatFilter
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.Sorter import Sorter
from topydo.lib.Utils import get_terminal_size
from topydo.lib.View import View
class ListCommand(ExpressionCommand):
......@@ -37,6 +39,7 @@ class ListCommand(ExpressionCommand):
self.printer = None
self.sort_expression = config().sort_string()
self.group_expression = config().group_string()
self.show_all = False
self.ids = None
self.format = config().list_format()
......@@ -55,7 +58,7 @@ class ListCommand(ExpressionCommand):
return True
def _process_flags(self):
opts, args = self.getopt('f:F:i:n:Ns:x')
opts, args = self.getopt('f:F:g:i:n:Ns:x')
for opt, value in opts:
if opt == '-x':
......@@ -81,6 +84,8 @@ class ListCommand(ExpressionCommand):
self.printer = None
elif opt == '-F':
self.format = value
elif opt == '-g':
self.group_expression = value
elif opt == '-N':
# 2 lines are assumed to be taken up by printing the next prompt
# display at least one item
......@@ -143,8 +148,17 @@ class ListCommand(ExpressionCommand):
self.printer = pretty_printer_factory(self.todolist, filters)
if self.group_expression:
self.out(self.printer.print_groups(self._view().groups))
else:
self.out(self.printer.print_list(self._view().todos))
def _view(self):
sorter = Sorter(self.sort_expression, self.group_expression)
filters = self._filters()
return View(sorter, filters, self.todolist)
def _N_lines(self):
''' Determine how many lines to print, such that the number of items
displayed will fit on the terminal (i.e one 'screen-ful' of items)
......
......@@ -92,6 +92,7 @@ class _Config:
'sort': {
'keep_sorted': '0',
'sort_string': 'desc:importance,due,desc:priority',
'group_string': '',
'ignore_weekends': '1',
},
......@@ -270,6 +271,9 @@ class _Config:
def sort_string(self):
return self.cp.get('sort', 'sort_string')
def group_string(self):
return self.cp.get('sort', 'group_string')
def ignore_weekends(self):
try:
return self.cp.getboolean('sort', 'ignore_weekends')
......
......@@ -34,13 +34,33 @@ 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 = lambda a: a.priority() or 'ZZ'
result = priority_key
elif p_field == 'context' or p_field == 'contexts':
result = lambda a: sorted([c.lower() for c in a.contexts()])
result = contexts_key
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.
......@@ -56,15 +76,14 @@ def get_field_function(p_field):
elif p_field == 'length':
result = lambda a: a.length()
elif p_field == 'project' or p_field == 'projects':
result = lambda a: sorted([c.lower() for c in a.projects()])
result = projects_key
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 = (lambda a: "0" + a.tag_value(p_field) if a.has_tag(p_field)
else "1")
result = get_tag_key
return result
......@@ -115,7 +134,11 @@ class Sorter(object):
return sorted_todos
def group(self, p_todos):
result = [([], self.sort(p_todos))]
"""
Groups the todos according to the given group string. Assumes that the
given todos have already been sorted with self.sort().
"""
result = [([], p_todos)]
for function, _ in self.groupfunctions:
oldresult = result
......
......@@ -38,3 +38,8 @@ class View(object):
result = _filter.filter(result)
return result
@property
def groups(self):
todos = self.todos
return self._sorter.group(self.todos)
......@@ -76,6 +76,15 @@ class PrettyPrinter(Printer):
"""
return [self.print_todo(todo) for todo in p_todos]
def print_groups(self, p_groups):
result = []
for key, todos in p_groups:
result.append(TopydoString(key))
result.append(TopydoString("\n===\n"))
result += self.print_list(todos)
return result
def pretty_printer_factory(p_todolist, p_additional_filters=None):
""" Returns a pretty printer suitable for the ls and dep subcommands. """
......
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