Commit 751105ea authored by Bram Schoenmakers's avatar Bram Schoenmakers

Fixed pylint errors

Among others, moved methods by turning them into (inline) functions or
static methods.
parent e276dcd5
from setuptools import setup, find_packages
import os import os
import re import re
import codecs import codecs
import sys
here = os.path.abspath(os.path.dirname(__file__)) from setuptools import setup, find_packages
_HERE = os.path.abspath(os.path.dirname(__file__))
def read(*parts): def read(*parts):
# intentionally *not* adding an encoding option to open # intentionally *not* adding an encoding option to open
return codecs.open(os.path.join(here, *parts), 'r').read() return codecs.open(os.path.join(_HERE, *parts), 'r').read()
def find_version(*file_paths): def find_version(*file_paths):
...@@ -24,17 +24,17 @@ WATCHDOG = 'watchdog >= 0.8.3' ...@@ -24,17 +24,17 @@ WATCHDOG = 'watchdog >= 0.8.3'
ICALENDAR = 'icalendar' ICALENDAR = 'icalendar'
setup( setup(
name = "topydo", name="topydo",
packages = find_packages(exclude=["test"]), packages=find_packages(exclude=["test"]),
version = find_version('topydo', 'lib', 'Version.py'), version=find_version('topydo', 'lib', 'Version.py'),
description = "A powerful todo.txt application for the console", description="A powerful todo.txt application for the console",
author = "Bram Schoenmakers", author="Bram Schoenmakers",
author_email = "bram@topydo.org", author_email="bram@topydo.org",
url = "https://www.topydo.org", url="https://www.topydo.org",
install_requires = [ install_requires=[
'arrow >= 0.7.0', 'arrow >= 0.7.0',
], ],
extras_require = { extras_require={
':sys_platform=="win32"': ['colorama>=0.2.5'], ':sys_platform=="win32"': ['colorama>=0.2.5'],
':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'], ':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'],
'columns': ['urwid >= 1.3.0', WATCHDOG], 'columns': ['urwid >= 1.3.0', WATCHDOG],
...@@ -43,10 +43,10 @@ setup( ...@@ -43,10 +43,10 @@ setup(
'test': ['coverage>=4.3', 'freezegun', 'green', ICALENDAR, 'pylint>=1.7.1'], 'test': ['coverage>=4.3', 'freezegun', 'green', ICALENDAR, 'pylint>=1.7.1'],
'test:python_version=="3.2"': ['mock'], 'test:python_version=="3.2"': ['mock'],
}, },
entry_points= { entry_points={
'console_scripts': ['topydo = topydo.ui.UILoader:main'], 'console_scripts': ['topydo=topydo.ui.UILoader:main'],
}, },
classifiers = [ classifiers=[
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
"Environment :: Console", "Environment :: Console",
"Intended Audience :: End Users/Desktop", "Intended Audience :: End Users/Desktop",
...@@ -60,7 +60,7 @@ setup( ...@@ -60,7 +60,7 @@ setup(
"Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Utilities", "Topic :: Utilities",
], ],
long_description = """\ long_description="""\
topydo is a powerful and customizable todo.txt application for the console, inspired by the todo.txt CLI by Gina Trapani. topydo is a powerful and customizable todo.txt application for the console, inspired by the todo.txt CLI by Gina Trapani.
Highlights of the additional features it provides: Highlights of the additional features it provides:
...@@ -74,5 +74,5 @@ Highlights of the additional features it provides: ...@@ -74,5 +74,5 @@ Highlights of the additional features it provides:
* Some conveniences when adding new items (e.g. adding creation date and use relative dates) * Some conveniences when adding new items (e.g. adding creation date and use relative dates)
""", """,
test_suite = "test", test_suite="test",
) )
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import unittest
from unittest import skip
from test.topydo_testcase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
...@@ -167,7 +166,7 @@ class ConfigTest(TopydoTest): ...@@ -167,7 +166,7 @@ class ConfigTest(TopydoTest):
def test_config28(self): def test_config28(self):
""" test duplicates. """ """ test duplicates. """
keymap, keystates = config("test/data/ConfigTest7.conf").column_keymap() keymap, _ = config("test/data/ConfigTest7.conf").column_keymap()
self.assertEqual(keymap['k'], 'bar') self.assertEqual(keymap['k'], 'bar')
self.assertEqual(keymap['z'], 'foobar') self.assertEqual(keymap['z'], 'foobar')
......
...@@ -100,18 +100,17 @@ class DoCommandTest(CommandTest): ...@@ -100,18 +100,17 @@ class DoCommandTest(CommandTest):
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
def test_do_subtasks_force1(self): def test_do_subtasks_force1(self):
prompt_shown = False
def prompt(p_prompt): def prompt(p_prompt):
global prompt_shown prompt.prompt_shown = True
prompt_shown = True
prompt.prompt_shown = False
command = DoCommand(["-f", "1"], self.todolist, self.out, self.error, command = DoCommand(["-f", "1"], self.todolist, self.out, self.error,
prompt) prompt)
command.execute() command.execute()
command.execute_post_archive_actions() command.execute_post_archive_actions()
self.assertFalse(prompt_shown) self.assertFalse(prompt.prompt_shown)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertFalse(self.todolist.todo(2).is_completed()) self.assertFalse(self.todolist.todo(2).is_completed())
......
...@@ -27,7 +27,7 @@ from topydo.lib.Config import config, ConfigError ...@@ -27,7 +27,7 @@ from topydo.lib.Config import config, ConfigError
class GetSubcommandTest(TopydoTest): class GetSubcommandTest(TopydoTest):
def test_normal_cmd(self): def test_normal_cmd(self):
args = ["add"] args = ["add"]
real_cmd, final_args = get_subcommand(args) real_cmd, _ = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, AddCommand)) self.assertTrue(issubclass(real_cmd, AddCommand))
def test_cmd_help(self): def test_cmd_help(self):
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import unittest
from datetime import date, timedelta from datetime import date
from freezegun import freeze_time from freezegun import freeze_time
from test.topydo_testcase import TopydoTest from test.topydo_testcase import TopydoTest
......
...@@ -35,6 +35,9 @@ class DoCommand(DCommand): ...@@ -35,6 +35,9 @@ class DoCommand(DCommand):
super().__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.condition = lambda todo: not todo.is_completed()
self.condition_failed_text = "Todo has already been completed."
def get_flags(self): def get_flags(self):
""" Additional flags. """ """ Additional flags. """
opts, long_opts = super().get_flags() opts, long_opts = super().get_flags()
...@@ -75,15 +78,6 @@ class DoCommand(DCommand): ...@@ -75,15 +78,6 @@ class DoCommand(DCommand):
def prefix(self): def prefix(self):
return "Completed: " return "Completed: "
def condition(self, p_todo):
"""
An additional condition whether execute_specific should be executed.
"""
return not p_todo.is_completed()
def condition_failed_text(self):
return "Todo has already been completed."
def execute_specific(self, p_todo): def execute_specific(self, p_todo):
""" Actions specific to this command. """ """ Actions specific to this command. """
self._handle_recurrence(p_todo) self._handle_recurrence(p_todo)
......
...@@ -44,11 +44,11 @@ class EditCommand(MultiCommand): ...@@ -44,11 +44,11 @@ class EditCommand(MultiCommand):
def get_flags(self): def get_flags(self):
return ("dE:", []) return ("dE:", [])
def process_flag(self, p_opt, p_value): def process_flag(self, p_option, p_value):
if p_opt == '-d': if p_option == '-d':
self.edit_archive = True self.edit_archive = True
self.multi_mode = False self.multi_mode = False
elif p_opt == '-E': elif p_option == '-E':
self.editor = shlex.split(p_value) self.editor = shlex.split(p_value)
def _process_flags(self): def _process_flags(self):
...@@ -71,9 +71,10 @@ class EditCommand(MultiCommand): ...@@ -71,9 +71,10 @@ class EditCommand(MultiCommand):
return f return f
def _todos_from_temp(self, p_temp_file): @staticmethod
f = codecs.open(p_temp_file.name, encoding='utf-8') def _todos_from_temp(p_temp_file):
todos = f.read().splitlines() with codecs.open(p_temp_file.name, encoding='utf-8') as temp:
todos = temp.read().splitlines()
todo_objs = [] todo_objs = []
for todo in todos: for todo in todos:
...@@ -112,7 +113,7 @@ class EditCommand(MultiCommand): ...@@ -112,7 +113,7 @@ class EditCommand(MultiCommand):
orig_mtime = _get_file_mtime(temp_todos) orig_mtime = _get_file_mtime(temp_todos)
if not self._open_in_editor(temp_todos.name): if not self._open_in_editor(temp_todos.name):
new_todos = self._todos_from_temp(temp_todos) new_todos = EditCommand._todos_from_temp(temp_todos)
if _is_edited(orig_mtime, temp_todos): if _is_edited(orig_mtime, temp_todos):
for todo in self.todos: for todo in self.todos:
......
...@@ -90,7 +90,7 @@ class ListCommand(ExpressionCommand): ...@@ -90,7 +90,7 @@ class ListCommand(ExpressionCommand):
elif opt == '-N': elif opt == '-N':
# 2 lines are assumed to be taken up by printing the next prompt # 2 lines are assumed to be taken up by printing the next prompt
# display at least one item # display at least one item
self.limit = self._N_lines() self.limit = ListCommand._N_lines()
elif opt == '-n': elif opt == '-n':
try: try:
self.limit = int(value) self.limit = int(value)
...@@ -164,7 +164,8 @@ class ListCommand(ExpressionCommand): ...@@ -164,7 +164,8 @@ class ListCommand(ExpressionCommand):
return View(sorter, filters, self.todolist) return View(sorter, filters, self.todolist)
def _N_lines(self): @staticmethod
def _N_lines():
''' Determine how many lines to print, such that the number of items ''' 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) displayed will fit on the terminal (i.e one 'screen-ful' of items)
...@@ -176,13 +177,13 @@ class ListCommand(ExpressionCommand): ...@@ -176,13 +177,13 @@ class ListCommand(ExpressionCommand):
Otherwise, it looks for a newline ('\n') in the environmental variable Otherwise, it looks for a newline ('\n') in the environmental variable
PS1. PS1.
''' '''
lines_in_prompt = 1 # prompt is assumed to take up one line, even lines_in_prompt = 1 # prompt is assumed to take up one line, even
# without any newlines in it # without any newlines in it
if "win32" in sys.platform: if "win32" in sys.platform:
lines_in_prompt += 1 # Windows will typically print a free line after lines_in_prompt += 1 # Windows will typically print a free line after
# the program output # the program output
a = re.findall('\$_', os.getenv('PROMPT', '')) a = re.findall(r'\$_', os.getenv('PROMPT', ''))
lines_in_prompt += len(a) lines_in_prompt += len(a)
else: else:
a = re.findall('\\n', os.getenv('PS1', '')) a = re.findall('\\n', os.getenv('PS1', ''))
......
...@@ -37,8 +37,8 @@ class PostponeCommand(MultiCommand): ...@@ -37,8 +37,8 @@ class PostponeCommand(MultiCommand):
def get_flags(self): def get_flags(self):
return("s", []) return("s", [])
def process_flag(self, p_opt, p_value): def process_flag(self, p_option, p_value):
if p_opt == '-s': if p_option == '-s':
self.move_start_date = True self.move_start_date = True
def _execute_multi_specific(self): def _execute_multi_specific(self):
......
...@@ -43,11 +43,11 @@ def get_backup_path(): ...@@ -43,11 +43,11 @@ def get_backup_path():
class ChangeSet(object): class ChangeSet(object):
""" Class for operations related with backup management. """ """ Class for operations related with backup management. """
def __init__(self, p_todolist=None, p_archive=None, p_label=[]): def __init__(self, p_todolist=None, p_archive=None, p_label=None):
self.todolist = deepcopy(p_todolist) self.todolist = deepcopy(p_todolist)
self.archive = deepcopy(p_archive) self.archive = deepcopy(p_archive)
self.timestamp = str(int(time.time())) self.timestamp = str(int(time.time()))
self.label = ' '.join(p_label) self.label = ' '.join(p_label if p_label else [])
try: try:
self.json_file = open(get_backup_path(), 'r+b') self.json_file = open(get_backup_path(), 'r+b')
......
...@@ -36,13 +36,14 @@ class DCommand(MultiCommand): ...@@ -36,13 +36,14 @@ class DCommand(MultiCommand):
self.force = False self.force = False
self._delta = [] self._delta = []
self.condition = lambda _: True
self.condition_failed_text = ""
def get_flags(self): def get_flags(self):
return ("f", ["force"]) return ("f", ["force"])
def process_flag(self, p_opt, p_value): def process_flag(self, p_option, p_value):
if p_opt == "-f" or p_opt == "--force": if p_option == "-f" or p_option == "--force":
self.force = True self.force = True
def _uncompleted_children(self, p_todo): def _uncompleted_children(self, p_todo):
...@@ -93,15 +94,6 @@ class DCommand(MultiCommand): ...@@ -93,15 +94,6 @@ class DCommand(MultiCommand):
return [todo for todo in self.todolist.todos() return [todo for todo in self.todolist.todos()
if not self._uncompleted_children(todo) and todo.is_active()] if not self._uncompleted_children(todo) and todo.is_active()]
def condition(self, _):
"""
An additional condition whether execute_specific should be executed.
"""
return True
def condition_failed_text(self):
raise NotImplementedError
def execute_specific(self, _): def execute_specific(self, _):
raise NotImplementedError raise NotImplementedError
...@@ -120,7 +112,7 @@ class DCommand(MultiCommand): ...@@ -120,7 +112,7 @@ class DCommand(MultiCommand):
self._process_subtasks(todo) self._process_subtasks(todo)
self.execute_specific(todo) self.execute_specific(todo)
else: else:
self.error(self.condition_failed_text()) self.error(self.condition_failed_text)
current_active = self._active_todos() current_active = self._active_todos()
self._delta = [todo for todo in current_active self._delta = [todo for todo in current_active
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from topydo.lib import Filter from topydo.lib import Filter
from topydo.lib.Command import Command from topydo.lib.Command import Command
from topydo.lib.Config import config from topydo.lib.Config import config
......
...@@ -205,7 +205,7 @@ class ListFormatParser(object): ...@@ -205,7 +205,7 @@ class ListFormatParser(object):
'T': lambda t: humanize_date(t.start_date()) if t.start_date() else '', 'T': lambda t: humanize_date(t.start_date()) if t.start_date() else '',
# unique text ID # unique text ID
'u': lambda t: self.todolist.uid(t), 'u': self.todolist.uid,
# unique text ID, padded with spaces # unique text ID, padded with spaces
'U': lambda t: _filler(self.todolist.uid(t), 'U': lambda t: _filler(self.todolist.uid(t),
......
...@@ -148,9 +148,81 @@ class Sorter(object): ...@@ -148,9 +148,81 @@ class Sorter(object):
""" """
def __init__(self, p_sortstring="desc:priority", p_groupstring=""): def __init__(self, p_sortstring="desc:priority", p_groupstring=""):
self.groupfunctions = self._parse(p_groupstring, p_group=True) if p_groupstring else [] def parse(p_string, p_group):
self.pregroupfunctions = self._parse(p_groupstring, p_group=False) if p_groupstring else [] """
self.sortfunctions = self._parse(p_sortstring, p_group=False) Parses a sort/group string and returns a list of functions and the
desired order.
"""
def get_field_function(p_field, p_group=False):
"""
Turns a field, part of a sort/group string, into a lambda that
takes a todo item and returns the field value.
"""
compose = lambda i: i.sort if not p_group else (i.group, i.label)
def group_value(p_todo):
"""
Returns a value to assign the given todo to a group. Date tags
are grouped according to the relative date (1 day, 1 month,
...)
"""
result = 'No value'
if p_todo.has_tag(p_field):
if p_field == config().tag_due():
result = humanize_date(p_todo.due_date())
elif p_field == config().tag_start():
result = humanize_date(p_todo.start_date())
else:
result = p_todo.tag_value(p_field)
try:
result = humanize_date(date_string_to_date(result))
except ValueError:
pass
return result
if p_field in FIELD_MAP:
return compose(FIELDS[FIELD_MAP[p_field]])
else:
# treat it as a tag value
return compose(Field(
sort=lambda t: '0' + t.tag_value(p_field) if t.has_tag(p_field) else '1',
group=group_value,
label=p_field,
))
result = []
fields = p_string.lower().split(',')
for field in fields:
parsed_field = re.match(
r'(?P<order>(asc|desc)(ending)?:)?(?P<field>\S+)',
field)
if not parsed_field:
continue
order = parsed_field.group('order')
order = 'desc' if order and order.startswith('desc') else 'asc'
field = parsed_field.group('field')
if field:
function = get_field_function(field, p_group)
# reverse order for priority: lower characters have higher
# priority
if field in FIELD_MAP and FIELD_MAP[field] == 'priority':
order = 'asc' if order == 'desc' else 'desc'
result.append((function, order))
return result
self.groupfunctions = parse(p_groupstring, p_group=True) if p_groupstring else []
self.pregroupfunctions = parse(p_groupstring, p_group=False) if p_groupstring else []
self.sortfunctions = parse(p_sortstring, p_group=False)
def sort(self, p_todos): def sort(self, p_todos):
""" """
...@@ -198,75 +270,3 @@ class Sorter(object): ...@@ -198,75 +270,3 @@ class Sorter(object):
return result return result
def _parse(self, p_string, p_group):
"""
Parses a sort/group string and returns a list of functions and the
desired order.
"""
def get_field_function(p_field, p_group=False):
"""
Turns a field, part of a sort/group string, into a lambda that
takes a todo item and returns the field value.
"""
compose = lambda i: i.sort if not p_group else (i.group, i.label)
def group_value(p_todo):
"""
Returns a value to assign the given todo to a group. Date tags
are grouped according to the relative date (1 day, 1 month,
...)
"""
result = 'No value'
if p_todo.has_tag(p_field):
if p_field == config().tag_due():
result = humanize_date(p_todo.due_date())
elif p_field == config().tag_start():
result = humanize_date(p_todo.start_date())
else:
result = p_todo.tag_value(p_field)
try:
result = humanize_date(date_string_to_date(result))
except ValueError:
pass
return result
if p_field in FIELD_MAP:
return compose(FIELDS[FIELD_MAP[p_field]])
else:
# treat it as a tag value
return compose(Field(
sort=lambda t: '0' + t.tag_value(p_field) if t.has_tag(p_field) else '1',
group=group_value,
label=p_field,
))
result = []
fields = p_string.lower().split(',')
for field in fields:
parsed_field = re.match(
r'(?P<order>(asc|desc)(ending)?:)?(?P<field>\S+)',
field)
if not parsed_field:
continue
order = parsed_field.group('order')
order = 'desc' if order and order.startswith('desc') else 'asc'
field = parsed_field.group('field')
if field:
function = get_field_function(field, p_group)
# reverse order for priority: lower characters have higher
# priority
if field in FIELD_MAP and FIELD_MAP[field] == 'priority':
order = 'asc' if order == 'desc' else 'desc'
result.append((function, order))
return result
...@@ -116,7 +116,7 @@ class TodoList(TodoListBase): ...@@ -116,7 +116,7 @@ class TodoList(TodoListBase):
super().add_todos(p_todos) super().add_todos(p_todos)
for todo in self._todos: for todo in self._todos:
todo.parents = types.MethodType(lambda i: self.parents(i), todo) todo.parents = types.MethodType(self.parents, todo)
# only do administration when the dependency info is initialized, # only do administration when the dependency info is initialized,
# otherwise we postpone it until it's really needed (through the # otherwise we postpone it until it's really needed (through the
......
...@@ -177,7 +177,8 @@ class CLIApplicationBase(object): ...@@ -177,7 +177,8 @@ class CLIApplicationBase(object):
self._post_archive_action = None self._post_archive_action = None
self.backup = None self.backup = None
def _usage(self): @staticmethod
def _usage():
usage() usage()
sys.exit(0) sys.exit(0)
...@@ -208,7 +209,7 @@ class CLIApplicationBase(object): ...@@ -208,7 +209,7 @@ class CLIApplicationBase(object):
elif opt in ("-v", "--version"): elif opt in ("-v", "--version"):
version() version()
else: else:
self._usage() CLIApplicationBase._usage()
if alt_config_path: if alt_config_path:
config(alt_config_path, overrides) config(alt_config_path, overrides)
...@@ -237,21 +238,17 @@ class CLIApplicationBase(object): ...@@ -237,21 +238,17 @@ class CLIApplicationBase(object):
if archive.dirty: if archive.dirty:
archive_file.write(archive.print_todos()) archive_file.write(archive.print_todos())
def _help(self, args): @staticmethod
if args is None: def is_read_only(p_command):
pass # TODO
else:
pass # TODO
def is_read_only(self, p_command):
""" Returns True when the given command class is read-only. """ """ Returns True when the given command class is read-only. """
read_only_commands = tuple(cmd for cmd read_only_commands = tuple(cmd for cmd
in ('revert', ) + READ_ONLY_COMMANDS) in ('revert', ) + READ_ONLY_COMMANDS)
return p_command.name() in read_only_commands return p_command.name() in read_only_commands
def _backup(self, p_command, p_args=[], p_label=None): def _backup(self, p_command, p_args=None, p_label=None):
if config().backup_count() > 0 and p_command and not self.is_read_only(p_command): if config().backup_count() > 0 and p_command and not CLIApplicationBase.is_read_only(p_command):
call = [p_command.name()]+ p_args p_args = p_args if p_args else []
call = [p_command.name()] + p_args
from topydo.lib.ChangeSet import ChangeSet from topydo.lib.ChangeSet import ChangeSet
label = p_label if p_label else call label = p_label if p_label else call
......
...@@ -57,7 +57,7 @@ class CLIApplication(CLIApplicationBase): ...@@ -57,7 +57,7 @@ class CLIApplication(CLIApplicationBase):
sys.exit(1) sys.exit(1)
if subcommand is None: if subcommand is None:
self._usage() CLIApplicationBase._usage()
if self._execute(subcommand, args) == False: if self._execute(subcommand, args) == False:
sys.exit(1) sys.exit(1)
......
...@@ -196,10 +196,63 @@ class UIApplication(CLIApplicationBase): ...@@ -196,10 +196,63 @@ class UIApplication(CLIApplicationBase):
self._screen = urwid.raw_display.Screen() self._screen = urwid.raw_display.Screen()
def create_color_palette():
project_color = to_urwid_color(config().project_color())
context_color = to_urwid_color(config().context_color())
metadata_color = to_urwid_color(config().metadata_color())
link_color = to_urwid_color(config().link_color())
focus_background_color = to_urwid_color(config().focus_background_color())
marked_background_color = to_urwid_color(config().marked_background_color())
palette = [
(PaletteItem.PROJECT, '', '', '', project_color, ''),
(PaletteItem.PROJECT_FOCUS, '', 'light gray', '', project_color, focus_background_color),
(PaletteItem.CONTEXT, '', '', '', context_color, ''),
(PaletteItem.CONTEXT_FOCUS, '', 'light gray', '', context_color, focus_background_color),
(PaletteItem.METADATA, '', '', '', metadata_color, ''),
(PaletteItem.METADATA_FOCUS, '', 'light gray', '', metadata_color, focus_background_color),
(PaletteItem.LINK, '', '', '', link_color, ''),
(PaletteItem.LINK_FOCUS, '', 'light gray', '', link_color, focus_background_color),
(PaletteItem.DEFAULT_FOCUS, '', 'light gray', '', '', focus_background_color),
(PaletteItem.MARKED, '', 'light blue', '', '', marked_background_color),
]
for C in ascii_uppercase:
pri_color_cfg = config().priority_color(C)
pri_color = to_urwid_color(pri_color_cfg)
pri_color_focus = pri_color if not pri_color_cfg.is_neutral() else 'black'
palette.append((
'pri_' + C, '', '', '', pri_color, ''
))
palette.append((
'pri_' + C + '_focus', '', 'light gray', '', pri_color_focus, focus_background_color
))
return palette
def create_mono_palette():
palette = [
(PaletteItem.DEFAULT_FOCUS, 'black', 'light gray'),
(PaletteItem.PROJECT_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.CONTEXT_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.METADATA_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.LINK_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.MARKED, 'default,underline,bold', 'default'),
]
for C in ascii_uppercase:
palette.append(
('pri_' + C + '_focus', PaletteItem.DEFAULT_FOCUS)
)
return palette
if config().colors(): if config().colors():
self._screen.register_palette(self._create_color_palette()) self._screen.register_palette(create_color_palette())
else: else:
self._screen.register_palette(self._create_mono_palette()) self._screen.register_palette(create_mono_palette())
self._screen.set_terminal_properties(256) self._screen.set_terminal_properties(256)
...@@ -213,59 +266,6 @@ class UIApplication(CLIApplicationBase): ...@@ -213,59 +266,6 @@ class UIApplication(CLIApplicationBase):
self.column_mode = _APPEND_COLUMN self.column_mode = _APPEND_COLUMN
self._set_alarm_for_next_midnight_update() self._set_alarm_for_next_midnight_update()
def _create_color_palette(self):
project_color = to_urwid_color(config().project_color())
context_color = to_urwid_color(config().context_color())
metadata_color = to_urwid_color(config().metadata_color())
link_color = to_urwid_color(config().link_color())
focus_background_color = to_urwid_color(config().focus_background_color())
marked_background_color = to_urwid_color(config().marked_background_color())
palette = [
(PaletteItem.PROJECT, '', '', '', project_color, ''),
(PaletteItem.PROJECT_FOCUS, '', 'light gray', '', project_color, focus_background_color),
(PaletteItem.CONTEXT, '', '', '', context_color, ''),
(PaletteItem.CONTEXT_FOCUS, '', 'light gray', '', context_color, focus_background_color),
(PaletteItem.METADATA, '', '', '', metadata_color, ''),
(PaletteItem.METADATA_FOCUS, '', 'light gray', '', metadata_color, focus_background_color),
(PaletteItem.LINK, '', '', '', link_color, ''),
(PaletteItem.LINK_FOCUS, '', 'light gray', '', link_color, focus_background_color),
(PaletteItem.DEFAULT_FOCUS, '', 'light gray', '', '', focus_background_color),
(PaletteItem.MARKED, '', 'light blue', '', '', marked_background_color),
]
for C in ascii_uppercase:
pri_color_cfg = config().priority_color(C)
pri_color = to_urwid_color(pri_color_cfg)
pri_color_focus = pri_color if not pri_color_cfg.is_neutral() else 'black'
palette.append((
'pri_' + C, '', '', '', pri_color, ''
))
palette.append((
'pri_' + C + '_focus', '', 'light gray', '', pri_color_focus, focus_background_color
))
return palette
def _create_mono_palette(self):
palette = [
(PaletteItem.DEFAULT_FOCUS, 'black', 'light gray'),
(PaletteItem.PROJECT_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.CONTEXT_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.METADATA_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.LINK_FOCUS, PaletteItem.DEFAULT_FOCUS),
(PaletteItem.MARKED, 'default,underline,bold', 'default'),
]
for C in ascii_uppercase:
palette.append(
('pri_' + C + '_focus', PaletteItem.DEFAULT_FOCUS)
)
return palette
def _set_alarm_for_next_midnight_update(self): def _set_alarm_for_next_midnight_update(self):
def callback(p_loop, p_data): def callback(p_loop, p_data):
TodoWidget.wipe_cache() TodoWidget.wipe_cache()
......
...@@ -91,7 +91,6 @@ class TodoWidget(urwid.WidgetWrap): ...@@ -91,7 +91,6 @@ class TodoWidget(urwid.WidgetWrap):
priority_widget = urwid.Text(priority_text) priority_widget = urwid.Text(priority_text)
self.text_widget = urwid.Text(txt_markup) self.text_widget = urwid.Text(txt_markup)
progress = to_urwid_color(progress_color(p_todo)) if config().colors() else PaletteItem.DEFAULT
self.progress_bar = urwid.AttrMap( self.progress_bar = urwid.AttrMap(
urwid.SolidFill(' '), urwid.SolidFill(' '),
{}, {},
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
""" Entry file for the topydo Prompt interface (CLI). """ """ Entry file for the topydo Prompt interface (CLI). """
import os.path
import shlex import shlex
import sys import sys
...@@ -38,7 +37,6 @@ except ConfigError as config_error: ...@@ -38,7 +37,6 @@ except ConfigError as config_error:
from topydo.Commands import get_subcommand from topydo.Commands import get_subcommand
from topydo.lib.TodoFileWatched import TodoFileWatched from topydo.lib.TodoFileWatched import TodoFileWatched
from topydo.lib import TodoList
class PromptApplication(CLIApplicationBase): class PromptApplication(CLIApplicationBase):
......
...@@ -52,15 +52,14 @@ class PromptCompleter(CompleterBase, Completer): ...@@ -52,15 +52,14 @@ class PromptCompleter(CompleterBase, Completer):
for candidate in candidates: for candidate in candidates:
yield Completion(candidate, -len(p_word)) yield Completion(candidate, -len(p_word))
def get_completions(self, p_document, _): def get_completions(self, p_word, p_is_first_word=False):
# include all characters except whitespaces (for + and @) # include all characters except whitespaces (for + and @)
word_before_cursor = p_document.get_word_before_cursor(True) word_before_cursor = p_word.get_word_before_cursor(True)
is_first_word = not re.match(r'\s*\S+\s', is_first_word = not re.match(r'\s*\S+\s',
p_document.current_line_before_cursor) p_word.current_line_before_cursor)
if word_before_cursor.startswith(config().tag_due() + ':'): if word_before_cursor.startswith(config().tag_due() + ':'):
return _dates(word_before_cursor) return _dates(word_before_cursor)
elif word_before_cursor.startswith(config().tag_start() + ':'): elif word_before_cursor.startswith(config().tag_start() + ':'):
return _dates(word_before_cursor) return _dates(word_before_cursor)
else:
return self._completion_generator(word_before_cursor, is_first_word) return self._completion_generator(word_before_cursor, is_first_word)
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