From a75518e78f0599f75e546617c8d6fbecbc9242eb Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Wed, 21 Jan 2026 09:06:50 +0000 Subject: [PATCH] ui: new `item_chooser()` function --- mmgen/tw/addresses.py | 26 +++++++------------------- mmgen/ui.py | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/mmgen/tw/addresses.py b/mmgen/tw/addresses.py index 50ffa5a8..fd80d234 100755 --- a/mmgen/tw/addresses.py +++ b/mmgen/tw/addresses.py @@ -12,7 +12,7 @@ tw.addresses: Tracking wallet listaddresses class for the MMGen suite """ -from ..util import msg, is_int, die +from ..util import msg, die from ..obj import MMGenListItem, ImmutableAttr, ListItemAttr, TwComment, NonNegativeInt from ..addr import CoinAddr, MMGenID, MMGenAddrType from ..amt import CoinAmtChk @@ -403,24 +403,12 @@ class TwAddresses(TwView): """ def choose_address(addrs): - - def format_line(n, d): - return '{a:3}) {b}{c}'.format( - a = n, - b = d.twmmid.hl(), - c = yellow(' <== has a label!') if d.comment else '' - ) - - prompt = '\nChoose a {desc}:\n\n{items}\n\nEnter a number> '.format( - desc = desc, - items = '\n'.join(format_line(n, d) for n, d in enumerate(addrs, 1))) - - from ..ui import line_input - while True: - res = line_input(self.cfg, prompt) - if is_int(res) and 0 < int(res) <= len(addrs): - return addrs[int(res)-1] - msg(f'{res}: invalid entry') + def format_addr(d): + return '{a}{b}'.format( + a = d.twmmid.hl(), + b = yellow(' <== has a label!') if d.comment else '') + from ..ui import item_chooser + return item_chooser(self.cfg, f'Choose a {desc}', addrs, format_addr).item def get_addr(mmtype): return [self.get_change_address( diff --git a/mmgen/ui.py b/mmgen/ui.py index aace8bd0..7e6bbc3a 100755 --- a/mmgen/ui.py +++ b/mmgen/ui.py @@ -14,7 +14,7 @@ ui: Interactive user interface functions for the MMGen suite import sys, os -from .util import msg, msg_r, Msg, die +from .util import msg, msg_r, Msg, die, is_int def confirm_or_raise(cfg, message, action, *, expect='YES', exit_msg='Exiting at user request'): if message: @@ -117,6 +117,21 @@ def keypress_confirm( case _: msg_r('\nInvalid reply\n' if verbose else '\r') +def item_chooser(cfg, hdr, items, item_formatter, indent=' '): + from collections import namedtuple + col1_w = len(str(len(items))) + prompt = '{i}{a}:\n{i}{b}\n{i}{c}'.format( + a = hdr, + b = ('\n' + indent).join(f' {n:{col1_w}}) {item_formatter(d)}' for n, d in enumerate(items, 1)), + c = 'Enter a number> ', + i = indent) + while True: + res = line_input(cfg, prompt) + if is_int(res) and 0 < int(res) <= len(items): + num = int(res) + return namedtuple('user_choice', 'num idx item')(num, num - 1, items[num - 1]) + msg(f'{indent}{res}: invalid entry\n') + def do_pager(text): pagers = ['less', 'more']