From bc03ffc69e5828e5470503a35a0fc95bc50d3d61 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 2 Oct 2026 10:02:32 +0000 Subject: [PATCH] ui: new `colorize_json()` func --- mmgen/color.py | 6 ++++++ mmgen/ui.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/mmgen/color.py b/mmgen/color.py index 7852f04e..d5012c35 100755 --- a/mmgen/color.py +++ b/mmgen/color.py @@ -39,6 +39,9 @@ _colors = { 'melon': (222, (33, 1)), 'brown': (173, (33, 0)), 'grndim': (108, (32, 0)), + 'puce': (137, (33, 0)), + 'sky': (117, (34, 1)), + 'lime': (115, (32, 1)), 'redbg': ((232, 210), (30, 101)), 'grnbg': ((232, 121), (30, 102)), @@ -128,6 +131,9 @@ pink = lambda s: s melon = lambda s: s brown = lambda s: s grndim = lambda s: s +puce = lambda s: s +sky = lambda s: s +lime = lambda s: s redbg = lambda s: s grnbg = lambda s: s diff --git a/mmgen/ui.py b/mmgen/ui.py index d486d15c..2fae454f 100755 --- a/mmgen/ui.py +++ b/mmgen/ui.py @@ -140,6 +140,58 @@ def item_chooser(cfg, hdr, items, item_formatter, indent='', empty_ok=False, add return namedtuple('user_choice', 'num idx item')(num, num - 1, items[num - 1]) msg(f'{indent}{res}: invalid entry\n') +def colorize_json(text): + "Colorize a pretty-formatted JSON string. Original indentation is preserved" + + from .color import puce, orange, gray, sky, lime + import re + + colon = orange(':') + # dict item: + pat01 = re.compile(r'(\s*)("\S+"): (".*")(,)*$') + pat02 = re.compile(r'(\s*)("\S+"): ([0-9]+)(,)*$') + pat03 = re.compile(r'(\s*)("\S+"): (true|false|null)(,)*$') + # list item + pat10 = re.compile(r'(\s*)(".+")(,)*$') + pat11 = re.compile(r'(\s*)([0-9]+)(,)*$') + pat12 = re.compile(r'(\s*)(true|false|null)(,)*$') + # dict item with punc + pat20 = re.compile(r'(\s*)("\S+"): ([\[\{\]\},]+)$') + # punc + pat30 = re.compile(r'(\s*)([\[\{\]\},]+)$') + + def ep(m): + return orange(m) if m else '' + + def tfn(s): + return { + 'true': puce('true'), + 'false': puce('false'), + 'null': gray('null')}[s] + + def gen(): + for line in text.split('\n'): # order matches by frequency of occurrence: + if m := pat01.match(line): + yield '{}{}{} {}{}'.format(m[1], sky(m[2]), colon, lime(m[3]), ep(m[4])) + elif m := pat02.match(line): + yield '{}{}{} {}{}'.format(m[1], sky(m[2]), colon, m[3], ep(m[4])) + elif m := pat03.match(line): + yield '{}{}{} {}{}'.format(m[1], sky(m[2]), colon, tfn(m[3]), ep(m[4])) + elif m := pat30.match(line): + yield '{}{}'.format(m[1], orange(m[2])) + elif m := pat20.match(line): + yield '{}{}{} {}'.format(m[1], sky(m[2]), colon, orange(m[3])) + elif m := pat10.match(line): + yield '{}{}{}'.format(m[1], lime(m[2]), ep(m[3])) + elif m := pat11.match(line): + yield '{}{}{}'.format(m[1], m[2], ep(m[3])) + elif m := pat12.match(line): + yield '{}{}{}'.format(m[1], tfn(m[2]), ep(m[3])) + else: # fallback: we shouldn’t be here + yield line + + return '\n'.join(gen()) + def do_pager(text): pagers = ['less', 'more']