From f44078a18704aac56cb53fc126c833b87d6ae6b8 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 11 Nov 2022 09:48:58 +0000 Subject: [PATCH] tw.common: dynamic format strings; tw.unspent: reimplement display --- mmgen/data/version | 2 +- mmgen/proto/btc/tw/addresses.py | 5 - mmgen/proto/btc/tw/txhistory.py | 3 - mmgen/proto/btc/tw/unspent.py | 5 - mmgen/proto/eth/tw/addresses.py | 28 ++++- mmgen/proto/eth/tw/unspent.py | 57 +++++++--- mmgen/tw/addresses.py | 39 ++----- mmgen/tw/common.py | 31 +++++- mmgen/tw/txhistory.py | 21 +--- mmgen/tw/unspent.py | 192 ++++++++++++++------------------ 10 files changed, 195 insertions(+), 188 deletions(-) diff --git a/mmgen/data/version b/mmgen/data/version index 32cf1b79..b7239029 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -13.3.dev17 +13.3.dev18 diff --git a/mmgen/proto/btc/tw/addresses.py b/mmgen/proto/btc/tw/addresses.py index 304692c3..a5aa7e27 100755 --- a/mmgen/proto/btc/tw/addresses.py +++ b/mmgen/proto/btc/tw/addresses.py @@ -45,11 +45,6 @@ Actions: [q]uit, r[e]draw, add [l]abel: 'p':'a_print_detail', 'l':'a_comment_add' } - squeezed_fs_fs = ' {{n:>{nw}}} {{m}} {{u}}%s {{c}} {{A}} {{d}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}}%s {{c:{cw}}} {{A:{Aw}}} {{d}}' - wide_fs_fs = ' {{n:>{nw}}} {{m}} {{u}} {{a}} {{c}} {{A}} {{b:<{bw}}} {{D}}' - wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{u:{uw}}} {{a:{aw}}} {{c:{cw}}} {{A:{Aw}}} {{b:{bw}}} {{D}}' - async def get_rpc_data(self): msg_r('Getting unspent outputs...') diff --git a/mmgen/proto/btc/tw/txhistory.py b/mmgen/proto/btc/tw/txhistory.py index a9f9383e..daff58be 100755 --- a/mmgen/proto/btc/tw/txhistory.py +++ b/mmgen/proto/btc/tw/txhistory.py @@ -253,9 +253,6 @@ Actions: [q]uit, r[e]draw: 'p':'a_print_squeezed', 'P':'a_print_detail' } - squeezed_fs_fs = ' {{n:>{nw}}} {{d:>{dw}}} {txid_fs}{{i}} {{A}} {{o}} {{c}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{d:{dw}}} {txid_fs}{{i:{iw}}} {{A}} {{o:{ow}}} {{c}}' - async def get_rpc_data(self): blockhash = ( await self.rpc.call( 'getblockhash', self.sinceblock ) diff --git a/mmgen/proto/btc/tw/unspent.py b/mmgen/proto/btc/tw/unspent.py index 42ef10ae..cff2ee7d 100755 --- a/mmgen/proto/btc/tw/unspent.py +++ b/mmgen/proto/btc/tw/unspent.py @@ -52,11 +52,6 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, add [l]abel: 'w':'a_view_detail', 'l':'a_comment_add' } - col_adj = 38 - squeezed_fs_fs = ' {{n:{cw}}} {{t:{tw}}} {{v:2}} {{a}} {{A}} {{c:<}}' - squeezed_hdr_fs_fs = ' {{n:{cw}}} {{t:{tw}}} {{a}} {{A}} {{c:<}}' - wide_fs_fs = ' {{n:4}} {{t:{tw}}} {{a}} {{m}} {{A:{aw}}} {cf}{{b:<8}} {{D:<19}} {{l}}' - async def get_rpc_data(self): # bitcoin-cli help listunspent: # Arguments: diff --git a/mmgen/proto/eth/tw/addresses.py b/mmgen/proto/eth/tw/addresses.py index 761ea8f7..3f273965 100755 --- a/mmgen/proto/eth/tw/addresses.py +++ b/mmgen/proto/eth/tw/addresses.py @@ -40,10 +40,30 @@ Actions: [q]uit, r[e]draw, [D]elete address, add [l]abel: 'w':'a_view_detail', 'p':'a_print_detail' } - squeezed_fs_fs = ' {{n:>{nw}}} {{m:}}%s {{c:}} {{A:}}' - squeezed_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}}%s {{c:{cw}}} {{A:{Aw}}}' - wide_fs_fs = ' {{n:>{nw}}} {{m:}} {{a:}} {{c:}} {{A:}}' - wide_hdr_fs_fs = ' {{n:>{nw}}} {{m:{mw}}} {{a:{aw}}} {{c:{cw}}} {{A:{Aw}}}' + def get_column_widths(self,data,wide=False): + + return self.compute_column_widths( + widths = { # fixed cols + 'num': max(2,len(str(len(data)))+1), + 'mmid': max(len(d.twmmid.disp) for d in data), + 'used': 0, + 'amt': self.disp_prec + 5, + 'date': 0, + 'block': 0, + 'date_time': 0, + 'spc': 5, # 4 spaces between cols + 1 leading space in fs + }, + maxws = { # expandable cols + 'addr': max(len(d.addr) for d in data) if self.showcoinaddrs else 0, + 'comment': max(d.comment.screen_width for d in data), + }, + minws = { + 'addr': 12 if self.showcoinaddrs else 0, + 'comment': len('Comment'), + }, + maxws_nice = {'addr': 18}, + wide = wide, + ) async def get_rpc_data(self): diff --git a/mmgen/proto/eth/tw/unspent.py b/mmgen/proto/eth/tw/unspent.py index e71358c3..e3ca48e5 100755 --- a/mmgen/proto/eth/tw/unspent.py +++ b/mmgen/proto/eth/tw/unspent.py @@ -20,20 +20,28 @@ proto.eth.twuo: Ethereum tracking wallet unspent outputs class """ -from ....globalvars import g from ....tw.common import TwLabel from ....tw.unspent import TwUnspentOutputs +from .common import EthereumTwCommon # No unspent outputs with Ethereum, but naming must be consistent -class EthereumTwUnspentOutputs(TwUnspentOutputs): +class EthereumTwUnspentOutputs(EthereumTwCommon,TwUnspentOutputs): + + class display_type(TwUnspentOutputs.display_type): + + class squeezed(TwUnspentOutputs.display_type.squeezed): + cols = ('num','addr','mmid','comment','amt','amt2') + + class detail(TwUnspentOutputs.display_type.detail): + cols = ('num','addr','mmid','amt','amt2','comment') class MMGenTwUnspentOutput(TwUnspentOutputs.MMGenTwUnspentOutput): valid_attrs = {'txid','vout','amt','amt2','comment','twmmid','addr','confs','skip'} invalid_attrs = {'proto'} + token_cls = False has_age = False can_group = False - col_adj = 29 hdr_lbl = 'tracked accounts' desc = 'account balances' item_desc = 'account' @@ -59,17 +67,35 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, 'D':'a_addr_delete', 'R':'a_balance_refresh' } - squeezed_fs_fs = squeezed_hdr_fs_fs = ' {{n:{cw}}} {{a}} {{A}}' - wide_fs_fs = ' {{n:4}} {{a}} {{m}} {{A:{aw}}} {{l}}' no_data_errmsg = 'No accounts in tracking wallet!' - def subheader(self,color): - if g.cached_balances: - from ....color import nocolor,yellow - return (nocolor,yellow)[color]( - 'WARNING: Using cached balances. These may be out of date!') + '\n' - else: - return '' + def get_column_widths(self,data,wide=False): + # min screen width: 80 cols + # num addr [mmid] [comment] amt [amt2] + return self.compute_column_widths( + widths = { # fixed cols + 'num': max(2,len(str(len(data)))+1), + 'mmid': max(len(d.twmmid.disp) for d in data) if self.show_mmid else 0, + 'amt': self.disp_prec + 5, + 'amt2': self.disp_prec + 5 if self.token_cls else 0, + 'spc': (5 if self.show_mmid else 3) + self.token_cls, # 5(3) spaces in fs + 'txid': 0, + 'vout': 0, + 'block': 0, + 'date': 0, + 'date_time': 0, + }, + maxws = { # expandable cols + 'addr': max(len(d.addr) for d in data), + 'comment': max(d.comment.screen_width for d in data) if self.show_mmid else 0, + }, + minws = { + 'addr': 10, + 'comment': len('Comment') if self.show_mmid else 0, + }, + maxws_nice = {'addr': 14} if self.show_mmid else {}, + wide = wide, + ) def do_sort(self,key=None,reverse=False): if key == 'txid': return @@ -86,15 +112,10 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, 'confirmations': 0, # TODO } for d in wl] - def age_disp(self,o,age_fmt): # TODO - pass - class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs): prompt_fs = 'Total to spend: {} {}\n\n' - col_adj = 37 - squeezed_fs_fs = squeezed_hdr_fs_fs = ' {{n:{cw}}} {{a}} {{A}} {{A2}}' - wide_fs_fs = ' {{n:4}} {{a}} {{m}} {{A:{aw}}} {{A2:{aw}}} {{l}}' + token_cls = True async def __init__(self,proto,*args,**kwargs): await super().__init__(proto,*args,**kwargs) diff --git a/mmgen/tw/addresses.py b/mmgen/tw/addresses.py index f7f52220..8b321cd9 100755 --- a/mmgen/tw/addresses.py +++ b/mmgen/tw/addresses.py @@ -37,6 +37,14 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): all_labels = False no_data_errmsg = 'No addresses in tracking wallet!' + class display_type(TwCommon.display_type): + + class squeezed(TwCommon.display_type.squeezed): + cols = ('num','mmid','used','addr','comment','amt','date') + + class detail(TwCommon.display_type.detail): + cols = ('num','mmid','used','addr','comment','amt','block','date_time') + class TwAddress(MMGenListItem): valid_attrs = {'twmmid','addr','al_id','confs','comment','amt','recvd','date','skip'} invalid_attrs = {'proto'} @@ -153,20 +161,7 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): else: return '' - def gen_squeezed_display(self,data,cw,color): - - fs_parms = { - 'nw': cw.num, - 'mw': cw.mmid, - 'uw': cw.used, - 'aw': cw.addr, - 'cw': cw.comment, - 'Aw': cw.amt, - 'dw': cw.date - } - - hdr_fs = (self.squeezed_hdr_fs_fs % ('',' {{a:{aw}}}')[self.showcoinaddrs]).format(**fs_parms) - fs = (self.squeezed_fs_fs % ('',' {{a}}')[self.showcoinaddrs]).format(**fs_parms) + def gen_squeezed_display(self,data,cw,hdr_fs,fs,color): yield hdr_fs.format( n = '', @@ -194,21 +189,7 @@ class TwAddresses(MMGenObject,TwCommon,metaclass=AsyncInit): d = self.age_disp( d, self.age_fmt ) ) - def gen_detail_display(self,data,cw,color): - - fs_parms = { - 'nw': cw.num, - 'mw': cw.mmid, - 'uw': cw.used, - 'aw': cw.addr, - 'cw': cw.comment, - 'Aw': cw.amt, - 'bw': self.age_col_params['block'][0], - 'Dw': self.age_col_params['date_time'][0], - } - - hdr_fs = self.wide_hdr_fs_fs.format(**fs_parms) - fs = self.wide_fs_fs.format(**fs_parms) + def gen_detail_display(self,data,cw,hdr_fs,fs,color): yield hdr_fs.format( n = '', diff --git a/mmgen/tw/common.py b/mmgen/tw/common.py index 43a0866e..254ab8a7 100755 --- a/mmgen/tw/common.py +++ b/mmgen/tw/common.py @@ -42,6 +42,24 @@ class TwCommon: _display_data = {} filters = () + fp = namedtuple('fs_params',['fs_key','hdr_fs_repl','fs_repl','hdr_fs','fs']) + fs_params = { + 'num': fp('n', True, True, ' {n:>%s}', ' {n:>%s}'), + 'txid': fp('t', True, False, ' {t:%s}', ' {t}'), + 'vout': fp('v', True, False, '{v:%s}', '{v}'), + 'used': fp('u', True, False, ' {u:%s}', ' {u}'), + 'addr': fp('a', True, False, ' {a:%s}', ' {a}'), + 'mmid': fp('m', True, False, ' {m:%s}', ' {m}'), + 'comment': fp('c', True, False, ' {c:%s}', ' {c}'), + 'amt': fp('A', True, False, ' {A:%s}', ' {A}'), + 'amt2': fp('B', True, False, ' {B:%s}', ' {B}'), + 'date': fp('d', True, True, ' {d:%s}', ' {d:<%s}'), + 'date_time': fp('D', True, True, ' {D:%s}', ' {D:%s}'), + 'block': fp('b', True, True, ' {b:%s}', ' {b:<%s}'), + 'inputs': fp('i', True, False, ' {i:%s}', ' {i}'), + 'outputs': fp('o', True, False, ' {o:%s}', ' {o}'), + } + age_fmts = ('confs','block','days','date','date_time') age_fmts_date_dependent = ('days','date','date_time') age_fmts_interactive = ('confs','block','days','date','date_time') @@ -283,12 +301,21 @@ class TwCommon: data = self.disp_data = list(self.filter_data()) # method could be a generator - cw = self.get_column_widths(data,wide=dt.detail) if data and dt.need_column_widths else None + if data and dt.need_column_widths: + cw = self.get_column_widths(data,wide=dt.detail) + cwh = cw._asdict() + fp = self.fs_params + hdr_fs = ''.join(fp[name].hdr_fs % ((),cwh[name])[fp[name].hdr_fs_repl] + for name in dt.cols if cwh[name]) + fs = ''.join(fp[name].fs % ((),cwh[name])[fp[name].fs_repl] + for name in dt.cols if cwh[name]) + else: + cw = hdr_fs = fs = None self._display_data[display_type] = '{a}{b}\n{c}\n'.format( a = self.header(color), b = self.subheader(color), - c = dt.item_separator.join(getattr(self,dt.fmt_method)(data,cw,color=color)) + c = dt.item_separator.join(getattr(self,dt.fmt_method)(data,cw,hdr_fs,fs,color=color)) if data else (nocolor,yellow)[color]('[no data for requested parameters]') ) diff --git a/mmgen/tw/txhistory.py b/mmgen/tw/txhistory.py index 27188e87..6da6c768 100755 --- a/mmgen/tw/txhistory.py +++ b/mmgen/tw/txhistory.py @@ -25,6 +25,9 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): class display_type(TwCommon.display_type): + class squeezed(TwCommon.display_type.squeezed): + cols = ('num','txid','date','inputs','amt','outputs','comment') + class detail(TwCommon.display_type.detail): need_column_widths = False item_separator = '\n\n' @@ -87,7 +90,7 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): return self.compute_column_widths(widths,maxws,minws,maxws_nice,wide=wide) - def gen_squeezed_display(self,data,cw,color): + def gen_squeezed_display(self,data,cw,hdr_fs,fs,color): if self.sinceblock: yield f'Displaying transactions since block {self.sinceblock.hl(color=color)}' @@ -98,18 +101,6 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): yield 'Due to screen width limitations, not all addresses could be displayed' yield '' - hdr_fs = self.squeezed_hdr_fs_fs.format( - nw = cw.num, - dw = self.age_w, - txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '', - iw = cw.inputs, - ow = cw.outputs ) - - fs = self.squeezed_fs_fs.format( - nw = cw.num, - dw = self.age_w, - txid_fs = f'{{i:{cw.txid}}} ' if self.show_txid else '' ) - yield hdr_fs.format( n = '', t = 'TxID', @@ -127,9 +118,9 @@ class TwTxHistory(MMGenObject,TwCommon,metaclass=AsyncInit): i = d.vouts_disp( 'inputs', width=cw.inputs, color=color ), A = d.amt_disp(self.show_total_amt).fmt( prec=self.disp_prec, color=color ), o = d.vouts_disp( 'outputs', width=cw.outputs, color=color ), - c = d.comment.fmt( width=cw.comment, color=color ) ).rstrip() + c = d.comment.fmt( width=cw.comment, color=color, nullrepl='-' ) ).rstrip() - def gen_detail_display(self,data,cw,color): + def gen_detail_display(self,data,cw,hdr_fs,fs,color): if self.sinceblock: yield f'Displaying transactions since block {self.sinceblock.hl(color=color)}' diff --git a/mmgen/tw/unspent.py b/mmgen/tw/unspent.py index df2515cc..b1be415d 100755 --- a/mmgen/tw/unspent.py +++ b/mmgen/tw/unspent.py @@ -20,8 +20,6 @@ twuo: Tracking wallet unspent outputs class for the MMGen suite """ -from collections import namedtuple - from ..globalvars import g from ..util import msg,suf,fmt from ..base_obj import AsyncInit @@ -41,6 +39,14 @@ from .common import TwCommon,TwMMGenID,get_tw_label class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit): + class display_type(TwCommon.display_type): + + class squeezed(TwCommon.display_type.squeezed): + cols = ('num','txid','vout','addr','mmid','comment','amt','amt2','date') + + class detail(TwCommon.display_type.detail): + cols = ('num','txid','vout','addr','mmid','amt','amt2','block','date_time','comment') + def __new__(cls,proto,*args,**kwargs): return MMGenObject.__new__(proto.base_proto_subclass(cls,'tw','unspent')) @@ -124,120 +130,94 @@ class TwUnspentOutputs(MMGenObject,TwCommon,metaclass=AsyncInit): return data def get_column_widths(self,data,wide=False): + # min screen width: 80 cols + # num txid vout addr [mmid] [comment] amt [amt2] date + maxws_nice = {'txid': 12} + if self.show_mmid: + maxws_nice['addr'] = 16 - self.cols = self.get_term_columns(g.min_screen_width) + return self.compute_column_widths( + widths = { # fixed cols + 'num': max(2,len(str(len(data)))+1), + 'vout': 4, + 'mmid': max(len(d.twmmid.disp) for d in data) if self.show_mmid else 0, + 'amt': self.disp_prec + 5, + 'amt2': 0, + 'block': self.age_col_params['block'][0] if wide else 0, + 'date_time': self.age_col_params['date_time'][0] if wide else 0, + 'date': self.age_w, + 'spc': 7 if self.show_mmid else 5, # 7(5) spaces in fs + }, + maxws = { # expandable cols + 'txid': self.txid_w, + 'addr': max(len(d.addr) for d in data), + 'comment': max(d.comment.screen_width for d in data) if self.show_mmid else 0, + }, + minws = { + 'txid': 7, + 'addr': 10, + 'comment': len('Comment') if self.show_mmid else 0, + }, + maxws_nice = maxws_nice, + wide = wide, + ) - # allow for 7-digit confirmation nums - col1_w = max(3,len(str(len(data)))+1) # num + ')' - mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in data) or 12 # DEADBEEF:S:1 - max_acct_w = max(i.comment.screen_width for i in data) + mmid_w + 1 - max_btcaddr_w = max(len(i.addr) for i in data) - min_addr_w = self.cols - self.col_adj - addr_w = min(max_btcaddr_w + (0,1+max_acct_w)[self.show_mmid],min_addr_w) - acct_w = min(max_acct_w, max(24,addr_w-10)) - btaddr_w = addr_w - acct_w - 1 - comment_w = acct_w - mmid_w - 1 - tx_w = min(self.txid_w,self.cols-addr_w-29-col1_w) # min=6 TODO + def gen_squeezed_display(self,data,cw,hdr_fs,fs,color): - return namedtuple( - 'column_widths', - ['num','mmid','addr','btaddr','comment','tx'] - )(col1_w, mmid_w, addr_w, btaddr_w, comment_w, tx_w) - - def gen_squeezed_display(self,data,cw,color): - fs = self.squeezed_fs_fs.format( cw=cw.num, tw=cw.tx ) - hdr_fs = self.squeezed_hdr_fs_fs.format( cw=cw.num, tw=cw.tx ) yield hdr_fs.format( - n = 'Num', - t = 'TXid'.ljust(cw.tx - 2) + ' Vout', - a = 'Address'.ljust(cw.addr), - A = f'Amt({self.proto.dcoin})'.ljust(self.disp_prec+5), - A2 = f' Amt({self.proto.coin})'.ljust(self.disp_prec+4), - c = self.age_hdr ).rstrip() - - for n,i in enumerate(data): - addr_dots = '|' + '.'*(cw.addr-1) - mmid_disp = MMGenID.fmtc( - ( - '.'*cw.mmid if i.skip == 'addr' else - i.twmmid if i.twmmid.type == 'mmgen' else - f'Non-{g.proj_name}' - ), - width = cw.mmid, - color = color ) - - if self.show_mmid: - addr_out = '{} {}{}'.format(( - type(i.addr).fmtc(addr_dots,width=cw.btaddr,color=color) if i.skip == 'addr' else - i.addr.fmt(width=cw.btaddr,color=color) - ), - mmid_disp, - (' ' + i.comment.fmt(width=cw.comment,color=color)) if cw.comment > 0 else '' - ) - else: - addr_out = ( - type(i.addr).fmtc(addr_dots,width=cw.addr,color=color) if i.skip=='addr' else - i.addr.fmt(width=cw.addr,color=color) ) + n = '', + t = 'TxID', + v = 'Vout', + a = 'Address', + m = 'MMGenID', + c = 'Comment', + A = 'Amt({})'.format(self.proto.dcoin), + B = 'Amt({})'.format(self.proto.coin), + d = self.age_hdr ) + for n,d in enumerate(data): yield fs.format( - n = str(n+1)+')', - t = ( - '' if not i.txid else - ' ' * (cw.tx-4) + '|...' if i.skip == 'txid' else - i.txid.truncate(width=cw.tx,color=True) ), - v = i.vout, - a = addr_out, - A = i.amt.fmt(color=color,prec=self.disp_prec), - A2 = (i.amt2.fmt(color=color,prec=self.disp_prec) if i.amt2 is not None else ''), - c = self.age_disp(i,self.age_fmt), - ).rstrip() + n = str(n+1)+')', + t = (CoinTxID.fmtc('|' + '.'*(cw.txid-1),color=color) if d.skip == 'txid' + else d.txid.truncate(width=cw.txid,color=color)) if cw.txid else None, + v = ' ' + d.vout.fmt(width=cw.vout-1,color=color) if cw.vout else None, + a = type(d.addr).fmtc('|' + '.'*(cw.addr-1),width=cw.addr,color=color) if d.skip == 'addr' + else d.addr.fmt(width=cw.addr,color=color), + m = (MMGenID.fmtc('.'*cw.mmid,color=color) if d.skip == 'addr' + else d.twmmid.fmt(width=cw.mmid,color=color)) if cw.mmid else None, + c = d.comment.fmt(width=cw.comment,color=color,nullrepl='-') if cw.comment else None, + A = d.amt.fmt(color=color,prec=self.disp_prec), + B = d.amt2.fmt(color=color,prec=self.disp_prec) if cw.amt2 else None, + d = self.age_disp(d,self.age_fmt), + ) - def gen_detail_display(self,data,cw,color): + def gen_detail_display(self,data,cw,hdr_fs,fs,color): - addr_w = max(len(i.addr) for i in data) - mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in data) or 12 # DEADBEEF:S:1 + yield hdr_fs.format( + n = '', + t = 'TxID', + v = 'Vout', + a = 'Address', + m = 'MMGenID', + A = 'Amt({})'.format(self.proto.dcoin), + B = 'Amt({})'.format(self.proto.coin) if cw.amt2 else None, + b = 'Block', + D = 'Date/Time', + c = 'Comment' ).rstrip() - fs = self.wide_fs_fs.format( - tw = self.txid_w + 3, - cf = '{c:<8} ', - aw = self.proto.coin_amt.max_prec + 5 ) - - yield fs.format( - n = 'Num', - t = 'Tx ID,Vout', - a = 'Address'.ljust(addr_w), - m = 'MMGen ID'.ljust(mmid_w), - A = f'Amount({self.proto.dcoin})', - A2 = f'Amount({self.proto.coin})', - c = 'Confs', # skipped for eth - b = 'Block', # skipped for eth - D = 'Date', - l = 'Label' ) - - max_comment_len = max([len(i.comment) for i in data if i.comment] or [2]) - - for n,i in enumerate(data): + for n,d in enumerate(data): yield fs.format( - n = str(n+1) + ')', - t = '{},{}'.format( - ('|'+'.'*63 if i.skip == 'txid' and self.group else i.txid), - i.vout ), - a = ( - '|'+'.' * addr_w if i.skip == 'addr' and self.group else - i.addr.fmt(color=color,width=addr_w) ), - m = MMGenID.fmtc( i.twmmid.disp, width=mmid_w, color=color ), - A = i.amt.fmt(color=color), - A2 = ( i.amt2.fmt(color=color) if i.amt2 is not None else '' ), - c = i.confs, - b = self.rpc.blockcount - (i.confs - 1), - D = self.age_disp(i,'date_time'), - l = i.comment.hl(color=color) if i.comment else - TwComment.fmtc( - s = '', - color = color, - nullrepl = '-', - width = max_comment_len ) - ).rstrip() + n = str(n+1) + ')', + t = d.txid.fmt(color=color) if cw.txid else None, + v = ' ' + d.vout.fmt(width=cw.vout-1,color=color) if cw.vout else None, + a = d.addr.fmt(width=cw.addr,color=color), + m = d.twmmid.fmt(width=cw.mmid,color=color), + A = d.amt.fmt(color=color,prec=self.disp_prec), + B = d.amt2.fmt(color=color,prec=self.disp_prec) if cw.amt2 else None, + b = self.age_disp(d,'block'), + D = self.age_disp(d,'date_time'), + c = d.comment.fmt(width=cw.comment,color=color,nullrepl='-'), + ).rstrip() def display_total(self): msg('\nTotal unspent: {} {} ({} output{})'.format(