diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2018-02-11 02:37:29 -0800 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2018-02-12 20:25:17 -0800 |
commit | 1b998cbeee338a21df7a88ba77577b8f19375cfa (patch) | |
tree | cbd4de980d33b8b4c1c19045753b82554ac7a37c | |
parent | fff3cc695df9924a84215b1ea019e391b953a6a9 (diff) | |
download | spack-1b998cbeee338a21df7a88ba77577b8f19375cfa.tar.gz spack-1b998cbeee338a21df7a88ba77577b8f19375cfa.tar.bz2 spack-1b998cbeee338a21df7a88ba77577b8f19375cfa.tar.xz spack-1b998cbeee338a21df7a88ba77577b8f19375cfa.zip |
Fix issues with `spack [cmd] -h` help output
- Shorten Spack command usage for short options. Short options are now
shown as [-abc] instead of as [-a] [-b] [-c]
- fix bug that mixed long and short options for top-level `spack help`
-rw-r--r-- | lib/spack/external/argparse.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/main.py | 51 |
2 files changed, 40 insertions, 13 deletions
diff --git a/lib/spack/external/argparse.py b/lib/spack/external/argparse.py index afce7fb3dc..d2d232d51e 100644 --- a/lib/spack/external/argparse.py +++ b/lib/spack/external/argparse.py @@ -356,8 +356,6 @@ class HelpFormatter(object): pos_usage = format(positionals, groups) opt_parts = _re.findall(part_regexp, opt_usage) pos_parts = _re.findall(part_regexp, pos_usage) - assert ' '.join(opt_parts) == opt_usage - assert ' '.join(pos_parts) == pos_usage # helper for wrapping lines def get_lines(parts, indent, prefix=None): diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py index 4c2b09f6ba..f29a0a6d8b 100644 --- a/lib/spack/spack/main.py +++ b/lib/spack/spack/main.py @@ -30,6 +30,7 @@ after the system path is set up. from __future__ import print_function import sys +import re import os import inspect import pstats @@ -127,6 +128,22 @@ def index_commands(): return index +class SpackHelpFormatter(argparse.RawTextHelpFormatter): + def _format_actions_usage(self, actions, groups): + """Formatter with more concise usage strings.""" + usage = super( + SpackHelpFormatter, self)._format_actions_usage(actions, groups) + + # compress single-character flags that are not mutually exclusive + # at the beginning of the usage string + chars = ''.join(re.findall(r'\[-(.)\]', usage)) + usage = re.sub(r'\[-.\] ?', '', usage) + if chars: + return '[-%s] %s' % (chars, usage) + else: + return usage + + class SpackArgumentParser(argparse.ArgumentParser): def format_help_sections(self, level): """Format help on sections for a particular verbosity level. @@ -182,14 +199,11 @@ class SpackArgumentParser(argparse.ArgumentParser): new_actions = [opts[letter] for letter in show_options] self._optionals._group_actions = new_actions - options = ''.join(opt.option_strings[0].strip('-') - for opt in self._optionals._group_actions) - - index = index_commands() - - # usage - formatter.add_text( - "usage: %s [-%s] <command> [...]" % (self.prog, options)) + # custom, more concise usage for top level + help_options = self._optionals._group_actions + help_options = help_options + [self._positionals._group_actions[-1]] + formatter.add_usage( + self.usage, help_options, self._mutually_exclusive_groups) # description formatter.add_text(self.description) @@ -198,7 +212,9 @@ class SpackArgumentParser(argparse.ArgumentParser): formatter.add_text(intro_by_level[level]) # add argument groups based on metadata in commands + index = index_commands() sections = index[level] + for section in sorted(sections): if section == 'help': continue # Cover help in the epilog. @@ -235,6 +251,18 @@ class SpackArgumentParser(argparse.ArgumentParser): # determine help from format above return formatter.format_help() + def add_subparsers(self, **kwargs): + """Ensure that sensible defaults are propagated to subparsers""" + kwargs.setdefault('metavar', 'SUBCOMMAND') + sp = super(SpackArgumentParser, self).add_subparsers(**kwargs) + old_add_parser = sp.add_parser + + def add_parser(name, **kwargs): + kwargs.setdefault('formatter_class', SpackHelpFormatter) + return old_add_parser(name, **kwargs) + sp.add_parser = add_parser + return sp + def add_command(self, cmd_name): """Add one subcommand to this parser.""" # lazily initialize any subparsers @@ -263,13 +291,14 @@ class SpackArgumentParser(argparse.ArgumentParser): return super(SpackArgumentParser, self).format_help() -def make_argument_parser(): +def make_argument_parser(**kwargs): """Create an basic argument parser without any subcommands added.""" parser = SpackArgumentParser( - formatter_class=argparse.RawTextHelpFormatter, add_help=False, + formatter_class=SpackHelpFormatter, add_help=False, description=( "A flexible package manager that supports multiple versions,\n" - "configurations, platforms, and compilers.")) + "configurations, platforms, and compilers."), + **kwargs) # stat names in groups of 7, for nice wrapping. stat_lines = list(zip(*(iter(stat_names),) * 7)) |