Commit 8650033b authored by Bram Schoenmakers's avatar Bram Schoenmakers

Introduce list format option.

The `ls` output can be customized with the list_format option in the
configuration, or the `-F` flag for `ls`.

Open issues:

* Relative dates to be implemented (see PR #52)
* Using (%p) without todo items without priority results in ()
* Ability to print todo on a single line (see PR #52)
parent bfe194a8
...@@ -15,6 +15,7 @@ auto_creation_date = 1 ...@@ -15,6 +15,7 @@ auto_creation_date = 1
hide_tags = id,p,ical hide_tags = id,p,ical
indent = 0 indent = 0
list_limit = -1 list_limit = -1
list_format = |%i| (%p) %s
[tags] [tags]
tag_start = t tag_start = t
......
...@@ -20,7 +20,8 @@ from topydo.lib.IcalPrinter import IcalPrinter ...@@ -20,7 +20,8 @@ from topydo.lib.IcalPrinter import IcalPrinter
from topydo.lib.JsonPrinter import JsonPrinter from topydo.lib.JsonPrinter import JsonPrinter
from topydo.lib.PrettyPrinter import pretty_printer_factory from topydo.lib.PrettyPrinter import pretty_printer_factory
from topydo.lib.PrettyPrinterFilter import (PrettyPrinterHideTagFilter, from topydo.lib.PrettyPrinterFilter import (PrettyPrinterHideTagFilter,
PrettyPrinterIndentFilter) PrettyPrinterIndentFilter,
PrettyPrinterFormatFilter)
class ListCommand(ExpressionCommand): class ListCommand(ExpressionCommand):
...@@ -34,6 +35,7 @@ class ListCommand(ExpressionCommand): ...@@ -34,6 +35,7 @@ class ListCommand(ExpressionCommand):
self.printer = None self.printer = None
self.sort_expression = config().sort_string() self.sort_expression = config().sort_string()
self.show_all = False self.show_all = False
self.format = config().list_format()
def _poke_icalendar(self): def _poke_icalendar(self):
""" """
...@@ -49,7 +51,7 @@ class ListCommand(ExpressionCommand): ...@@ -49,7 +51,7 @@ class ListCommand(ExpressionCommand):
return True return True
def _process_flags(self): def _process_flags(self):
opts, args = self.getopt('f:s:x') opts, args = self.getopt('f:F:s:x')
for opt, value in opts: for opt, value in opts:
if opt == '-x': if opt == '-x':
...@@ -64,6 +66,8 @@ class ListCommand(ExpressionCommand): ...@@ -64,6 +66,8 @@ class ListCommand(ExpressionCommand):
self.printer = IcalPrinter(self.todolist) self.printer = IcalPrinter(self.todolist)
else: else:
self.printer = None self.printer = None
elif opt == '-F':
self.format = value
self.args = args self.args = args
...@@ -81,6 +85,8 @@ class ListCommand(ExpressionCommand): ...@@ -81,6 +85,8 @@ class ListCommand(ExpressionCommand):
hidden_tags = config().hidden_tags() hidden_tags = config().hidden_tags()
filters = [] filters = []
filters.append(PrettyPrinterFormatFilter(self.todolist,
self.format))
filters.append(PrettyPrinterIndentFilter(indent)) filters.append(PrettyPrinterIndentFilter(indent))
filters.append(PrettyPrinterHideTagFilter(hidden_tags)) filters.append(PrettyPrinterHideTagFilter(hidden_tags))
......
...@@ -69,6 +69,7 @@ class _Config: ...@@ -69,6 +69,7 @@ class _Config:
'hide_tags': 'id,p,ical', 'hide_tags': 'id,p,ical',
'indent': '0', 'indent': '0',
'list_limit': '-1', 'list_limit': '-1',
'list_format': '|%i| (%p) %s',
}, },
'tags': { 'tags': {
...@@ -307,6 +308,11 @@ class _Config: ...@@ -307,6 +308,11 @@ class _Config:
return alias_dict return alias_dict
def list_format(self):
""" Returns the list format used by `ls` """
return self.cp.get('ls', 'list_format')
def config(p_path=None, p_overrides=None): def config(p_path=None, p_overrides=None):
""" """
Retrieve the config instance. Retrieve the config instance.
......
...@@ -125,3 +125,55 @@ class PrettyPrinterHideTagFilter(PrettyPrinterFilter): ...@@ -125,3 +125,55 @@ class PrettyPrinterHideTagFilter(PrettyPrinterFilter):
p_todo_str) p_todo_str)
return p_todo_str return p_todo_str
class PrettyPrinterFormatFilter(PrettyPrinterFilter):
def __init__(self, p_todolist, p_format=None):
super(PrettyPrinterFormatFilter, self).__init__()
self.todolist = p_todolist
self.format = p_format or config().list_format()
def filter(self, p_todo_str, p_todo):
placeholders = {
# absolute creation date
'c': lambda t: t.creation_date().isoformat() if t.creation_date() else '',
# relative creation date
'C': lambda t: '#', # TODO: humanized creation date
# absolute due date
'd': lambda t: t.due_date().isoformat() if t.due_date() else '',
# relative due date
'D': lambda t: '#', # TODO: humanized due date
# todo ID
'i': lambda t: str(self.todolist.number(t)),
# list of tags (spaces)
'K': lambda t: ' '.join(['{}:{}'.format(tag, value)
for tag, value in sorted(p_todo.tags())]),
# priority
'p': lambda t: t.priority() if t.priority() else '',
# text
's': lambda t: t.text(),
# absolute start date
't': lambda t: t.start_date().isoformat() if t.start_date() else '',
# relative start date
'T': lambda t: '#', # TODO: humanized start date
# literal %
'%': lambda _: '%',
}
p_todo_str = self.format
for placeholder, getter in placeholders.items():
p_todo_str = re.sub(r'%\[?{}\]?'.format(placeholder), getter(p_todo), p_todo_str)
return p_todo_str
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