Commit 4cd1fbbc authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge pull request #62 from mruwek/ls-format-S

Add %S - truncated version of %s
parents bb126f00 64c57dbc
......@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import shlex
from six import iteritems
from six.moves import configparser
......@@ -301,7 +302,7 @@ class _Config:
alias_dict = dict()
for alias, meaning in aliases:
meaning = meaning.split()
meaning = shlex.split(meaning)
real_subcommand = meaning[0]
alias_args = meaning[1:]
alias_dict[alias] = (real_subcommand, alias_args)
......
......@@ -29,3 +29,26 @@ def humanize_date(p_datetime):
now = arrow.now()
date = now.replace(day=p_datetime.day, month=p_datetime.month, year=p_datetime.year)
return date.humanize()
def humanize_dates(p_due=None, p_start=None, p_creation=None):
"""
Returns string with humanized versions of p_due, p_start and p_creation.
Examples:
- all dates: "16 days ago, due in a month, started 2 days ago"
- p_due and p_start: "due in a month, started 2 days ago"
- p_creation and p_due: "16 days ago, due in a month"
"""
dates_list = []
if p_creation:
dates_list.append(humanize_date(p_creation))
if p_due:
dates_list.append('due ' + humanize_date(p_due))
if p_start:
now = arrow.now().date()
start = humanize_date(p_start)
if p_start <= now:
dates_list.append('started ' + start)
else:
dates_list.append('starts in ' + start)
return ', '.join(dates_list)
......@@ -18,11 +18,13 @@
import re
from collections import OrderedDict
from six import u
from topydo.lib.Colors import NEUTRAL_COLOR, Colors
from topydo.lib.Config import config
from topydo.lib.ListFormat import filler, humanize_date
from topydo.lib.ListFormat import filler, humanize_date, humanize_dates
from topydo.lib.Utils import get_terminal_size
class PrettyPrinterFilter(object):
......@@ -135,53 +137,62 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter):
self.format = p_format or config().list_format()
def filter(self, p_todo_str, p_todo):
placeholders = {
placeholders = OrderedDict()
# absolute creation date
'c': lambda t: t.creation_date().isoformat() if t.creation_date() else '',
placeholders['c'] = lambda t: t.creation_date().isoformat() if t.creation_date() else ''
# relative creation date
'C': lambda t: humanize_date(t.creation_date()) if t.creation_date() else '',
placeholders['C'] = lambda t: humanize_date(t.creation_date()) if t.creation_date() else ''
# absolute due date
'd': lambda t: t.due_date().isoformat() if t.due_date() else '',
placeholders['d'] = lambda t: t.due_date().isoformat() if t.due_date() else ''
# relative due date
'D': lambda t: humanize_date(t.due_date()) if t.due_date() else '',
placeholders['D'] = lambda t: humanize_date(t.due_date()) if t.due_date() else ''
# relative dates: due, start
placeholders['h'] = lambda t: humanize_dates(t.due_date(), t.start_date())
# relative dates in form: creation, due, start
placeholders['H'] = lambda t: humanize_dates(t.due_date(), t.start_date(), t.creation_date())
# todo ID
'i': lambda t: str(self.todolist.number(t)),
placeholders['i'] = lambda t: str(self.todolist.number(t))
# todo ID pre-filled with 1 or 2 spaces if its length is <3
'I': lambda t: filler(str(self.todolist.number(t)), 3),
placeholders['I'] = lambda t: filler(str(self.todolist.number(t)), 3)
# list of tags (spaces)
'K': lambda t: ' '.join([u('{}:{}').format(tag, value)
# list of tags (spaces) without due: and t:
placeholders['k'] = lambda t: ' '.join([u('{}:{}').format(tag, value)
for tag, value in sorted(p_todo.tags()) if
tag not in config().hidden_tags()]),
tag not in config().hidden_tags() + [config().tag_start(), config().tag_due()]])
# list of tags (spaces) without due: and t:
'k': lambda t: ' '.join([u('{}:{}').format(tag, value)
# list of tags (spaces)
placeholders['K'] = lambda t: ' '.join([u('{}:{}').format(tag, value)
for tag, value in sorted(p_todo.tags()) if
tag not in config().hidden_tags() + [config().tag_start(), config().tag_due()]]),
tag not in config().hidden_tags()])
# priority
'p': lambda t: t.priority() if t.priority() else '',
placeholders['p'] = lambda t: t.priority() if t.priority() else ''
# text
's': lambda t: t.text(),
placeholders['s'] = lambda t: t.text()
# absolute start date
't': lambda t: t.start_date().isoformat() if t.start_date() else '',
placeholders['t'] = lambda t: t.start_date().isoformat() if t.start_date() else ''
# relative start date
'T': lambda t: humanize_date(t.start_date()) if t.start_date() else '',
placeholders['T'] = lambda t: humanize_date(t.start_date()) if t.start_date() else ''
# completed
'x': lambda t: 'x ' + t.completion_date().isoformat() if t.is_completed() else '',
placeholders['x'] = lambda t: 'x ' + t.completion_date().isoformat() if t.is_completed() else ''
# literal %
'%': lambda _: '%',
}
placeholders['%'] = lambda _: '%'
# text (truncated if necessary)
placeholders['S'] = lambda t: t.text()
p_todo_str = self.format
......@@ -219,6 +230,13 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter):
p_todo_str = re.sub(pattern, strip_braces, p_todo_str)
p_todo_str = re.sub(r'%{}'.format(placeholder), repl, p_todo_str)
p_todo_str = p_todo_str.rstrip()
return p_todo_str.rstrip()
if placeholder == 'S':
line_width = get_terminal_size().columns -1
if len(p_todo_str) > line_width:
text_lim = line_width - len(p_todo_str) - 3
p_todo_str = re.sub(re.escape(repl), repl[:text_lim] + '...', p_todo_str)
return p_todo_str
......@@ -19,6 +19,8 @@ Various utility functions.
"""
import re
from collections import namedtuple
from datetime import date
......@@ -51,3 +53,25 @@ def escape_ansi(p_string):
return escape_ansi.pattern.sub('', p_string)
escape_ansi.pattern = re.compile(r'\x1b[^m]*m')
def get_terminal_size():
"""
Try to determine terminal size at run time. If that is not possible,
returns the default size of 80x24.
"""
try:
from shutil import get_terminal_size # pylint: disable=no-name-in-module
except ImportError:
from backports.shutil_get_terminal_size import get_terminal_size
try:
sz = get_terminal_size()
except ValueError:
"""
This can result from the 'underlying buffer being detached', which
occurs during running the unittest on Windows (but not on Linux?)
"""
terminal_size = namedtuple('Terminal_Size', 'columns lines')
sz = terminal_size((80, 24))
return sz
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