From 4eb7c64560326c7abe12a8ec0ee89ef8d34f6ea4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 31 Jan 2025 16:00:47 +0000 Subject: [PATCH] opts, help: contextual usage screens The following invocations now produce different output: $ mmgen-txcreate --usage $ mmgen-txcreate --usage --coin=eth --- mmgen/cfg.py | 4 ++++ mmgen/help/__init__.py | 2 +- mmgen/help/help_notes.py | 5 +++++ mmgen/main_txcreate.py | 4 +++- mmgen/main_txdo.py | 5 +++-- mmgen/opts.py | 6 ++++-- test/cmdtest_d/ct_help.py | 20 +++++++++++++++++--- 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/mmgen/cfg.py b/mmgen/cfg.py index 1de18b58..d84c3f08 100755 --- a/mmgen/cfg.py +++ b/mmgen/cfg.py @@ -533,6 +533,10 @@ class Config(Lockable): self.coin = self.coin.upper() self.token = self.token.upper() if self.token else None + if 'usage' in self._uopts: # requires self.coin + import importlib + getattr(importlib.import_module(UserOpts.help_pkg), 'usage')(self) # exits + # self.color is finalized, so initialize color: if self.color: # MMGEN_DISABLE_COLOR sets this to False from .color import init_color diff --git a/mmgen/help/__init__.py b/mmgen/help/__init__.py index 2639fae0..14d24455 100755 --- a/mmgen/help/__init__.py +++ b/mmgen/help/__init__.py @@ -80,7 +80,7 @@ def make_usage_str(cfg, caller): yield '{a:{w}} {b} {c}'.format( a = ulbl, b = gc.prog_name, - c = line, + c = cfg._usage_code(*gen_arg_tuple(cfg, cfg._usage_code, line)) if cfg._usage_code else line, w = col1_w) ulbl = '' return ('\n' + (' ' * indent)).join(gen()) diff --git a/mmgen/help/help_notes.py b/mmgen/help/help_notes.py index 9dd2c203..6a1b8063 100755 --- a/mmgen/help/help_notes.py +++ b/mmgen/help/help_notes.py @@ -20,6 +20,11 @@ class help_notes: self.proto = proto self.cfg = cfg + def txcreate_args(self): + return ( + '' if self.proto.base_coin == 'ETH' else + '[ ...] ') + def account_info_desc(self): return 'account info' if self.proto.base_coin == 'ETH' else 'unspent outputs' diff --git a/mmgen/main_txcreate.py b/mmgen/main_txcreate.py index 35193568..d14d985d 100755 --- a/mmgen/main_txcreate.py +++ b/mmgen/main_txcreate.py @@ -28,7 +28,7 @@ opts_data = { 'sets': [('yes', True, 'quiet', True)], 'text': { 'desc': f'Create a transaction with outputs to specified coin or {gc.proj_name} addresses', - 'usage': '[opts] [ ...] [addr file ...]', + 'usage': '[opts] {u_args} [addr file ...]', 'options': """ -h, --help Print this help message --, --longhelp Print help message for long (global) options @@ -68,6 +68,8 @@ opts_data = { 'notes': '\n{c}\n{F}\n{x}', }, 'code': { + 'usage': lambda cfg, proto, help_notes, s: s.format( + u_args = help_notes('txcreate_args')), 'options': lambda cfg, proto, help_notes, s: s.format( a_info = help_notes('account_info_desc'), fu = help_notes('rel_fee_desc'), diff --git a/mmgen/main_txdo.py b/mmgen/main_txdo.py index 7f2cb399..e8eff769 100755 --- a/mmgen/main_txdo.py +++ b/mmgen/main_txdo.py @@ -28,8 +28,7 @@ opts_data = { 'sets': [('yes', True, 'quiet', True)], 'text': { 'desc': f'Create, sign and send an {gc.proj_name} transaction', - 'usage': '[opts] [ ...] [addr file ...] ' + - '[seed source ...]', + 'usage': '[opts] {u_args} [addr file ...] [seed source ...]', 'options': """ -h, --help Print this help message --, --longhelp Print help message for long (global) options @@ -102,6 +101,8 @@ FMT CODES: {x}""" }, 'code': { + 'usage': lambda cfg, proto, help_notes, s: s.format( + u_args = help_notes('txcreate_args')), 'options': lambda cfg, proto, help_notes, s: s.format( gc = gc, cfg = cfg, diff --git a/mmgen/opts.py b/mmgen/opts.py index 9b87b93f..84ebaedf 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -262,8 +262,10 @@ class Opts: cfg._parsed_opts = po cfg._use_env = True cfg._use_cfg_file = not 'skip_cfg_file' in uopts - # Make this available to usage() + + # Make these available to usage(): cfg._usage_data = opts_data['text'].get('usage2') or opts_data['text']['usage'] + cfg._usage_code = opts_data.get('code', {}).get('usage') if os.getenv('MMGEN_DEBUG_OPTS'): opt_preproc_debug(po) @@ -276,7 +278,7 @@ class Opts: class UserOpts(Opts): help_pkg = 'mmgen.help' - info_funcs = ('usage', 'version', 'show_hash_presets') + info_funcs = ('version', 'show_hash_presets') global_opts_data = { # coin code : cmd code : opt : opt param : text diff --git a/test/cmdtest_d/ct_help.py b/test/cmdtest_d/ct_help.py index ae290843..19417141 100755 --- a/test/cmdtest_d/ct_help.py +++ b/test/cmdtest_d/ct_help.py @@ -26,7 +26,9 @@ class CmdTestHelp(CmdTestBase): passthru_opts = ('daemon_data_dir', 'rpc_port', 'coin', 'testnet') cmd_group = ( ('usage1', (1, 'usage message (via --usage)', [])), - ('usage2', (1, 'usage message (via bad invocation)', [])), + ('usage2', (1, 'usage message (via --usage)', [])), + ('usage3', (1, 'usage message (via bad invocation)', [])), + ('usage4', (1, 'usage message (via bad invocation, with --coin)', [])), ('version', (1, 'version message', [])), ('license', (1, 'license message', [])), ('helpscreens', (1, 'help screens', [])), @@ -39,15 +41,27 @@ class CmdTestHelp(CmdTestBase): ) def usage1(self): - t = self.spawn('mmgen-txsend', ['--usage'], no_passthru_opts=True) - t.expect('USAGE: mmgen-txsend') + t = self.spawn('mmgen-walletgen', ['--usage'], no_passthru_opts=True) + t.expect('USAGE: mmgen-walletgen') return t def usage2(self): + cmd = 'xmrwallet' if self.coin == 'xmr' else 'txcreate' + t = self.spawn(f'mmgen-{cmd}', ['--usage', f'--coin={self.coin}'], no_passthru_opts=True) + t.expect(f'USAGE: mmgen-{cmd}') + return t + + def usage3(self): t = self.spawn('mmgen-walletgen', ['foo'], exit_val=1, no_passthru_opts=True) t.expect('USAGE: mmgen-walletgen') return t + def usage4(self): + cmd = 'xmrwallet' if self.coin == 'xmr' else 'addrgen' + t = self.spawn(f'mmgen-{cmd}', [f'--coin={self.coin}'], exit_val=1, no_passthru_opts=True) + t.expect(f'USAGE: mmgen-{cmd}') + return t + def version(self): t = self.spawn('mmgen-tool', ['--version'], exit_val=0) t.expect('MMGEN-TOOL version')