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`
This commit is contained in:
		
							
								
								
									
										2
									
								
								lib/spack/external/argparse.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								lib/spack/external/argparse.py
									
									
									
									
										vendored
									
									
								
							@@ -356,8 +356,6 @@ def _format_usage(self, usage, actions, groups, prefix):
 | 
				
			|||||||
                pos_usage = format(positionals, groups)
 | 
					                pos_usage = format(positionals, groups)
 | 
				
			||||||
                opt_parts = _re.findall(part_regexp, opt_usage)
 | 
					                opt_parts = _re.findall(part_regexp, opt_usage)
 | 
				
			||||||
                pos_parts = _re.findall(part_regexp, pos_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
 | 
					                # helper for wrapping lines
 | 
				
			||||||
                def get_lines(parts, indent, prefix=None):
 | 
					                def get_lines(parts, indent, prefix=None):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,7 @@
 | 
				
			|||||||
from __future__ import print_function
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import inspect
 | 
					import inspect
 | 
				
			||||||
import pstats
 | 
					import pstats
 | 
				
			||||||
@@ -127,6 +128,22 @@ def index_commands():
 | 
				
			|||||||
    return index
 | 
					    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):
 | 
					class SpackArgumentParser(argparse.ArgumentParser):
 | 
				
			||||||
    def format_help_sections(self, level):
 | 
					    def format_help_sections(self, level):
 | 
				
			||||||
        """Format help on sections for a particular verbosity level.
 | 
					        """Format help on sections for a particular verbosity level.
 | 
				
			||||||
@@ -182,14 +199,11 @@ def add_subcommand_group(title, commands):
 | 
				
			|||||||
            new_actions = [opts[letter] for letter in show_options]
 | 
					            new_actions = [opts[letter] for letter in show_options]
 | 
				
			||||||
            self._optionals._group_actions = new_actions
 | 
					            self._optionals._group_actions = new_actions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options = ''.join(opt.option_strings[0].strip('-')
 | 
					        # custom, more concise usage for top level
 | 
				
			||||||
                          for opt in self._optionals._group_actions)
 | 
					        help_options = self._optionals._group_actions
 | 
				
			||||||
 | 
					        help_options = help_options + [self._positionals._group_actions[-1]]
 | 
				
			||||||
        index = index_commands()
 | 
					        formatter.add_usage(
 | 
				
			||||||
 | 
					            self.usage, help_options, self._mutually_exclusive_groups)
 | 
				
			||||||
        # usage
 | 
					 | 
				
			||||||
        formatter.add_text(
 | 
					 | 
				
			||||||
            "usage: %s [-%s] <command> [...]" % (self.prog, options))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # description
 | 
					        # description
 | 
				
			||||||
        formatter.add_text(self.description)
 | 
					        formatter.add_text(self.description)
 | 
				
			||||||
@@ -198,7 +212,9 @@ def add_subcommand_group(title, commands):
 | 
				
			|||||||
        formatter.add_text(intro_by_level[level])
 | 
					        formatter.add_text(intro_by_level[level])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # add argument groups based on metadata in commands
 | 
					        # add argument groups based on metadata in commands
 | 
				
			||||||
 | 
					        index = index_commands()
 | 
				
			||||||
        sections = index[level]
 | 
					        sections = index[level]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for section in sorted(sections):
 | 
					        for section in sorted(sections):
 | 
				
			||||||
            if section == 'help':
 | 
					            if section == 'help':
 | 
				
			||||||
                continue   # Cover help in the epilog.
 | 
					                continue   # Cover help in the epilog.
 | 
				
			||||||
@@ -235,6 +251,18 @@ def add_subcommand_group(title, commands):
 | 
				
			|||||||
        # determine help from format above
 | 
					        # determine help from format above
 | 
				
			||||||
        return formatter.format_help()
 | 
					        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):
 | 
					    def add_command(self, cmd_name):
 | 
				
			||||||
        """Add one subcommand to this parser."""
 | 
					        """Add one subcommand to this parser."""
 | 
				
			||||||
        # lazily initialize any subparsers
 | 
					        # lazily initialize any subparsers
 | 
				
			||||||
@@ -263,13 +291,14 @@ def format_help(self, level='short'):
 | 
				
			|||||||
            return super(SpackArgumentParser, self).format_help()
 | 
					            return super(SpackArgumentParser, self).format_help()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def make_argument_parser():
 | 
					def make_argument_parser(**kwargs):
 | 
				
			||||||
    """Create an basic argument parser without any subcommands added."""
 | 
					    """Create an basic argument parser without any subcommands added."""
 | 
				
			||||||
    parser = SpackArgumentParser(
 | 
					    parser = SpackArgumentParser(
 | 
				
			||||||
        formatter_class=argparse.RawTextHelpFormatter, add_help=False,
 | 
					        formatter_class=SpackHelpFormatter, add_help=False,
 | 
				
			||||||
        description=(
 | 
					        description=(
 | 
				
			||||||
            "A flexible package manager that supports multiple versions,\n"
 | 
					            "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 names in groups of 7, for nice wrapping.
 | 
				
			||||||
    stat_lines = list(zip(*(iter(stat_names),) * 7))
 | 
					    stat_lines = list(zip(*(iter(stat_names),) * 7))
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user