# HG changeset patch # User Dmitriy Morozov # Date 1302932599 25200 # Node ID f44b6f1f21158c4aaf5bff18c0c8ed08fbac6eb5 # Parent 6c388fe11dcc64a8907722a5e6fd151eea28dd4f Added termcolor.py and started working on #edb (colorize output) diff -r 6c388fe11dcc -r f44b6f1f2115 .issues/edb1a7697e0f1e24/new/1208863350.M507651P11810Q1.metatron --- a/.issues/edb1a7697e0f1e24/new/1208863350.M507651P11810Q1.metatron Fri Apr 15 21:37:16 2011 -0700 +++ b/.issues/edb1a7697e0f1e24/new/1208863350.M507651P11810Q1.metatron Fri Apr 15 22:43:19 2011 -0700 @@ -1,6 +1,6 @@ From: Dmitriy Morozov Date: Tue, 22 Apr 2008 07:21:57 -State: new +State: in-progress Subject: Colorize output Message-Id: diff -r 6c388fe11dcc -r f44b6f1f2115 .issues/edb1a7697e0f1e24/new/1302932456.M373542P7817Q1.vine --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.issues/edb1a7697e0f1e24/new/1302932456.M373542P7817Q1.vine Fri Apr 15 22:43:19 2011 -0700 @@ -0,0 +1,11 @@ +From: Dmitriy Morozov +Date: Fri, 15 Apr 2011 22:35:57 -0700 +Subject: More generic color selection +Message-Id: +References: +In-Reply-To: + +Right now the color criteria are hard-coded: state is new vs fixed. This +selection should be more generic. Instead of providing just two possible color +styles in the config file, the user should be able to specify colors for +arbitrary states, maybe even more general selection based on other properties. diff -r 6c388fe11dcc -r f44b6f1f2115 artemis.py --- a/artemis.py Fri Apr 15 21:37:16 2011 -0700 +++ b/artemis.py Fri Apr 15 22:43:19 2011 -0700 @@ -14,6 +14,8 @@ from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from termcolor import colored + state = {'new': 'new', 'fixed': ['fixed', 'resolved']} state['default'] = state['new'] @@ -36,6 +38,8 @@ if opts['order']: order = opts['order'] + # Colors + colors = _read_colors(ui) # Find issues issues_dir = ui.config('artemis', 'issues', default = default_issues_dir) @@ -61,7 +65,7 @@ list_properties_dict = {} properties += filter(lambda p: len(p) > 1, cmd_properties) - subjects = [] + summaries = [] for issue in issues: mbox = mailbox.Maildir(issue, factory=mailbox.MaildirMessage) root = _find_root_key(mbox) @@ -77,18 +81,15 @@ if match_date and not date_match(util.parsedate(mbox[root]['date'])[0]): continue if not list_properties: - subjects.append(("%s (%3d) [%s]: %s\n" % (issue[len(issues_path)+1:], # +1 for trailing / - len(mbox)-1, # number of replies (-1 for self) - _status_msg(mbox[root]), - mbox[root]['Subject']), - _find_mbox_date(mbox, root, order))) + summaries.append((_summary_line(mbox, root, issue[len(issues_path)+1:], colors), # +1 for trailing / + _find_mbox_date(mbox, root, order))) else: for lp in list_properties: if lp in mbox[root]: list_properties_dict.setdefault(lp, set()).add(mbox[root][lp]) if not list_properties: - subjects.sort(lambda (s1,d1),(s2,d2): cmp(d2,d1)) - for s,d in subjects: + summaries.sort(lambda (s1,d1),(s2,d2): cmp(d2,d1)) + for s,d in summaries: ui.write(s) else: for lp in list_properties_dict.keys(): @@ -421,6 +422,35 @@ else: return msg['State'] +def _read_colors(ui): + colors = {} + # defaults + colors['new.color'] = 'red' + colors['new.on_color'] = 'on_grey' + colors['new.attrs'] = 'bold' + colors['resolved.color'] = 'white' + colors['resolved.on_color'] = '' + colors['resolved.attrs'] = '' + for v in colors: + colors[v] = ui.config('artemis', v, colors[v]) + if v.endswith('attrs'): colors[v] = colors[v].split() + return colors + +def _color_summary(line, msg, colors): + if msg['State'] == 'new': + return colored(line, colors['new.color'], attrs = colors['new.attrs']) + elif msg['State'] in state['fixed']: + return colored(line, colors['resolved.color'], attrs = colors['resolved.attrs']) + else: + return line + +def _summary_line(mbox, root, issue, colors): + line = "%s (%3d) [%s]: %s\n" % (issue, + len(mbox)-1, # number of replies (-1 for self) + _status_msg(mbox[root]), + mbox[root]['Subject']) + return _color_summary(line, mbox[root], colors) + cmdtable = { 'ilist': (ilist, [('a', 'all', False, diff -r 6c388fe11dcc -r f44b6f1f2115 termcolor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/termcolor.py Fri Apr 15 22:43:19 2011 -0700 @@ -0,0 +1,168 @@ +# coding: utf-8 +# Copyright (c) 2008-2011 Volvox Development Team +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# Author: Konstantin Lepa + +"""ANSII Color formatting for output in terminal.""" + +from __future__ import print_function +import os + + +__ALL__ = [ 'colored', 'cprint' ] + +VERSION = (1, 1, 0) + +ATTRIBUTES = dict( + list(zip([ + 'bold', + 'dark', + '', + 'underline', + 'blink', + '', + 'reverse', + 'concealed' + ], + list(range(1, 9)) + )) + ) +del ATTRIBUTES[''] + + +HIGHLIGHTS = dict( + list(zip([ + 'on_grey', + 'on_red', + 'on_green', + 'on_yellow', + 'on_blue', + 'on_magenta', + 'on_cyan', + 'on_white' + ], + list(range(40, 48)) + )) + ) + + +COLORS = dict( + list(zip([ + 'grey', + 'red', + 'green', + 'yellow', + 'blue', + 'magenta', + 'cyan', + 'white', + ], + list(range(30, 38)) + )) + ) + + +RESET = '\033[0m' + + +def colored(text, color=None, on_color=None, attrs=None): + """Colorize text. + + Available text colors: + red, green, yellow, blue, magenta, cyan, white. + + Available text highlights: + on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white. + + Available attributes: + bold, dark, underline, blink, reverse, concealed. + + Example: + colored('Hello, World!', 'red', 'on_grey', ['blue', 'blink']) + colored('Hello, World!', 'green') + """ + if os.getenv('ANSI_COLORS_DISABLED') is None: + fmt_str = '\033[%dm%s' + if color is not None: + text = fmt_str % (COLORS[color], text) + + if on_color is not None: + text = fmt_str % (HIGHLIGHTS[on_color], text) + + if attrs is not None: + for attr in attrs: + text = fmt_str % (ATTRIBUTES[attr], text) + + text += RESET + return text + + +def cprint(text, color=None, on_color=None, attrs=None, **kwargs): + """Print colorize text. + + It accepts arguments of print function. + """ + + print((colored(text, color, on_color, attrs)), **kwargs) + + +if __name__ == '__main__': + print('Current terminal type: %s' % os.getenv('TERM')) + print('Test basic colors:') + cprint('Grey color', 'grey') + cprint('Red color', 'red') + cprint('Green color', 'green') + cprint('Yellow color', 'yellow') + cprint('Blue color', 'blue') + cprint('Magenta color', 'magenta') + cprint('Cyan color', 'cyan') + cprint('White color', 'white') + print(('-' * 78)) + + print('Test highlights:') + cprint('On grey color', on_color='on_grey') + cprint('On red color', on_color='on_red') + cprint('On green color', on_color='on_green') + cprint('On yellow color', on_color='on_yellow') + cprint('On blue color', on_color='on_blue') + cprint('On magenta color', on_color='on_magenta') + cprint('On cyan color', on_color='on_cyan') + cprint('On white color', color='grey', on_color='on_white') + print('-' * 78) + + print('Test attributes:') + cprint('Bold grey color', 'grey', attrs=['bold']) + cprint('Dark red color', 'red', attrs=['dark']) + cprint('Underline green color', 'green', attrs=['underline']) + cprint('Blink yellow color', 'yellow', attrs=['blink']) + cprint('Reversed blue color', 'blue', attrs=['reverse']) + cprint('Concealed Magenta color', 'magenta', attrs=['concealed']) + cprint('Bold underline reverse cyan color', 'cyan', + attrs=['bold', 'underline', 'reverse']) + cprint('Dark blink concealed white color', 'white', + attrs=['dark', 'blink', 'concealed']) + print(('-' * 78)) + + print('Test mixing:') + cprint('Underline red on grey color', 'red', 'on_grey', + ['underline']) + cprint('Reversed green on red color', 'green', 'on_red', ['reverse']) +