Commit 06a7f892 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Turn the pretty printer into a class.

This allows for other printer implementations, where a printer is a
transformation from a Todo item to a string.
parent fbb21562
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -21,7 +21,7 @@ import re
from topydo.lib.Config import config
from topydo.lib.Command import Command
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.RelativeDate import relative_date_to_date
from topydo.lib.TodoListBase import InvalidTodoException
......@@ -93,7 +93,9 @@ class AddCommand(Command):
self.todo = self.todolist.add(self.text)
self._postprocess_input_todo()
self.out(pretty_print(self.todo, [self.todolist.pp_number()]))
self.out(
self.printer.print_todo(self.todo,
[PrettyPrinterNumbers(self.todolist)]))
else:
self.error(self.usage())
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.TodoListBase import InvalidTodoException
class AppendCommand(Command):
......@@ -37,7 +37,9 @@ class AppendCommand(Command):
if text:
todo = self.todolist.todo(number)
self.todolist.append(todo, text)
self.out(pretty_print(todo, [self.todolist.pp_number()]))
self.out(self.printer.print_todo(todo,
[PrettyPrinterNumbers(self.todolist)]))
else:
self.error(self.usage())
except InvalidCommandArgument:
......
......@@ -16,6 +16,8 @@
import getopt
from topydo.lib.PrettyPrinter import PrettyPrinter
class InvalidCommandArgument(Exception):
pass
......@@ -49,6 +51,9 @@ class Command(object):
self.error = p_err
self.prompt = p_prompt
# make pretty printer available
self.printer = PrettyPrinter()
def execute(self):
"""
Execute the command. Intercepts the help subsubcommand to show the help
......
......@@ -17,7 +17,7 @@
import re
from topydo.lib.Command import Command
from topydo.lib.PrettyPrinter import pretty_print, pretty_print_list
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.TodoListBase import InvalidTodoException
class DCommand(Command):
......@@ -72,8 +72,8 @@ class DCommand(Command):
)
def _print_list(self, p_todos):
filters = [self.todolist.pp_number()]
self.out("\n".join(pretty_print_list(p_todos, filters)))
filters = [PrettyPrinterNumbers(self.todolist)]
self.out("\n".join(self.printer.print_list(p_todos, filters)))
def prompt_text(self):
return "Yes or no? [y/N] "
......@@ -93,7 +93,7 @@ class DCommand(Command):
if not self.force and re.match('^y(es)?$', confirmation, re.I):
for child in children:
self.execute_specific_core(child)
self.out(self.prefix() + pretty_print(child))
self.out(self.prefix() + self.printer.print_todo(child))
def _print_unlocked_todos(self, p_old, p_new):
delta = [todo for todo in p_new if todo not in p_old]
......
......@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.DCommand import DCommand
from topydo.lib.PrettyPrinter import pretty_print
class DeleteCommand(DCommand):
def __init__(self, p_args, p_todolist,
......@@ -35,7 +34,7 @@ class DeleteCommand(DCommand):
self.todolist.delete(p_todo)
def execute_specific(self, p_todo):
self.out(self.prefix() + pretty_print(p_todo))
self.out(self.prefix() + self.printer.print_todo(p_todo))
self.execute_specific_core(p_todo)
def usage(self):
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.TodoListBase import InvalidTodoException
class DepriCommand(Command):
......@@ -37,7 +36,7 @@ class DepriCommand(Command):
if todo.priority() != None:
self.todolist.set_priority(todo, None)
self.out("Priority removed.")
self.out(pretty_print(todo))
self.out(self.printer.print_todo(todo))
except InvalidCommandArgument:
self.error(self.usage())
except (InvalidTodoException):
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -17,7 +17,7 @@
from datetime import date
from topydo.lib.DCommand import DCommand
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.Recurrence import advance_recurring_todo, strict_advance_recurring_todo
from topydo.lib.Utils import date_string_to_date
......@@ -56,7 +56,8 @@ class DoCommand(DCommand):
self.completion_date)
self.todolist.add_todo(new_todo)
self.out(pretty_print(new_todo, [self.todolist.pp_number()]))
self.out(self.printer.print_todo(new_todo,
[PrettyPrinterNumbers(self.todolist)]))
def prompt_text(self):
return "Also mark subtasks as done? [y/N] "
......@@ -77,7 +78,7 @@ class DoCommand(DCommand):
""" Actions specific to this command. """
self._handle_recurrence(p_todo)
self.execute_specific_core(p_todo)
self.out(self.prefix() + pretty_print(p_todo))
self.out(self.prefix() + self.printer.print_todo(p_todo))
def execute_specific_core(self, p_todo):
"""
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -19,7 +19,7 @@ import re
from topydo.lib.Command import Command
from topydo.lib.Config import config
from topydo.lib import Filter
from topydo.lib.PrettyPrinter import pp_indent
from topydo.lib.PrettyPrinterFilter import PrettyPrinterIndentFilter
from topydo.lib.Sorter import Sorter
class ListCommand(Command):
......@@ -83,7 +83,8 @@ class ListCommand(Command):
sorter = Sorter(self.sort_expression)
filters = self._filters()
pp_filters = [pp_indent(config().list_indent())]
indent = config().list_indent()
pp_filters = [PrettyPrinterIndentFilter(indent)]
self.out(self.todolist.view(sorter, filters).pretty_print(pp_filters))
def usage(self):
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -18,7 +18,7 @@ from datetime import date, timedelta
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.Config import config
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.RelativeDate import relative_date_to_date
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.Utils import date_string_to_date
......@@ -75,7 +75,8 @@ class PostponeCommand(Command):
todo.set_tag(config().tag_due(), new_due.isoformat())
self.todolist.set_dirty()
self.out(pretty_print(todo, [self.todolist.pp_number()]))
self.out(self.printer.print_todo(todo,
[PrettyPrinterNumbers(self.todolist)]))
else:
self.error("Invalid date pattern given.")
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -14,75 +14,54 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" Provides a function to pretty print a list of todo items. """
import re
from topydo.lib.Config import config
PRIORITY_COLORS = {
'A': '\033[36m', # cyan
'B': '\033[33m', # yellow
'C': '\033[34m' # blue
}
PROJECT_COLOR = '\033[31m' # red
NEUTRAL_COLOR = '\033[0m'
def pp_color(p_todo_str, p_todo):
class Printer(object):
"""
Adds colors to the todo string by inserting ANSI codes.
An abstract class that turns todo items into strings.
Should be passed as a filter in the filter list of pretty_print()
Subclasses must at least implement the print_todo method.
"""
if config().colors():
color = NEUTRAL_COLOR
try:
color = PRIORITY_COLORS[p_todo.priority()]
except KeyError:
pass
p_todo_str = color + p_todo_str + NEUTRAL_COLOR
if config().highlight_projects_contexts():
p_todo_str = re.sub(
r'\B(\+|@)(\S*\w)',
PROJECT_COLOR + r'\g<0>' + color,
p_todo_str)
p_todo_str += NEUTRAL_COLOR
return p_todo_str
def pp_indent(p_indent=0):
return lambda s, t: ' ' * p_indent + s
def pretty_print(p_todo, p_filters=None):
def print_todo(self, p_todo):
""" Base implementation. Simply returns the string conversion. """
return str(p_todo)
def print_list(self, p_todos):
"""
Given a list of todo items, pretty print it and return a list of
formatted strings.
"""
return [self.print_todo(todo) for todo in p_todos]
class PrettyPrinter(Printer):
"""
Given a todo item, pretty print it and return a list of formatted strings.
Prints todo items on a single line, decorated by the filters passed by
the caller.
p_filters is a list of functions that transform the output string, each
function accepting two arguments:
The caller can adjust the output by passing on a set of filters, that may
add colors, indentation, etc. These filters are found in the
PrettyPrinterFilter module.
"""
def print_todo(self, p_todo, p_filters=None):
"""
Given a todo item, pretty print it.
* the todo's text that has to be modified;
* the todo object itself which allows for obtaining relevant information.
p_filters is a list of PrettyPrinterFilter objects (typically
subclasses of it, see PrettyPrinterFilter module)
"""
p_filters = p_filters or []
Example is pp_color in this fle.
"""
p_filters = p_filters or []
todo_str = str(p_todo)
todo_str = str(p_todo)
for ppf in p_filters:
todo_str = ppf.filter(todo_str, p_todo)
for f in p_filters:
todo_str = f(todo_str, p_todo)
return todo_str
return todo_str
def print_list(self, p_todos, p_filters=None):
"""
Given a list of todo items, pretty print it and return a list of
formatted strings.
def pretty_print_list(p_todos, p_filters=None):
"""
Given a list of todo items, pretty print it and return a list of
formatted strings.
"""
p_filters = p_filters or []
return [pretty_print(todo, p_filters) for todo in p_todos]
This override also passes on filters.
"""
p_filters = p_filters or []
return [self.print_todo(todo, p_filters) for todo in p_todos]
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" Provides filters used for pretty printing. """
import re
from topydo.lib.Config import config
class PrettyPrinterFilter(object):
"""
Base class for a pretty printer filter.
Subclasses must reimplement the filter method.
"""
def filter(self, p_todo_str, _):
""" Default implementation returns an unmodified todo string. """
return p_todo_str
PRIORITY_COLORS = {
'A': '\033[36m', # cyan
'B': '\033[33m', # yellow
'C': '\033[34m' # blue
}
PROJECT_COLOR = '\033[31m' # red
NEUTRAL_COLOR = '\033[0m'
class PrettyPrinterColorFilter(PrettyPrinterFilter):
"""
Adds colors to the todo string by inserting ANSI codes.
Should be passed as a filter in the filter list of pretty_print()
"""
def filter(self, p_todo_str, p_todo):
""" Applies the colors. """
if config().colors():
color = NEUTRAL_COLOR
try:
color = PRIORITY_COLORS[p_todo.priority()]
except KeyError:
pass
p_todo_str = color + p_todo_str + NEUTRAL_COLOR
if config().highlight_projects_contexts():
p_todo_str = re.sub(
r'\B(\+|@)(\S*\w)',
PROJECT_COLOR + r'\g<0>' + color,
p_todo_str)
p_todo_str += NEUTRAL_COLOR
return p_todo_str
class PrettyPrinterIndentFilter(PrettyPrinterFilter):
""" Adds indentation to the todo item. """
def __init__(self, p_indent=0):
super(PrettyPrinterIndentFilter, self).__init__()
self.indent = p_indent
def filter(self, p_todo_str, _):
""" Applies the indentation. """
return ' ' * self.indent + p_todo_str
class PrettyPrinterNumbers(PrettyPrinterFilter):
""" Prepends the todo's number, retrieved from the todolist. """
def __init__(self, p_todolist):
super(PrettyPrinterNumbers, self).__init__()
self.todolist = p_todolist
def filter(self, p_todo_str, p_todo):
""" Prepends the number to the todo string. """
return "|{:>3}| {}".format(self.todolist.number(p_todo), p_todo_str)
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.PrettyPrinter import pretty_print
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.Utils import is_valid_priority
......@@ -48,7 +47,7 @@ class PriorityCommand(Command):
elif not old_priority:
self.out("Priority set to {}.".format(priority))
self.out(pretty_print(todo))
self.out(self.printer.print_todo(todo))
else:
self.error("Invalid priority given.")
except InvalidCommandArgument:
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -15,8 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.PrettyPrinter import pretty_print
class TagCommand(Command):
def __init__(self, p_args, p_todolist,
......@@ -60,7 +60,8 @@ class TagCommand(Command):
self.value = ""
def _print(self):
self.out(pretty_print(self.todo, [self.todolist.pp_number()]))
filters = [PrettyPrinterNumbers(self.todolist)]
self.out(self.printer.print_todo(self.todo, filters))
def _choose(self):
"""
......
......@@ -24,7 +24,7 @@ import re
from topydo.lib.Config import config
from topydo.lib import Filter
from topydo.lib.HashListValues import hash_list_values
from topydo.lib.PrettyPrinter import pretty_print_list
from topydo.lib.PrettyPrinter import PrettyPrinter
from topydo.lib.Todo import Todo
from topydo.lib.View import View
......@@ -242,14 +242,6 @@ class TodoListBase(object):
except (ValueError, KeyError):
raise InvalidTodoException
def pp_number(self):
"""
A filter for the pretty printer to append the todo number to the
printed todo.
"""
return lambda p_todo_str, p_todo: \
"|{:>3}| {}".format(self.number(p_todo), p_todo_str)
def _update_todo_ids(self):
# the idea is to have a hash that is independent of the position of the
# todo. Use the text (without tags) of the todo to keep the id as stable
......@@ -264,5 +256,6 @@ class TodoListBase(object):
self._id_todo_map[uid] = todo
def __str__(self):
return '\n'.join(pretty_print_list(self._todos))
printer = PrettyPrinter()
return '\n'.join(printer.print_list(self._todos))
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -16,7 +16,11 @@
""" A view is a list of todos, sorted and filtered. """
from topydo.lib.PrettyPrinter import pretty_print_list, pp_color
from topydo.lib.PrettyPrinterFilter import (
PrettyPrinterColorFilter,
PrettyPrinterNumbers
)
from topydo.lib.PrettyPrinter import PrettyPrinter
class View(object):
"""
......@@ -29,6 +33,7 @@ class View(object):
self._viewdata = []
self._sorter = p_sorter
self._filters = p_filters
self._printer = PrettyPrinter()
self.update()
......@@ -45,8 +50,14 @@ class View(object):
def pretty_print(self, p_pp_filters=None):
""" Pretty prints the view. """
p_pp_filters = p_pp_filters or []
pp_filters = [self._todolist.pp_number(), pp_color] + p_pp_filters
return '\n'.join(pretty_print_list(self._viewdata, pp_filters))
pp_filters = [
PrettyPrinterNumbers(self._todolist),
PrettyPrinterColorFilter()
]
pp_filters += p_pp_filters
return '\n'.join(self._printer.print_list(self._viewdata, pp_filters))
def __str__(self):
return '\n'.join(pretty_print_list(self._viewdata))
return '\n'.join(self._printer.print_list(self._viewdata))
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