diff --git a/pubs/color.py b/pubs/color.py index f00d1f9..45ef268 100644 --- a/pubs/color.py +++ b/pubs/color.py @@ -6,7 +6,7 @@ import re import os def _color_supported(stream): - """Returns True is the stream supports colors""" + """Return True is the stream supports colors""" if sys.platform == 'win32' and 'ANSICON' not in os.environ: return False if hasattr(stream, 'isatty') and stream.isatty(): # we have a tty @@ -20,7 +20,17 @@ def _color_supported(stream): COLOR_LIST = [u'black', u'red', u'green', u'yellow', u'blue', u'purple', u'cyan', u'grey'] -def generate_colors(stream, color=True, bold=True, italic=True): +def generate_colors(stream, color=True, bold=True, italic=True, force_colors=False): + """Generate colors, based on configuration and detected support + + :param color: generate colors. If False, bold and italic will not change + the current color. + :param bold: generate bold colors, if False, bold color are the same as + normal colors. + :param italic: generate italic colors + :param force_colors: generate colors whether support is detected or not. Will not + overrride the `color` parameter. + """ colors = {name: u'' for name in COLOR_LIST} colors.update({u'b' +name: u'' for name in COLOR_LIST}) colors.update({u'i' +name: u'' for name in COLOR_LIST}) @@ -30,7 +40,9 @@ def generate_colors(stream, color=True, bold=True, italic=True): colors[u'end'] = u'' colors[u''] = u'' - if (color or bold or italic) and _color_supported(stream): + color_support = force_colors or _color_supported(stream) + + if (color or bold or italic) and color_support: bold_flag, italic_flag = '', '' if bold: colors['bold'] = u'\033[1m' @@ -64,27 +76,32 @@ def generate_colors(stream, color=True, bold=True, italic=True): COLORS_OUT = generate_colors(sys.stdout, color=False, bold=False, italic=False) COLORS_ERR = generate_colors(sys.stderr, color=False, bold=False, italic=False) + def dye_out(s, color='end'): + """Color a string for output on stdout""" return u'{}{}{}'.format(COLORS_OUT[color], s, COLORS_OUT['end']) def dye_err(s, color='end'): + """Color a string for output on stderr""" return u'{}{}{}'.format(COLORS_ERR[color], s, COLORS_OUT['end']) -def _nodye(s, *args, **kwargs): - return s -def setup(conf): +def setup(conf, force_colors=False): + """Prepare color for stdout and stderr""" global COLORS_OUT, COLORS_ERR - COLORS_OUT = generate_colors(sys.stdout, color=conf['formating']['color'], - bold=conf['formating']['bold'], - italic=conf['formating']['italics']) - COLORS_ERR = generate_colors(sys.stderr, color=conf['formating']['color'], - bold=conf['formating']['bold'], - italic=conf['formating']['italics']) + COLORS_OUT = generate_colors(sys.stdout, force_colors=force_colors, + color=conf['formating']['color'], + bold=conf['formating']['bold'], + italic=conf['formating']['italics']) + COLORS_ERR = generate_colors(sys.stderr, force_colors=force_colors, + color=conf['formating']['color'], + bold=conf['formating']['bold'], + italic=conf['formating']['italics']) for key, value in conf['theme'].items(): COLORS_OUT[key] = COLORS_OUT.get(value, '') COLORS_ERR[key] = COLORS_ERR.get(value, '') + # undye undye_re = re.compile('\x1b\[[;\d]*[A-Za-z]') diff --git a/pubs/pubs_cmd.py b/pubs/pubs_cmd.py index 3c450b1..e06edce 100644 --- a/pubs/pubs_cmd.py +++ b/pubs/pubs_cmd.py @@ -35,6 +35,9 @@ def execute(raw_args=sys.argv): conf_parser = argparse.ArgumentParser(prog="pubs", add_help=False) conf_parser.add_argument("-c", "--config", help="path to config file", type=str, metavar="FILE") + conf_parser.add_argument('--force-colors', dest='force_colors', + action='store_true', default=False, + help='color are not disabled when piping to a file or other commands') #conf_parser.add_argument("-u", "--update", help="update config if needed", # default=False, action='store_true') top_args, remaining_args = conf_parser.parse_known_args(raw_args[1:]) @@ -59,7 +62,7 @@ def execute(raw_args=sys.argv): conf = config.load_default_conf() conf.filename = conf_path - uis.init_ui(conf) + uis.init_ui(conf, force_colors=top_args.force_colors) ui = uis.get_ui() parser = argparse.ArgumentParser(description="research papers repository", diff --git a/pubs/uis.py b/pubs/uis.py index 587db98..4951af4 100644 --- a/pubs/uis.py +++ b/pubs/uis.py @@ -44,19 +44,19 @@ def get_ui(): return _ui -def init_ui(conf): +def init_ui(conf, force_colors=False): global _ui - _ui = InputUI(conf) + _ui = InputUI(conf, force_colors=force_colors) class PrintUI(object): - def __init__(self, conf): + def __init__(self, conf, force_colors=False): """ :param conf: if None, conservative default values are used. Useful to instanciate the UI before parsing the config file. """ - color.setup(conf) + color.setup(conf, force_colors=force_colors) self.encoding = _get_encoding(conf) self._stdout = codecs.getwriter(self.encoding)(_get_raw_stdout(), errors='replace') @@ -87,8 +87,8 @@ class InputUI(PrintUI): """UI class. Stores configuration parameters and system information. """ - def __init__(self, conf): - super(InputUI, self).__init__(conf) + def __init__(self, conf, force_colors=False): + super(InputUI, self).__init__(conf, force_colors=force_colors) self.editor = conf['main']['edit_cmd'] or _get_local_editor() def input(self):