Commit a66b9305 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge pull request #64 from mruwek/ls-format

Add customizable right alignment in list_format
parents c7959d3f 99b91fea
...@@ -31,11 +31,16 @@ setup( ...@@ -31,11 +31,16 @@ setup(
url = "https://github.com/bram85/topydo", url = "https://github.com/bram85/topydo",
install_requires = [ install_requires = [
'six >= 1.9.0', 'six >= 1.9.0',
'arrow', 'arrow >= 0.7.0',
], ],
extras_require = { extras_require = {
':sys_platform=="win32"': ['colorama>=0.2.5'], ':sys_platform=="win32"': ['colorama>=0.2.5'],
':python_version=="2.7"': ['ushlex'], # shutil.get_terminal_size() was introduced in Python 3.3
':python_version=="2.7"': [
'backports.shutil_get_terminal_size>=1.0.0',
'ushlex',
],
':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'],
'ical': ['icalendar'], 'ical': ['icalendar'],
'prompt-toolkit': ['prompt-toolkit >= 0.53'], 'prompt-toolkit': ['prompt-toolkit >= 0.53'],
'edit-cmd-tests': ['mock'], 'edit-cmd-tests': ['mock'],
......
...@@ -15,7 +15,7 @@ auto_creation_date = 1 ...@@ -15,7 +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| %x %{(}p{)} %c %s %k list_format = |%I| %x %{(}p{)} %c %s %k %{due:}d %{t:}t
[tags] [tags]
tag_start = t tag_start = t
...@@ -51,6 +51,7 @@ append_parent_contexts = 0 ...@@ -51,6 +51,7 @@ append_parent_contexts = 0
[aliases] [aliases]
;showall = ls -x ;showall = ls -x
;next = ls -n 1 ;next = ls -n 1
;top = ls -F '|%I| %x %p %S %k %{(}H{)}'
;lsproj = lsprj ;lsproj = lsprj
;listprj = lsprj ;listprj = lsprj
;listproj = lsprj ;listproj = lsprj
......
...@@ -24,9 +24,13 @@ from topydo.cli.CLIApplicationBase import CLIApplicationBase, error, usage ...@@ -24,9 +24,13 @@ from topydo.cli.CLIApplicationBase import CLIApplicationBase, error, usage
from topydo.cli.TopydoCompleter import TopydoCompleter from topydo.cli.TopydoCompleter import TopydoCompleter
from prompt_toolkit.shortcuts import prompt from prompt_toolkit.shortcuts import prompt
from prompt_toolkit.history import InMemoryHistory from prompt_toolkit.history import InMemoryHistory
from six import PY2
from topydo.lib.Config import config, ConfigError from topydo.lib.Config import config, ConfigError
if PY2:
import ushlex as shlex
# First thing is to poke the configuration and check whether it's sane # First thing is to poke the configuration and check whether it's sane
# The modules below may already read in configuration upon import, so # The modules below may already read in configuration upon import, so
# make sure to bail out if the configuration is invalid. # make sure to bail out if the configuration is invalid.
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.ExpressionCommand import ExpressionCommand from topydo.lib.ExpressionCommand import ExpressionCommand
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 (PrettyPrinterAlignFilter,
PrettyPrinterHideTagFilter,
PrettyPrinterIndentFilter, PrettyPrinterIndentFilter,
PrettyPrinterFormatFilter) PrettyPrinterFormatFilter)
...@@ -92,6 +93,7 @@ class ListCommand(ExpressionCommand): ...@@ -92,6 +93,7 @@ class ListCommand(ExpressionCommand):
filters = [] filters = []
filters.append(PrettyPrinterFormatFilter(self.todolist, filters.append(PrettyPrinterFormatFilter(self.todolist,
self.format)) self.format))
filters.append(PrettyPrinterAlignFilter())
filters.append(PrettyPrinterIndentFilter(indent)) filters.append(PrettyPrinterIndentFilter(indent))
filters.append(PrettyPrinterHideTagFilter(hidden_tags)) filters.append(PrettyPrinterHideTagFilter(hidden_tags))
......
...@@ -74,7 +74,7 @@ class _Config: ...@@ -74,7 +74,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| %x %{(}p{)} %c %s %k', 'list_format': '|%I| %x %{(}p{)} %c %s %k %{due:}d %{t:}t',
}, },
'tags': { 'tags': {
......
...@@ -52,3 +52,36 @@ def humanize_dates(p_due=None, p_start=None, p_creation=None): ...@@ -52,3 +52,36 @@ def humanize_dates(p_due=None, p_start=None, p_creation=None):
dates_list.append('starts in ' + start) dates_list.append('starts in ' + start)
return ', '.join(dates_list) return ', '.join(dates_list)
def strip_placeholder_braces(p_matchobj):
"""
Returns string with conditional braces around placeholder stripped and
percent sign glued into placeholder character.
Returned string is composed from 'start', 'before', 'placeholder', 'after',
'whitespace', and 'end' match-groups of p_matchobj. Conditional braces are
stripped from 'before' and 'after' groups. 'whitespace', 'start', and 'end'
groups are preserved without any change.
Using this function as an 'repl' argument in re.sub it is possible to turn:
%{(}B{)}
into:
(%B)
"""
try:
before = p_matchobj.group('before').strip('{}')
except AttributeError:
before = ''
placeholder = p_matchobj.group('placeholder')
try:
after = p_matchobj.group('after').strip('{}')
except AttributeError:
after = ''
whitespace = p_matchobj.group('whitespace') or ''
start = p_matchobj.group('start') or ''
end = p_matchobj.group('end') or ''
return start + before + '%' + placeholder + after + whitespace + end
...@@ -23,7 +23,8 @@ from six import u ...@@ -23,7 +23,8 @@ from six import u
from topydo.lib.Colors import NEUTRAL_COLOR, Colors from topydo.lib.Colors import NEUTRAL_COLOR, Colors
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.ListFormat import filler, humanize_date, humanize_dates from topydo.lib.ListFormat import (filler, humanize_date, humanize_dates,
strip_placeholder_braces)
from topydo.lib.Utils import get_terminal_size from topydo.lib.Utils import get_terminal_size
...@@ -162,15 +163,14 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter): ...@@ -162,15 +163,14 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter):
# todo ID pre-filled with 1 or 2 spaces if its length is <3 # todo ID pre-filled with 1 or 2 spaces if its length is <3
placeholders['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) without due: and t: # list of tags (spaces) without hidden ones and due: and t:
placeholders['k'] = lambda t: ' '.join([u('{}:{}').format(tag, value) placeholders['k'] = lambda t: ' '.join([u('{}:{}').format(tag, value)
for tag, value in sorted(p_todo.tags()) if 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() + [config().tag_start(), config().tag_due()]])
# list of tags (spaces) # list of all tags (spaces)
placeholders['K'] = lambda t: ' '.join([u('{}:{}').format(tag, value) placeholders['K'] = lambda t: ' '.join([u('{}:{}').format(tag, value)
for tag, value in sorted(p_todo.tags()) if for tag, value in sorted(p_todo.tags())])
tag not in config().hidden_tags()])
# priority # priority
placeholders['p'] = lambda t: t.priority() if t.priority() else '' placeholders['p'] = lambda t: t.priority() if t.priority() else ''
...@@ -205,41 +205,49 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter): ...@@ -205,41 +205,49 @@ class PrettyPrinterFormatFilter(PrettyPrinterFilter):
r'%(?P<before>{{.+?}})?' r'%(?P<before>{{.+?}})?'
r'(?P<placeholder>{ph}|\[{ph}\])' r'(?P<placeholder>{ph}|\[{ph}\])'
r'(?P<after>{{.+?}})?' r'(?P<after>{{.+?}})?'
r'(?P<whitespace>\s)*' r'(?P<whitespace> *)'
r'(?P<end>.*)').format(ph=placeholder) r'(?P<end>.*)').format(ph=placeholder)
match = re.match(pattern, p_todo_str) match = re.match(pattern, p_todo_str)
if match: if match:
if repl == '': if repl == '':
p_todo_str = re.sub(pattern, match.group('start') + match.group('end'), p_todo_str) p_todo_str = re.sub(pattern, match.group('start') + match.group('end'), p_todo_str)
else: else:
def strip_braces(p_matchobj):
try:
before = p_matchobj.group('before').strip('{}')
except AttributeError:
before = ''
placeholder = p_matchobj.group('placeholder')
try:
after = p_matchobj.group('after').strip('{}')
except AttributeError:
after = ''
whitespace = p_matchobj.group('whitespace') or '' p_todo_str = re.sub(pattern, strip_placeholder_braces, p_todo_str)
start = p_matchobj.group('start') or ''
end = p_matchobj.group('end') or ''
return start + before + '%' + placeholder + after + whitespace + end
p_todo_str = re.sub(pattern, strip_braces, p_todo_str)
p_todo_str = re.sub(r'%({ph}|\[{ph}\])'.format(ph=placeholder), repl, p_todo_str) p_todo_str = re.sub(r'%({ph}|\[{ph}\])'.format(ph=placeholder), repl, p_todo_str)
p_todo_str = p_todo_str.rstrip() p_todo_str = p_todo_str.rstrip()
if placeholder == 'S': if placeholder == 'S':
line_width = get_terminal_size().columns -1 p_todo_str = re.sub(' *\t *', '\t', p_todo_str)
if len(p_todo_str) > line_width: line_width = get_terminal_size().columns
text_lim = line_width - len(p_todo_str) - 3 if len(p_todo_str) >= line_width:
text_lim = line_width - len(p_todo_str) - 4
p_todo_str = re.sub(re.escape(repl), repl[:text_lim] + '...', p_todo_str) p_todo_str = re.sub(re.escape(repl), repl[:text_lim] + '...', p_todo_str)
return p_todo_str # cut trailing space left when last placeholder in p_todo_str is empty and its predecessor is not
return p_todo_str.rstrip()
class PrettyPrinterAlignFilter(PrettyPrinterFilter):
"""
Final make-up for todo item line.
Currently it only provides right alignment from place specified in
list_format config-option (subsitutes tab-character with as many spaces as
it is needed to fill the whole line).
"""
def __init__(self):
super(PrettyPrinterAlignFilter, self).__init__()
def filter(self, p_todo_str, _):
tab = re.search('.*\t', p_todo_str)
if tab:
line_width = get_terminal_size().columns
to_fill = line_width - len(p_todo_str)
if to_fill > 0:
p_todo_str = re.sub('\t', ' '*to_fill, p_todo_str)
elif to_fill <= 0:
p_todo_str = re.sub('\t', ' ', 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