opts, help: contextual usage screens

The following invocations now produce different output:

    $ mmgen-txcreate --usage
    $ mmgen-txcreate --usage --coin=eth
This commit is contained in:
The MMGen Project 2025-01-31 16:00:47 +00:00
commit 4eb7c64560
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
7 changed files with 37 additions and 9 deletions

View file

@ -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

View file

@ -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())

View file

@ -20,6 +20,11 @@ class help_notes:
self.proto = proto
self.cfg = cfg
def txcreate_args(self):
return (
'<addr,amt>' if self.proto.base_coin == 'ETH' else
'[<addr,amt> ...] <change addr, addrlist ID or addr type>')
def account_info_desc(self):
return 'account info' if self.proto.base_coin == 'ETH' else 'unspent outputs'

View file

@ -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,amt> ...] <change addr, addrlist ID or addr type> [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'),

View file

@ -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,amt> ...] <change addr, addrlist ID or addr type> [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,

View file

@ -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

View file

@ -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')