From 0ec7bca054f0e4ce818aadd6dd0fddb18480e1be Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 31 Jan 2025 16:00:47 +0000 Subject: [PATCH] opts, help: minor fixes & cleanups --- mmgen/help/__init__.py | 70 ++++++++++++++++++++++------------------ mmgen/help/help_notes.py | 18 ++++++++++- mmgen/main_txcreate.py | 5 +-- mmgen/main_txdo.py | 3 +- mmgen/opts.py | 6 ++-- 5 files changed, 65 insertions(+), 37 deletions(-) diff --git a/mmgen/help/__init__.py b/mmgen/help/__init__.py index b156a093..2639fae0 100755 --- a/mmgen/help/__init__.py +++ b/mmgen/help/__init__.py @@ -44,6 +44,31 @@ def show_hash_presets(cfg): msg(' N = memory usage (power of two)\n p = iterations (rounds)') sys.exit(0) +def gen_arg_tuple(cfg, func, text): + + def help_notes(k): + import importlib + return getattr(importlib.import_module( + f'{cfg._opts.help_pkg}.help_notes').help_notes(proto, cfg), k)() + + def help_mod(modname): + import importlib + return importlib.import_module( + f'{cfg._opts.help_pkg}.{modname}').help(proto, cfg) + + from ..protocol import init_proto_from_cfg + proto = init_proto_from_cfg(cfg, need_amt=True) + + d = { + 'proto': proto, + 'help_notes': help_notes, + 'help_mod': help_mod, + 'cfg': cfg, + } + + for arg in func.__code__.co_varnames: + yield d[arg] if arg in d else text + def make_usage_str(cfg, caller): indent, col1_w = { 'help': (2, len(gc.prog_name) + 1), @@ -52,7 +77,11 @@ def make_usage_str(cfg, caller): def gen(): ulbl = 'USAGE:' for line in [cfg._usage_data.strip()] if isinstance(cfg._usage_data, str) else cfg._usage_data: - yield f'{ulbl:{col1_w}} {gc.prog_name} {line}' + yield '{a:{w}} {b} {c}'.format( + a = ulbl, + b = gc.prog_name, + c = line, + w = col1_w) ulbl = '' return ('\n' + (' ' * indent)).join(gen()) @@ -64,27 +93,6 @@ class Help: def make(self, cfg, opts): - def gen_arg_tuple(func, text): - - def help_notes(k): - import importlib - return getattr(importlib.import_module( - f'{opts.help_pkg}.help_notes').help_notes(proto, cfg), k)() - - def help_mod(modname): - import importlib - return importlib.import_module( - f'{opts.help_pkg}.{modname}').help(proto, cfg) - - d = { - 'proto': proto, - 'help_notes': help_notes, - 'help_mod': help_mod, - 'cfg': cfg, - } - for arg in func.__code__.co_varnames: - yield d[arg] if arg in d else text - def gen_output(): yield ' {} {}'.format(gc.prog_name.upper() + ':', opts.opts_data['text']['desc'].strip()) yield make_usage_str(cfg, caller='help') @@ -93,21 +101,19 @@ class Help: # process code for options opts_text = nl.join(self.gen_text(opts)) if 'options' in code: - yield code['options'](*tuple(gen_arg_tuple(code['options'], opts_text))) + yield code['options'](*gen_arg_tuple(cfg, code['options'], opts_text)) else: yield opts_text # process code for notes if 'notes' in text: if 'notes' in code: - yield from code['notes'](*tuple(gen_arg_tuple(code['notes'], text['notes']))).splitlines() + yield from code['notes'](*gen_arg_tuple(cfg, code['notes'], text['notes'])).splitlines() else: yield from text['notes'].splitlines() - from ..protocol import init_proto_from_cfg - proto = init_proto_from_cfg(cfg, need_amt=True) text = getattr(opts, self.data_desc)['text'] - code = getattr(opts, self.data_desc)['code'] + code = getattr(opts, self.data_desc).get('code', {}) nl = '\n ' return nl.join(gen_output()) + '\n' @@ -146,7 +152,7 @@ class GlobalHelp(Help): skipping = False coin_filter_codes = opts.global_filter_codes.coin cmd_filter_codes = opts.global_filter_codes.cmd - for line in opts.global_opts_data['text']['options'][1:-3].splitlines(): + for line in opts.global_opts_data['text']['options'][1:].rstrip().splitlines(): m = global_opts_help_pat.match(line) if m[1] == '+': if not skipping: @@ -159,9 +165,11 @@ class GlobalHelp(Help): def print_help(cfg, opts): - if not 'code' in opts.opts_data: - opts.opts_data['code'] = {} + if cfg.help: + help_cls = CmdHelp + else: + help_cls = GlobalHelp from ..ui import do_pager - do_pager((CmdHelp if cfg.help else GlobalHelp)().make(cfg, opts)) + do_pager(help_cls().make(cfg, opts)) sys.exit(0) diff --git a/mmgen/help/help_notes.py b/mmgen/help/help_notes.py index 8328f4e5..9dd2c203 100755 --- a/mmgen/help/help_notes.py +++ b/mmgen/help/help_notes.py @@ -20,6 +20,9 @@ class help_notes: self.proto = proto self.cfg = cfg + def account_info_desc(self): + return 'account info' if self.proto.base_coin == 'ETH' else 'unspent outputs' + def fee_spec_letters(self, use_quotes=False): cu = self.proto.coin_amt.units sep, conj = ((',', ' or '), ("','", "' or '"))[use_quotes] @@ -139,7 +142,20 @@ seed, the same seed length and hash preset parameters must always be used. addr = t.privhex2addr('bead' * 16) sample_addr = addr.views[addr.view_pref] - return f""" + if self.proto.base_coin == 'ETH': + return f""" +EXAMPLES: + + Send 0.123 {self.proto.coin} to an external {self.proto.name} address: + + $ {gc.prog_name} {sample_addr},0.123 + + Send 0.123 {self.proto.coin} to another account in wallet 01ABCDEF: + + $ {gc.prog_name} 01ABCDEF:{mmtype}:7,0.123 +""" + else: + return f""" EXAMPLES: Send 0.123 {self.proto.coin} to an external {self.proto.name} address, returning the change to a diff --git a/mmgen/main_txcreate.py b/mmgen/main_txcreate.py index 87f7ca71..35193568 100755 --- a/mmgen/main_txcreate.py +++ b/mmgen/main_txcreate.py @@ -36,7 +36,7 @@ opts_data = { ‘mmgen-autosign’). The removable device is mounted and unmounted automatically -A, --fee-adjust= f Adjust transaction fee by factor 'f' (see below) --B, --no-blank Don't blank screen before displaying unspent outputs +-B, --no-blank Don't blank screen before displaying {a_info} -c, --comment-file=f Source the transaction's comment from file 'f' -C, --fee-estimate-confs=c Desired number of confirmations for fee estimation (default: {cfg.fee_estimate_confs}) @@ -49,7 +49,7 @@ opts_data = { See FEE SPECIFICATION below. If omitted, fee will be calculated using network fee estimation. -g, --gas= g Specify start gas amount in Wei (ETH only) --i, --info Display unspent outputs and exit +-i, --info Display {a_info} and exit -I, --inputs= i Specify transaction inputs (comma-separated list of MMGen IDs or coin addresses). Note that ALL unspent outputs associated with each address will be included. @@ -69,6 +69,7 @@ opts_data = { }, 'code': { 'options': lambda cfg, proto, help_notes, s: s.format( + a_info = help_notes('account_info_desc'), fu = help_notes('rel_fee_desc'), fl = help_notes('fee_spec_letters'), fe_all = fmt_list(cfg._autoset_opts['fee_estimate_mode'].choices, fmt='no_spc'), diff --git a/mmgen/main_txdo.py b/mmgen/main_txdo.py index 364913d6..7f2cb399 100755 --- a/mmgen/main_txdo.py +++ b/mmgen/main_txdo.py @@ -36,7 +36,7 @@ opts_data = { -A, --fee-adjust= f Adjust transaction fee by factor 'f' (see below) -b, --brain-params=l,p Use seed length 'l' and hash preset 'p' for brainwallet input --B, --no-blank Don't blank screen before displaying unspent outputs +-B, --no-blank Don't blank screen before displaying {a_info} -c, --comment-file= f Source the transaction's comment from file 'f' -C, --fee-estimate-confs=c Desired number of confirmations for fee estimation (default: {cfg.fee_estimate_confs}) @@ -107,6 +107,7 @@ FMT CODES: cfg = cfg, pnm = gc.proj_name, pnl = gc.proj_name.lower(), + a_info = help_notes('account_info_desc'), kgs = help_notes('keygen_backends'), coin_id = help_notes('coin_id'), fu = help_notes('rel_fee_desc'), diff --git a/mmgen/opts.py b/mmgen/opts.py index d3aa6ca8..9b87b93f 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -150,9 +150,11 @@ def process_uopts(cfg, opts_data, opts, need_proto): return uopts, uargs -cmd_opts_pat = re.compile(r'^-([a-zA-Z0-9-]), --([a-zA-Z0-9-]{2,64})(=| )(.+)') -global_opts_pat = re.compile(r'^\t\t\t(.)(.) --([a-z0-9-]{2,64})(=| )(.+)') +cmd_opts_pat = re.compile(r'^-([a-zA-Z0-9-]), --([a-zA-Z0-9-]{2,64})(=| )(.+)') + +global_opts_pat = re.compile(r'^\t\t\t(.)(.) --([a-z0-9-]{2,64})(=| )(.+)') global_opts_help_pat = re.compile(r'^\t\t\t(.)(.) (?:--([{}a-zA-Z0-9-]{2,64})(=| ))?(.+)') + opt_tuple = namedtuple('cmdline_option', ['name', 'has_parm']) def parse_opts(cfg, opts_data, opt_filter, global_opts_data, global_filter_codes, need_proto):