def _str_to_dict(p_string): pri_colors_dict = dict() for pri_color in p_string.split(','): pri, color = pri_color.split(':') pri_colors_dict[pri] = Color(color) return pri_colors_dict
def priority_color(self, p_priority): """ Returns a dict with priorities as keys and color numbers as value. """ def _str_to_dict(p_string): pri_colors_dict = dict() for pri_color in p_string.split(','): pri, color = pri_color.split(':') pri_colors_dict[pri] = Color(color) return pri_colors_dict try: pri_colors_str = self.cp.get('colorscheme', 'priority_colors') if pri_colors_str == '': pri_colors_dict = _str_to_dict('A:-1,B:-1,C:-1') else: pri_colors_dict = _str_to_dict(pri_colors_str) except ValueError: pri_colors_dict = _str_to_dict( self.defaults['colorscheme']['priority_colors']) return pri_colors_dict[ p_priority] if p_priority in pri_colors_dict else Color('NEUTRAL')
def metadata_color(self): try: return Color(self.cp.getint('colorscheme', 'metadata_color')) except ValueError: return Color(self.cp.get('colorscheme', 'metadata_color'))
def context_color(self): try: return Color(self.cp.getint('colorscheme', 'context_color')) except ValueError: return Color(self.cp.get('colorscheme', 'context_color'))
def project_color(self): try: return Color(self.cp.getint('colorscheme', 'project_color')) except ValueError: return Color(self.cp.get('colorscheme', 'project_color'))
def progress_color(p_todo): color16_range = [ 2, # green 10, # light green 3, # yellow 1, # red ] # https://commons.wikimedia.org/wiki/File:Xterm_256color_chart.svg # a gradient from green to yellow to red color256_range = \ [22, 28, 34, 40, 46, 82, 118, 154, 190, 226, 220, 214, 208, 202, 196] def get_length(): """ Returns the length of the p_todo item in days, based on the recurrence period + due date, or the start/due date. """ result = 0 def diff_days(p_start, p_end): """ Returns the difference in days between p_start and p_end, where start is before due. """ diff = p_end - p_start return diff.days does_recur = p_todo.has_tag('rec') start_date = p_todo.start_date() due_date = p_todo.due_date() creation_date = p_todo.creation_date() if does_recur and due_date and not start_date: # add negation, offset is based on due date recurrence_pattern = p_todo.tag_value('rec') neg_recurrence_pattern = re.sub('^\+?', '-', recurrence_pattern) start = relative_date_to_date(neg_recurrence_pattern, due_date) result = diff_days(start, due_date) elif due_date and not start_date and not creation_date: result = ASSUMED_TODO_LENGTH elif due_date and start_date and due_date < start_date: result = ASSUMED_TODO_LENGTH elif due_date and not start_date and creation_date and due_date < creation_date: result = ASSUMED_TODO_LENGTH else: result = p_todo.length() # a todo item is at least one day long return max(1, result) def get_progress(p_todo, p_consider_parents=True): """ Returns a value from 0 to 1 where we are today in a date range. Returns a value >1 when a todo item is overdue. """ def progress_of_parents(): try: parents = p_todo.parents() except AttributeError: parents = [] if parents: return max(get_progress(parent, False) for parent in parents) else: return 0 if p_todo.is_completed(): return 0 elif p_todo.is_overdue(): return 1.1 elif p_todo.due_date(): days_till_due = p_todo.days_till_due() length = get_length() return max((length - days_till_due), 0) / length elif p_consider_parents: return progress_of_parents() else: return 0 use_256_colors = config().colors() == 256 color_range = color256_range if use_256_colors else color16_range progress = get_progress(p_todo) # TODO: remove linear scale to exponential scale if progress > 1: # overdue, return the last color return Color(color_range[-1]) elif p_todo.is_completed(): # return grey return Color(243) if use_256_colors else Color(7) else: # not overdue, calculate position over color range excl. due date # color pos = round(progress * (len(color_range) - 2)) return Color(color_range[pos])
def test_neutral_color(self): color = Color('NEUTRAL') self.assertEqual(color.as_ansi(), NEUTRAL_COLOR)