Browse Source

CoinAmt: improve columnar formatting

The MMGen Project 2 years ago
parent
commit
9c07442191

+ 10 - 17
mmgen/amt.py

@@ -38,7 +38,6 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class
 	max_prec = 0      # number of decimal places for this coin
 	max_amt  = None   # coin supply if known, otherwise None
 	units    = ()     # defined unit names, e.g. ('satoshi',...)
-	amt_fs   = '0.0'  # format string for the fmt() method
 
 	def __new__(cls,num,from_unit=None,from_decimal=False):
 		if type(num) == cls:
@@ -73,21 +72,18 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class
 	def fmtc(cls):
 		cls.method_not_implemented()
 
-	def fmt(self,fs=None,color=False,suf='',prec=1000):
-		if fs == None:
-			fs = self.amt_fs
+	def fmt(self,color=False,iwidth=1,prec=None): # iwidth: width of the integer part
 		s = self.__str__()
-		if '.' in fs:
-			p1,p2 = list(map(int,fs.split('.',1)))
-			ss = s.split('.',1)
-			if len(ss) == 2:
-				a,b = ss
-				ret = a.rjust(p1) + '.' + ((b+suf).ljust(p2+len(suf)))[:prec]
-			else:
-				ret = s.rjust(p1) + suf + (' ' * (p2+1))[:prec+1-len(suf)]
+		prec = prec or self.max_prec
+		if '.' in s:
+			a,b = s.split('.',1)
+			return self.colorize(
+				a.rjust(iwidth) + '.' + b.ljust(prec)[:prec], # truncation, not rounding!
+				color = color )
 		else:
-			ret = s.ljust(int(fs))
-		return self.colorize(ret,color=color)
+			return self.colorize(
+				s.rjust(iwidth).ljust(iwidth+prec+1),
+				color = color )
 
 	def hl(self,color=True):
 		return self.colorize(self.__str__(),color=color)
@@ -165,7 +161,6 @@ class BTCAmt(CoinAmt):
 	max_amt = 21000000
 	satoshi = Decimal('0.00000001')
 	units = ('satoshi',)
-	amt_fs = '4.8'
 
 class BCHAmt(BTCAmt):
 	pass
@@ -177,7 +172,6 @@ class XMRAmt(CoinAmt):
 	max_prec = 12
 	atomic = Decimal('0.000000000001')
 	units = ('atomic',)
-	amt_fs = '4.12'
 
 # Kwei (babbage) 3, Mwei (lovelace) 6, Gwei (shannon) 9, µETH (szabo) 12, mETH (finney) 15, ETH 18
 class ETHAmt(CoinAmt):
@@ -189,7 +183,6 @@ class ETHAmt(CoinAmt):
 	szabo   = Decimal('0.000001')
 	finney  = Decimal('0.001')
 	units   = ('wei','Kwei','Mwei','Gwei','szabo','finney')
-	amt_fs  = '4.18'
 
 	def toWei(self):
 		return int(Decimal(self) // self.wei)

+ 1 - 1
mmgen/data/version

@@ -1 +1 @@
-13.3.dev19
+13.3.dev20

+ 1 - 1
mmgen/proto/eth/tw/addresses.py

@@ -48,7 +48,7 @@ Actions: [q]uit, r[e]draw, [D]elete address, add [l]abel:
 				'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,
+				'amt':  self.amt_widths['amt'],
 				'date': 0,
 				'block': 0,
 				'date_time': 0,

+ 2 - 2
mmgen/proto/eth/tw/unspent.py

@@ -75,8 +75,8 @@ Actions:         [q]uit view, [p]rint to file, pager [v]iew, [w]ide view,
 			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.has_amt2 else 0,
+				'amt': self.amt_widths['amt'],
+				'amt2': self.amt_widths.get('amt2',0),
 				'spc': (5 if self.show_mmid else 3) + self.has_amt2, # 5(3) spaces in fs
 				'txid': 0,
 				'vout': 0,

+ 3 - 3
mmgen/tw/addresses.py

@@ -131,7 +131,7 @@ class TwAddresses(TwView):
 				'num':  max(2,len(str(len(data)))+1),
 				'mmid': max(len(d.twmmid.disp) for d in data),
 				'used': 4,
-				'amt':  self.disp_prec + 5,
+				'amt':  self.amt_widths['amt'],
 				'date': self.age_w if self.has_age else 0,
 				'block': self.age_col_params['block'][0] if wide and self.has_age else 0,
 				'date_time': self.age_col_params['date_time'][0] if wide and self.has_age else 0,
@@ -179,7 +179,7 @@ class TwAddresses(TwView):
 				u = yes if d.recvd else no,
 				a = d.addr.fmt( color=color, width=cw.addr ),
 				c = d.comment.fmt( width=cw.comment, color=color, nullrepl='-' ),
-				A = d.amt.fmt( color=color, prec=self.disp_prec ),
+				A = d.amt.fmt( color=color, iwidth=cw.iwidth, prec=self.disp_prec ),
 				d = self.age_disp( d, self.age_fmt )
 			)
 
@@ -208,7 +208,7 @@ class TwAddresses(TwView):
 				u = yes if d.recvd else no,
 				a = d.addr.fmt( color=color, width=cw.addr ),
 				c = d.comment.fmt( width=cw.comment, color=color, nullrepl='-' ),
-				A = d.amt.fmt( color=color, prec=self.disp_prec ),
+				A = d.amt.fmt( color=color, iwidth=cw.iwidth, prec=self.disp_prec ),
 				b = self.age_disp( d, 'block' ),
 				D = self.age_disp( d, 'date_time' ),
 			).rstrip()

+ 1 - 1
mmgen/tw/bal.py

@@ -69,7 +69,7 @@ class TwGetBalance(MMGenObject,metaclass=AsyncInit):
 					return len(str(int(max(v[colname] for v in self.data.values())))) + iwidth_adj
 
 				def make_col(label,col):
-					return(self.data[label][col].fmt(fs=f'{iwidths[col]}.{add_w-1}',color=color))
+					return(self.data[label][col].fmt(iwidth=iwidths[col],color=color))
 
 				if color:
 					from ..color import red,green,yellow

+ 8 - 2
mmgen/tw/txhistory.py

@@ -12,6 +12,8 @@
 tw.txhistory: Tracking wallet transaction history class for the MMGen suite
 """
 
+from collections import namedtuple
+
 from ..util import fmt
 from ..objmethods import MMGenObject
 from ..obj import NonNegativeInt
@@ -49,6 +51,10 @@ class TwTxHistory(TwView):
 	def filter_data(self):
 		return (d for d in self.data if d.confirmations > 0 or self.show_unconfirmed)
 
+	def set_amt_widths(self,data):
+		amts_tuple = namedtuple('amts_data',['amt'])
+		return super().set_amt_widths([amts_tuple(d.amt_disp(self.show_total_amt)) for d in data])
+
 	def get_column_widths(self,data,wide=False):
 
 		# var cols: inputs outputs comment [txid]
@@ -77,7 +83,7 @@ class TwTxHistory(TwView):
 		widths = { # fixed cols
 			'num': max(2,len(str(len(data)))+1),
 			'date': self.age_w,
-			'amt': self.disp_prec + 5,
+			'amt': self.amt_widths['amt'],
 			'spc': 6 + self.show_txid, # 5(6) spaces between cols + 1 leading space in fs
 		}
 
@@ -109,7 +115,7 @@ class TwTxHistory(TwView):
 				t = d.txid_disp( width=cw.txid, color=color ) if hasattr(cw,'txid') else None,
 				d = d.age_disp( self.age_fmt, width=self.age_w, color=color ),
 				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 ),
+				A = d.amt_disp(self.show_total_amt).fmt( iwidth=cw.iwidth, 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, nullrepl='-' ) ).rstrip()
 

+ 6 - 6
mmgen/tw/unspent.py

@@ -132,8 +132,8 @@ class TwUnspentOutputs(TwView):
 				'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,
+				'amt': self.amt_widths['amt'],
+				'amt2': self.amt_widths.get('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,
@@ -177,8 +177,8 @@ class TwUnspentOutputs(TwView):
 				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,
+				A = d.amt.fmt( color=color, iwidth=cw.iwidth, prec=self.disp_prec ),
+				B = d.amt2.fmt( color=color, iwidth=cw.iwidth2, prec=self.disp_prec ) if cw.amt2 else None,
 				d = self.age_disp(d,self.age_fmt),
 			)
 
@@ -203,8 +203,8 @@ class TwUnspentOutputs(TwView):
 				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,
+				A = d.amt.fmt( color=color, iwidth=cw.iwidth, prec=self.disp_prec ),
+				B = d.amt2.fmt( color=color, iwidth=cw.iwidth2, 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='-' ),

+ 10 - 0
mmgen/tw/view.py

@@ -121,6 +121,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 		if self.has_wallet:
 			from .ctl import TrackingWallet
 			self.wallet = await TrackingWallet(proto,mode='w')
+		self.amt_keys = {'amt':'iwidth','amt2':'iwidth2'} if self.has_amt2 else {'amt':'iwidth'}
 
 	@property
 	def age_w(self):
@@ -225,10 +226,12 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 
 		def do_ret(freews):
 			widths.update({k:minws[k] + freews.get(k,0) for k in minws})
+			widths.update({ikey: widths[key] - self.disp_prec - 1 for key,ikey in self.amt_keys.items()})
 			return namedtuple('column_widths',widths.keys())(*widths.values())
 
 		def do_ret_max():
 			widths.update({k:max(minws[k],maxws[k]) for k in minws})
+			widths.update({ikey: widths[key] - self.disp_prec - 1 for key,ikey in self.amt_keys.items()})
 			return namedtuple('column_widths',widths.keys())(*widths.values())
 
 		def get_freews(cols,varws,varw,minw):
@@ -308,6 +311,12 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 			self.proto.dcoin
 		) if hasattr(self,'total') else ''
 
+	def set_amt_widths(self,data):
+		# width of amts column: min(7,width of integer part) + len('.') + width of fractional part
+		self.amt_widths = {k:
+			min(7,max(len(str(getattr(d,k).to_integral_value())) for d in data)) + 1 + self.disp_prec
+				for k in self.amt_keys}
+
 	async def format(self,display_type,color=True,cached=False,interactive=False):
 
 		if not cached:
@@ -322,6 +331,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 			data = self.disp_data = list(self.filter_data()) # method could be a generator
 
 			if data and dt.need_column_widths:
+				self.set_amt_widths(data)
 				cw = self.get_column_widths(data,wide=dt.detail)
 				cwh = cw._asdict()
 				fp = self.fs_params

+ 1 - 1
mmgen/xmrwallet.py

@@ -276,7 +276,7 @@ class MoneroWalletOps:
 			uarg_info = xmrwallet_uarg_info
 
 			def fmt_amt(amt):
-				return self.proto.coin_amt(amt,from_unit='atomic').fmt(fs='5.12',color=True)
+				return self.proto.coin_amt(amt,from_unit='atomic').fmt( iwidth=5, prec=12, color=True )
 			def hl_amt(amt):
 				return self.proto.coin_amt(amt,from_unit='atomic').hl()