Commit 239a275f authored by Bram Schoenmakers's avatar Bram Schoenmakers

Introduce -C flag to steer color output

The -C flag takes 0, 1, 16, 256, auto, yes, true, no, false as possible
values.

If auto, then colors are enabled unless the output is not connected to a
TTY and is likely not to understand ANSI escape codes. 'auto' is the
default value.

The config().colors() function either returns 0, 16 or 256 for the
possible colors that can be displayed.

These values are also recognized by the colors option in the
configuration file.

This fixes issue #111.
parent 163fdb91
......@@ -45,8 +45,7 @@ class ConfigTest(TopydoTest):
""" Bad colour switch value. """
# boolean settings must first be typecast to integers, because all
# strings evaulate to 'True'
self.assertEqual(config("test/data/ConfigTest4.conf").colors(),
bool(int(config().defaults["topydo"]["colors"])))
self.assertEqual(config("test/data/ConfigTest4.conf").colors(), 0)
def test_config06(self):
""" Bad auto creation date switch value. """
......
......@@ -684,13 +684,9 @@ C -
self.maxDiff = None
mock_terminal_size.return_value = self.terminal_size(100, 25)
config(p_overrides={('ls', 'list_format'): '%Z|%I| %x %p %S %k\\t%{(}h{)}'})
command1 = ListCommand(["-x"], self.todolist, self.out, self.error)
command1.execute()
config(p_overrides={('ls', 'list_format'): '%z|%I| %x %p %S %k\\t%{(}h{)}'})
command2 = ListCommand(["-x"], self.todolist, self.out, self.error)
command2.execute()
command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute()
result = u""" | 1| D Bar @Context1 +Project2 (due a month ago, started a month ago)
| 2| Z Lorem ipsum dolorem sit amet. Red @fox +jumpe... lazy:bar (due in 2 days, starts in a day)
......@@ -699,7 +695,7 @@ C -
| 5| Drink beer @ home
| 6| x 2014-12-12 Completed but with date:2014-12-12
"""
self.assertEqual(self.output, result * 2)
self.assertEqual(self.output, result)
if __name__ == '__main__':
unittest.main()
......@@ -4,7 +4,7 @@
default_command = ls
; filename = todo.txt
; archive_filename = done.txt
colors = 1
colors = auto
; identifiers can be 'linenumber' or 'text'
identifiers = linenumber
backup_count = 5
......@@ -42,6 +42,8 @@ append_parent_contexts = 0
; [light-]gray, darkgray or numbers from 0 to 255. When number is specified color
; is matched from Xterm color chart available here:
; http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
; When using values between 16 and 256, make sure to set colors = 256 in the
; [topydo] section.
; priority_colors = A:cyan,B:yellow,C:blue
; project_color = red
......
......@@ -22,7 +22,7 @@ I/O on the command-line.
import getopt
import sys
MAIN_OPTS = "ac:d:ht:v"
MAIN_OPTS = "ac:C:d:ht:v"
READ_ONLY_COMMANDS = ('List', 'ListContext', 'ListProject')
......@@ -30,12 +30,14 @@ def usage():
""" Prints the command-line usage of topydo. """
print("""\
Synopsis: topydo [-a] [-c <config>] [-d <archive>] [-t <todo.txt>] subcommand [help|args]
Synopsis: topydo [-a] [-c <config>] [-C <colormode>] [-d <archive>] [-t <todo.txt>] subcommand [help|args]
topydo -h
topydo -v
-a : Do not archive todo items on completion.
-c : Specify an alternative configuration file.
-C : Specify color mode (0 = disable, 1 = enable 16 colors,
16 = enable 16 colors, 256 = enable 256 colors, auto (default))
-d : Specify an alternative archive file (done.txt)
-h : This help text
-t : Specify an alternative todo file
......@@ -62,14 +64,14 @@ Available commands:
Run `topydo help <subcommand>` for command-specific help.
""")
def write(p_file, p_string):
"""
Write p_string to file p_file, trailed by a newline character.
ANSI codes are removed when the file is not a TTY.
ANSI codes are removed when the file is not a TTY (and colors are
automatically determined).
"""
if not p_file.isatty():
if not config().colors(16 if p_file.isatty() else 0):
p_string = escape_ansi(p_string)
if p_string:
......@@ -140,6 +142,8 @@ class CLIApplicationBase(object):
self.do_archive = False
elif opt == "-c":
alt_config_path = value
elif opt == "-C":
overrides[('topydo', 'colors')] = value
elif opt == "-t":
overrides[('topydo', 'filename')] = value
elif opt == "-d":
......
......@@ -58,7 +58,7 @@ class _Config:
self.defaults = {
'topydo': {
'default_command': 'ls',
'colors': '1',
'colors': 'auto',
'filename': 'todo.txt',
'archive_filename': 'done.txt',
'identifiers': 'linenumber',
......@@ -152,11 +152,30 @@ class _Config:
def default_command(self):
return self.cp.get('topydo', 'default_command')
def colors(self):
def colors(self, p_default=16):
"""
Returns 0, 16 or 256 representing the number of colors that should be
used in the output. When the configured value is 'auto', the default
value is used.
"""
lookup = {
'auto': p_default,
'false': 0,
'no': 0,
'0': 0,
'1': 16,
'true': 16,
'yes': 16,
'16': 16,
'256': 256,
}
try:
return self.cp.getboolean('topydo', 'colors')
return lookup[self.cp.get('topydo', 'colors').lower()] # pylint: disable=no-member
except ValueError:
return self.defaults['topydo']['colors'] == '1'
return lookup[self.defaults['topydo']['colors'].lower()] # pylint: disable=no-member
except KeyError:
return 0
def todotxt(self):
return os.path.expanduser(self.cp.get('topydo', 'filename'))
......
......@@ -129,9 +129,9 @@ def _right_align(p_str):
return p_str
def color_block(p_todo, p_256_color):
def color_block(p_todo):
return '{} {}'.format(
progress_color(p_todo, p_256_color).as_ansi(p_background=True),
progress_color(p_todo).as_ansi(p_background=True),
config().priority_color(p_todo.priority()).as_ansi(),
)
......@@ -201,9 +201,7 @@ class ListFormatParser(object):
# relative completion date
'X': lambda t: 'x ' + humanize_date(t.completion_date()) if t.is_completed() else '',
'z': lambda t: color_block(t, p_256_color=False) if config().colors() else ' ',
'Z': lambda t: color_block(t, p_256_color=True) if config().colors() else ' ',
'z': lambda t: color_block(t) if config().colors() else ' ',
}
self.format_list = self._preprocess_format()
......
......@@ -17,9 +17,10 @@
import re
from topydo.lib.Color import Color
from topydo.lib.Config import config
from topydo.lib.Recurrence import relative_date_to_date
def progress_color(p_todo, p_256color=False):
def progress_color(p_todo):
color16_range = [
10, # light green
2, # green
......@@ -76,7 +77,7 @@ def progress_color(p_todo, p_256color=False):
else:
return 0
color_range = color256_range if p_256color else color16_range
color_range = color256_range if config().colors() == 256 else color16_range
progress = get_progress()
# TODO: remove linear scale to exponential scale
......
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