ui: new item_chooser() function

This commit is contained in:
The MMGen Project 2026-01-21 09:06:50 +00:00
commit a75518e78f
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
2 changed files with 23 additions and 20 deletions

View file

@ -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(

View file

@ -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']