From 39167e90be19a3b218d846d75eb467c88dd97ade Mon Sep 17 00:00:00 2001 From: philemon Date: Mon, 12 Dec 2016 16:27:30 +0300 Subject: [PATCH] [color]: support for 8-color terminals, better default colors [opt/cfg]: --force-256-color on terminals that support but don't advertise it --- data_files/mmgen.cfg | 3 ++ mmgen/color.py | 98 ++++++++++++++++++++++++++++++-------------- mmgen/globalvars.py | 6 ++- mmgen/opts.py | 3 +- 4 files changed, 76 insertions(+), 34 deletions(-) diff --git a/data_files/mmgen.cfg b/data_files/mmgen.cfg index 8ccd5954..106f0602 100644 --- a/data_files/mmgen.cfg +++ b/data_files/mmgen.cfg @@ -14,6 +14,9 @@ # Uncomment to disable color output: # color false +# Uncomment to force 256-color output when 'color' is true: +# force_256_color true + # Uncomment to use testnet instead of mainnet: # testnet true diff --git a/mmgen/color.py b/mmgen/color.py index 1df53e4b..756c7011 100755 --- a/mmgen/color.py +++ b/mmgen/color.py @@ -17,42 +17,78 @@ # along with this program. If not, see . """ -color.py: color routines for the MMGen suite +color.py: color handling for the MMGen suite """ -# If 88- or 256-color support is compiled, the following apply. -# P s = 3 8 ; 5 ; P s -> Set foreground color to the second P s . -# P s = 4 8 ; 5 ; P s -> Set background color to the second P s . -import os -if os.environ['TERM'][-8:] == '256color': - _blk,_red,_grn,_yel,_blu,_mag,_cya,_bright,_dim,_ybright,_ydim,_pnk,_orng,_gry,_pur = [ - '\033[38;5;%s;1m' % c for c in 232,210,121,229,75,90,122,231,245,187,243,218,215,246,147] - _redbg = '\033[38;5;232;48;5;210;1m' - _grnbg = '\033[38;5;232;48;5;121;1m' - _grybg = '\033[38;5;231;48;5;240;1m' - _reset = '\033[0m' -else: - _blk,_red,_grn,_yel,_blu,_mag,_cya,_reset,_grnbg = \ - ['\033[%sm' % c for c in '30;1','31;1','32;1','33;1','34;1','35;1','36;1','0','30;102'] - _gry=_orng=_pnk=_redbg=_ybright=_ydim=_bright=_dim=_grybg=_mag=_pur # TODO +_colors = { + 'black': ( 232, (30,0) ), + 'red': ( 210, (31,1) ), + 'green': ( 121, (32,1) ), + 'yellow': ( 229, (33,1) ), + 'blue': ( 75, (34,1) ), + 'magenta': ( 213, (35,1) ), + 'cyan': ( 122, (36,1) ), + 'pink': ( 218, (35,1) ), + 'orange': ( 216, (31,1) ), + 'gray': ( 246, (30,1) ), + 'purple': ( 141, (35,1) ), -_colors = 'red','grn','grnbg','yel','cya','blu','pnk','orng','gry','mag','pur','reset' -for c in _colors: globals()['clr_'+c] = '' + 'brown': ( 208, (33,0) ), + 'grndim': ( 108, (32,0) ), + 'redbg': ( (232,210), (30,101) ), + 'grnbg': ( (232,121), (30,102) ), + 'blubg': ( (232,75), (30,104) ), + 'yelbg': ( (232,229), (30,103) ), +} + +for c in _colors: + e = _colors[c] + if type(e[0]) == int: + globals()['_256_'+c] = '\033[38;5;{};1m'.format(e[0]) + else: + globals()['_256_'+c] = '\033[38;5;{};48;5;{};1m'.format(*e[0]) + if e[1][1] == 0: + globals()['_16_'+c] = '\033[{}m'.format(e[1][0]) + else: + globals()['_16_'+c] = '\033[{};{}m'.format(*e[1]) + globals()['_clr_'+c] = ''; _reset = '' + exec "def {c}(s): return _clr_{c}+s+_reset".format(c=c) def nocolor(s): return s -def red(s): return clr_red+s+clr_reset -def green(s): return clr_grn+s+clr_reset -def grnbg(s): return clr_grnbg+s+clr_reset -def yellow(s): return clr_yel+s+clr_reset -def cyan(s): return clr_cya+s+clr_reset -def blue(s): return clr_blu+s+clr_reset -def pink(s): return clr_pnk+s+clr_reset -def orange(s): return clr_orng+s+clr_reset -def gray(s): return clr_gry+s+clr_reset -def magenta(s): return clr_mag+s+clr_reset -def purple(s): return clr_pur+s+clr_reset -def init_color(enable_color=True): +def init_color(enable_color=True,num_colors='auto'): if enable_color: + assert num_colors in ['auto',8,16,256] + globals()['_reset'] = '\033[0m' + if num_colors in [8,16]: + pfx = '_16_' + elif num_colors in [256]: + pfx = '_256_' + else: + try: + import os + assert os.environ['TERM'][-8:] == '256color' + pfx = '_256_' + except: + try: + import subprocess + a = subprocess.check_output(['infocmp','-0']) + b = [e.split('#')[1] for e in a.split(',') if e[:6] == 'colors'][0] + pfx = ('_16_','_256_')[b=='256'] + except: + pfx = '_16_' + for c in _colors: - globals()['clr_'+c] = globals()['_'+c] + globals()['_clr_'+c] = globals()[pfx+c] + +def test_color(): + try: + import colorama + colorama.init(strip=True,convert=True) + except: + pass + for desc,n in ('auto','auto'),('8-color',8),('256-color',256): + if n != 'auto': init_color(num_colors=n) + print('{:9}: {}'.format(desc,' '.join([globals()[c](c) for c in sorted(_colors)]))) + +if __name__ == '__main__': test_color() diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index 330fc5b3..5fdb5994 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -65,6 +65,7 @@ class g(object): no_license = False hold_protect = True color = (False,True)[sys.stdout.isatty()] + force_256_color = False testnet = False rpc_host = '' rpc_port = 0 @@ -93,7 +94,7 @@ class g(object): # User opt sets global var: common_opts = ( 'color','no_license','rpc_host','rpc_port','testnet','rpc_user','rpc_password', - 'bitcoin_data_dir' + 'bitcoin_data_dir','force_256_color' ) required_opts = ( 'quiet','verbose','debug','outdir','echo_passphrase','passwd_file','stdout', @@ -110,13 +111,14 @@ class g(object): cfg_file_opts = ( 'color','debug','hash_preset','http_timeout','no_license','rpc_host','rpc_port', 'quiet','tx_fee','tx_fee_adj','usr_randchars','testnet','rpc_user','rpc_password', - 'bitcoin_data_dir' + 'bitcoin_data_dir','force_256_color' ) env_opts = ( 'MMGEN_BOGUS_WALLET_DATA', 'MMGEN_DEBUG', 'MMGEN_QUIET', 'MMGEN_DISABLE_COLOR', + 'MMGEN_FORCE_256_COLOR', 'MMGEN_DISABLE_HOLD_PROTECT', 'MMGEN_MIN_URANDCHARS', 'MMGEN_NO_LICENSE', diff --git a/mmgen/opts.py b/mmgen/opts.py index 1c8b60cc..624dfd85 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -68,6 +68,7 @@ def _show_hash_presets(): # most, but not all, of these set the corresponding global var common_opts_data = """ --, --color=0|1 Disable or enable color output +--, --force-256-color Force 256-color output when color is enabled --, --bitcoin-data-dir=d Specify Bitcoin data directory location 'd' --, --data-dir=d Specify {pnm} data directory location 'd' --, --no-license Suppress the GPL license prompt @@ -116,7 +117,7 @@ def opt_postproc_initializations(): check_or_create_dir(g.data_dir) # dies on error from mmgen.color import init_color - init_color(g.color) + init_color(enable_color=g.color,num_colors=('auto',256)[bool(g.force_256_color)]) if g.platform == 'win': start_mscolor()