Browse Source

tw.view: new classes: scroll_action, sort_action, display_action

The MMGen Project 2 years ago
parent
commit
eb04c84f26

+ 1 - 1
mmgen/data/version

@@ -1 +1 @@
-13.3.dev29
+13.3.dev30

+ 2 - 3
mmgen/proto/btc/tw/addresses.py

@@ -33,17 +33,16 @@ Actions: [q]uit menu, r[e]draw, add [l]abel:
 		'a':'s_amt',
 		'A':'s_age',
 		'M':'s_twmmid',
-		'r':'d_reverse',
+		'r':'s_reverse',
 		'D':'d_days',
 		'e':'d_redraw',
 		'E':'d_showempty',
 		'u':'d_showused',
 		'L':'d_all_labels',
-		'q':'a_quit',
 		'v':'a_view',
 		'w':'a_view_detail',
 		'p':'a_print_detail',
-		'l':'a_comment_add' }
+		'l':'i_comment_add' }
 
 	async def get_rpc_data(self):
 

+ 1 - 2
mmgen/proto/btc/tw/prune.py

@@ -28,13 +28,12 @@ Pruning: [q]uit pruning, [p]rune, [u]nprune, [c]lear prune list:
 		'a':'s_amt',
 		'A':'s_age',
 		'M':'s_twmmid',
-		'r':'d_reverse',
+		'r':'s_reverse',
 		'D':'d_days',
 		'e':'d_redraw',
 		'E':'d_showempty',
 		'U':'d_showused',
 		'L':'d_all_labels',
-		'q':'a_quit',
 		'v':'a_view',
 		'w':'a_view_detail',
 		'p':'a_prune',

+ 1 - 2
mmgen/proto/btc/tw/txhistory.py

@@ -242,13 +242,12 @@ Filters/Actions: show [u]nconfirmed, [q]uit menu, r[e]draw:
 		'a':'s_amt',
 		'm':'s_total_amt',
 		't':'s_txid',
-		'r':'d_reverse',
+		'r':'s_reverse',
 		'D':'d_days',
 		'e':'d_redraw',
 		'u':'d_show_unconfirmed',
 		'i':'d_show_txid',
 		'T':'d_show_total_amt',
-		'q':'a_quit',
 		'v':'a_view',
 		'V':'a_view_detail',
 		'p':'a_print_squeezed',

+ 2 - 3
mmgen/proto/btc/tw/unspent.py

@@ -40,17 +40,16 @@ Actions: [q]uit menu, [p]rint, r[e]draw, add [l]abel:
 		'a':'s_amt',
 		'd':'s_addr',
 		'A':'s_age',
-		'r':'d_reverse',
 		'M':'s_twmmid',
+		'r':'s_reverse',
 		'D':'d_days',
 		'o':'d_group',
 		'm':'d_mmid',
 		'e':'d_redraw',
-		'q':'a_quit',
 		'p':'a_print_detail',
 		'v':'a_view',
 		'w':'a_view_detail',
-		'l':'a_comment_add' }
+		'l':'i_comment_add' }
 
 	async def get_rpc_data(self):
 		# bitcoin-cli help listunspent:

+ 3 - 4
mmgen/proto/eth/tw/addresses.py

@@ -30,13 +30,12 @@ Actions: [q]uit menu, r[e]draw, [D]elete addr, add [l]abel:
 	key_mappings = {
 		'a':'s_amt',
 		'M':'s_twmmid',
-		'r':'d_reverse',
+		'r':'s_reverse',
 		'e':'d_redraw',
 		'E':'d_showempty',
 		'L':'d_all_labels',
-		'q':'a_quit',
-		'l':'a_comment_add',
-		'D':'a_addr_delete',
+		'l':'i_comment_add',
+		'D':'i_addr_delete',
 		'v':'a_view',
 		'w':'a_view_detail',
 		'p':'a_print_detail' }

+ 4 - 5
mmgen/proto/eth/tw/unspent.py

@@ -54,17 +54,16 @@ Actions: [q]uit menu, [D]elete addr, add [l]abel, [R]efresh balance:
 	key_mappings = {
 		'a':'s_amt',
 		'd':'s_addr',
-		'r':'d_reverse',
+		'r':'s_reverse',
 		'M':'s_twmmid',
 		'm':'d_mmid',
 		'e':'d_redraw',
-		'q':'a_quit',
 		'p':'a_print_detail',
 		'v':'a_view',
 		'w':'a_view_detail',
-		'l':'a_comment_add',
-		'D':'a_addr_delete',
-		'R':'a_balance_refresh' }
+		'l':'i_comment_add',
+		'D':'i_addr_delete',
+		'R':'i_balance_refresh' }
 
 	no_data_errmsg = 'No accounts in tracking wallet!'
 

+ 1 - 4
mmgen/tw/addresses.py

@@ -362,10 +362,7 @@ class TwAddresses(TwView):
 		elif False in res:
 			return False
 
-	class action(TwView.action):
-
-		def s_amt(self,parent):
-			parent.do_sort('amt')
+	class display_action(TwView.display_action):
 
 		def d_showempty(self,parent):
 			parent.showempty = not parent.showempty

+ 3 - 3
mmgen/tw/prune.py

@@ -119,7 +119,7 @@ class TwAddressesPrune(TwAddresses):
 				else:
 					msg('\nInvalid keypress')
 
-		def a_prune(self,parent):
+		async def a_prune(self,parent):
 
 			def do_entry(desc,n,addrnum,e):
 				if auto[desc]:
@@ -160,13 +160,13 @@ class TwAddressesPrune(TwAddresses):
 			if parent.scroll:
 				msg_r(CUR_HOME + ERASE_ALL)
 
-		def a_unprune(self,parent):
+		async def a_unprune(self,parent):
 			for addrnum in self.get_addrnums(parent,'unprune'):
 				parent.disp_data[addrnum-1].tag = False
 
 			if parent.scroll:
 				msg_r(CUR_HOME + ERASE_ALL)
 
-		def a_clear_prune_list(self,parent):
+		async def a_clear_prune_list(self,parent):
 			for d in parent.data:
 				d.tag = False

+ 6 - 1
mmgen/tw/txhistory.py

@@ -182,7 +182,10 @@ class TwTxHistory(TwView):
 	def dump_fn_pfx(self):
 		return 'transaction-history' + (f'-since-block-{self.sinceblock}' if self.sinceblock else '')
 
-	class action(TwView.action):
+	class sort_action(TwView.sort_action):
+
+		def s_blockheight(self,parent):
+			parent.do_sort('blockheight')
 
 		def s_amt(self,parent):
 			parent.do_sort('amt')
@@ -192,6 +195,8 @@ class TwTxHistory(TwView):
 			parent.do_sort('total_amt')
 			parent.show_total_amt = True
 
+	class display_action(TwView.display_action):
+
 		def d_show_txid(self,parent):
 			parent.show_txid = not parent.show_txid
 

+ 3 - 1
mmgen/tw/unspent.py

@@ -226,12 +226,14 @@ class TwUnspentOutputs(TwView):
 				o.date = dates[idx]
 			self.dates_set = True
 
-	class action(TwView.action):
+	class sort_action(TwView.sort_action):
 
 		def s_twmmid(self,parent):
 			parent.do_sort('twmmid')
 			parent.show_mmid = True
 
+	class display_action(TwView.display_action):
+
 		def d_mmid(self,parent):
 			parent.show_mmid = not parent.show_mmid
 

+ 107 - 66
mmgen/tw/view.py

@@ -38,6 +38,17 @@ CUR_UP    = lambda n: f'\033[{n}A'
 CUR_DOWN  = lambda n: f'\033[{n}B'
 ERASE_ALL = '\033[0J'
 
+# decorator for action.run():
+def enable_echo(orig_func):
+	async def f(self,parent,action_method):
+		if parent.scroll:
+			parent.term.set('echo')
+		ret = await orig_func(self,parent,action_method)
+		if parent.scroll:
+			parent.term.set('noecho')
+		return ret
+	return f
+
 # base class for TwUnspentOutputs,TwAddresses,TwTxHistory:
 class TwView(MMGenObject,metaclass=AsyncInit):
 
@@ -495,6 +506,14 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 
 	async def view_filter_and_sort(self):
 
+		action_map = {
+			'a_': 'action',
+			's_': 'sort_action',
+			'd_': 'display_action',
+			'm_': 'scroll_action',
+			'i_': 'item_action',
+		}
+
 		def make_key_mappings(scroll):
 			if scroll:
 				for k in self.scroll_keys['vi']:
@@ -506,6 +525,8 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 		scroll = self.scroll = g.scroll
 
 		key_mappings = make_key_mappings(scroll)
+		action_classes = { k: getattr(self,action_map[v[:2]])() for k,v in key_mappings.items() }
+		action_methods = { k: getattr(v,key_mappings[k]) for k,v in action_classes.items() }
 		prompt = self.prompt_fs.strip().format(
 			s='\nScrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom' if scroll else '' )
 
@@ -516,10 +537,12 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 
 		clear_screen = '\n\n' if opt.no_blank else CUR_HOME + ('' if scroll else ERASE_ALL)
 
+		from ..term import get_term,get_char,get_char_raw
+
 		if scroll:
-			term = get_term()
-			term.register_cleanup()
-			term.set('noecho')
+			self.term = get_term()
+			self.term.register_cleanup()
+			self.term.set('noecho')
 			get_char = get_char_raw
 			msg_r(CUR_HOME + ERASE_ALL)
 
@@ -540,31 +563,18 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 
 			self.oneshot_msg = ''
 
-			if reply not in key_mappings:
-				if not scroll:
-					msg_r('\ninvalid keypress ')
-					await asyncio.sleep(0.3)
-				continue
-
-			action = key_mappings[reply]
-
-			if scroll and action.startswith('a_'): # 'a_' actions may require line input
-				term.set('echo')
-
-			if hasattr(self.action,action):
-				if action.startswith('m_'): # scrolling actions
-					self.use_cached = True
-				await self.action().run(self,action)
-			elif action.startswith('s_'): # put here to allow overriding by action method
-				self.do_sort(action[2:])
-			elif hasattr(self.item_action,action):
-				await self.item_action().run(self,action)
-			elif action == 'a_quit':
+			if reply in key_mappings:
+				ret = action_classes[reply].run(self,action_methods[reply])
+				if type(ret).__name__ == 'coroutine':
+					await ret
+			elif reply == 'q':
 				msg('')
+				if self.scroll:
+					self.term.set('echo')
 				return self.disp_data
-
-			if scroll and action.startswith('a_'):
-				term.set('noecho')
+			elif not scroll:
+				msg_r('\ninvalid keypress ')
+				await asyncio.sleep(0.3)
 
 	@property
 	def blank_prompt(self):
@@ -581,23 +591,9 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 
 	class action:
 
-		async def run(self,parent,action):
-			ret = getattr(self,action)(parent)
-			if type(ret).__name__ == 'coroutine':
-				await ret
-
-		def d_days(self,parent):
-			af = parent.age_fmts
-			parent.age_fmt = af[(af.index(parent.age_fmt) + 1) % len(af)]
-			if parent.update_widths_on_age_toggle: # TODO
-				pass
-
-		def d_redraw(self,parent):
-			msg_r(CUR_HOME + ERASE_ALL)
-
-		def d_reverse(self,parent):
-			parent.data.reverse()
-			parent.reverse = not parent.reverse
+		@enable_echo
+		async def run(self,parent,action_method):
+			return await action_method(parent)
 
 		async def a_print_detail(self,parent):
 			return await self._print(parent,output_type='detail')
@@ -647,27 +643,10 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 			msg_r(CUR_HOME)
 			do_pager( await parent.format('detail',color=True) )
 
-		async def m_cursor_up(self,parent):
-			parent.pos -= min( parent.pos - 0, 1 )
-
-		async def m_cursor_down(self,parent):
-			parent.pos += min( parent.max_pos - parent.pos, 1 )
-
-		async def m_pg_up(self,parent):
-			parent.pos -= min( parent.scrollable_height, parent.pos - 0 )
-
-		async def m_pg_down(self,parent):
-			parent.pos += min( parent.scrollable_height, parent.max_pos - parent.pos )
-
-		async def m_top(self,parent):
-			parent.pos = 0
-
-		async def m_bot(self,parent):
-			parent.pos = parent.max_pos
-
 	class item_action:
 
-		async def run(self,parent,action):
+		@enable_echo
+		async def run(self,parent,action_method):
 
 			if not parent.disp_data:
 				return
@@ -695,7 +674,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 					#  None:   action aborted by user or no action performed
 					#  False:  an error occurred
 					#  'redo': user will be re-prompted for item number
-					ret = await getattr(self,action)(parent,idx)
+					ret = await action_method(parent,idx)
 					if ret != 'redo':
 						break
 					await asyncio.sleep(0.5)
@@ -706,7 +685,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 					CUR_HOME + ERASE_ALL +
 					await parent.format(display_type='squeezed',interactive=True,scroll=True) )
 
-		async def a_balance_refresh(self,parent,idx):
+		async def i_balance_refresh(self,parent,idx):
 			if not parent.keypress_confirm(
 					f'Refreshing tracking wallet {parent.item_desc} #{idx}.  Is this what you want?'):
 				return 'redo'
@@ -714,7 +693,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 			await parent.get_data()
 			parent.oneshot_msg = yellow(f'{parent.proto.dcoin} balance for account #{idx} refreshed')
 
-		async def a_addr_delete(self,parent,idx):
+		async def i_addr_delete(self,parent,idx):
 			if not parent.keypress_confirm(
 					'Removing {} {} from tracking wallet.  Is this what you want?'.format(
 						parent.item_desc, red(f'#{idx}') )):
@@ -728,7 +707,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 				parent.oneshot_msg = red('Address could not be removed')
 				return False
 
-		async def a_comment_add(self,parent,idx):
+		async def i_comment_add(self,parent,idx):
 
 			async def do_comment_add(comment):
 
@@ -766,3 +745,65 @@ class TwView(MMGenObject,metaclass=AsyncInit):
 					return 'redo'
 
 			return await do_comment_add(res)
+
+	class scroll_action:
+
+		def run(self,parent,action_method):
+			self.use_cached = True
+			return action_method(parent)
+
+		def m_cursor_up(self,parent):
+			parent.pos -= min( parent.pos - 0, 1 )
+
+		def m_cursor_down(self,parent):
+			parent.pos += min( parent.max_pos - parent.pos, 1 )
+
+		def m_pg_up(self,parent):
+			parent.pos -= min( parent.scrollable_height, parent.pos - 0 )
+
+		def m_pg_down(self,parent):
+			parent.pos += min( parent.scrollable_height, parent.max_pos - parent.pos )
+
+		def m_top(self,parent):
+			parent.pos = 0
+
+		def m_bot(self,parent):
+			parent.pos = parent.max_pos
+
+	class sort_action:
+
+		def run(self,parent,action_method):
+			return action_method(parent)
+
+		def s_addr(self,parent):
+			parent.do_sort('addr')
+
+		def s_age(self,parent):
+			parent.do_sort('age')
+
+		def s_amt(self,parent):
+			parent.do_sort('amt')
+
+		def s_txid(self,parent):
+			parent.do_sort('txid')
+
+		def s_twmmid(self,parent):
+			parent.do_sort('twmmid')
+
+		def s_reverse(self,parent):
+			parent.data.reverse()
+			parent.reverse = not parent.reverse
+
+	class display_action:
+
+		def run(self,parent,action_method):
+			return action_method(parent)
+
+		def d_days(self,parent):
+			af = parent.age_fmts
+			parent.age_fmt = af[(af.index(parent.age_fmt) + 1) % len(af)]
+			if parent.update_widths_on_age_toggle: # TODO
+				pass
+
+		def d_redraw(self,parent):
+			msg_r(CUR_HOME + ERASE_ALL)