Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 17 additions & 23 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2398,7 +2398,8 @@ def _alias_list(self, args: argparse.Namespace) -> None:
alias_parser = Cmd2ArgumentParser(description=alias_description, epilog=alias_epilog, prog='alias')

# Add subcommands to alias
alias_subparsers = alias_parser.add_subparsers()
alias_subparsers = alias_parser.add_subparsers(dest='subcommand')
alias_subparsers.required = True

# alias -> create
alias_create_help = "create or overwrite an alias"
Expand Down Expand Up @@ -2453,13 +2454,9 @@ def _alias_list(self, args: argparse.Namespace) -> None:
@with_argparser(alias_parser, preserve_quotes=True)
def do_alias(self, args: argparse.Namespace) -> None:
"""Manage aliases"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
func(self, args)
else:
# noinspection PyTypeChecker
self.do_help('alias')
# Call whatever subcommand function was selected
func = getattr(args, 'func')
func(self, args)

# ----- Macro subcommand functions -----

Expand Down Expand Up @@ -2578,7 +2575,8 @@ def _macro_list(self, args: argparse.Namespace) -> None:
macro_parser = Cmd2ArgumentParser(description=macro_description, epilog=macro_epilog, prog='macro')

# Add subcommands to macro
macro_subparsers = macro_parser.add_subparsers()
macro_subparsers = macro_parser.add_subparsers(dest='subcommand')
macro_subparsers.required = True

# macro -> create
macro_create_help = "create or overwrite a macro"
Expand Down Expand Up @@ -2655,13 +2653,9 @@ def _macro_list(self, args: argparse.Namespace) -> None:
@with_argparser(macro_parser, preserve_quotes=True)
def do_macro(self, args: argparse.Namespace) -> None:
"""Manage macros"""
func = getattr(args, 'func', None)
if func is not None:
# Call whatever subcommand function was selected
func(self, args)
else:
# noinspection PyTypeChecker
self.do_help('macro')
# Call whatever subcommand function was selected
func = getattr(args, 'func')
func(self, args)

def complete_help_command(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""Completes the command argument of help"""
Expand All @@ -2672,9 +2666,9 @@ def complete_help_command(self, text: str, line: str, begidx: int, endidx: int)
strs_to_match = list(topics | visible_commands)
return utils.basic_complete(text, line, begidx, endidx, strs_to_match)

def complete_help_subcommand(self, text: str, line: str, begidx: int, endidx: int,
arg_tokens: Dict[str, List[str]]) -> List[str]:
"""Completes the subcommand argument of help"""
def complete_help_subcommands(self, text: str, line: str, begidx: int, endidx: int,
arg_tokens: Dict[str, List[str]]) -> List[str]:
"""Completes the subcommands argument of help"""

# Make sure we have a command whose subcommands we will complete
command = arg_tokens['command'][0]
Expand All @@ -2688,7 +2682,7 @@ def complete_help_subcommand(self, text: str, line: str, begidx: int, endidx: in
return []

# Combine the command and its subcommand tokens for the AutoCompleter
tokens = [command] + arg_tokens['subcommand']
tokens = [command] + arg_tokens['subcommands']

from .argparse_completer import AutoCompleter
completer = AutoCompleter(argparser, self)
Expand All @@ -2698,8 +2692,8 @@ def complete_help_subcommand(self, text: str, line: str, begidx: int, endidx: in
"detailed help for a specific command")
help_parser.add_argument('command', nargs=argparse.OPTIONAL, help="command to retrieve help for",
completer_method=complete_help_command)
help_parser.add_argument('subcommand', nargs=argparse.REMAINDER, help="subcommand to retrieve help for",
completer_method=complete_help_subcommand)
help_parser.add_argument('subcommands', nargs=argparse.REMAINDER, help="subcommand(s) to retrieve help for",
completer_method=complete_help_subcommands)
help_parser.add_argument('-v', '--verbose', action='store_true',
help="print a list of all commands with descriptions of each")

Expand All @@ -2723,7 +2717,7 @@ def do_help(self, args: argparse.Namespace) -> None:
if func is not None and argparser is not None:
from .argparse_completer import AutoCompleter
completer = AutoCompleter(argparser, self)
tokens = [args.command] + args.subcommand
tokens = [args.command] + args.subcommands

# Set end to blank so the help output matches how it looks when "command -h" is used
self.poutput(completer.format_help(tokens), end='')
Expand Down
6 changes: 4 additions & 2 deletions tests/test_cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1620,7 +1620,8 @@ def test_get_settable_completion_items(base_app):

def test_alias_no_subcommand(base_app):
out, err = run_cmd(base_app, 'alias')
assert "Usage: alias [-h]" in out[0]
assert "Usage: alias [-h]" in err[0]
assert "Error: the following arguments are required: subcommand" in err[1]

def test_alias_create(base_app):
# Create the alias
Expand Down Expand Up @@ -1713,7 +1714,8 @@ def test_multiple_aliases(base_app):

def test_macro_no_subcommand(base_app):
out, err = run_cmd(base_app, 'macro')
assert "Usage: macro [-h]" in out[0]
assert "Usage: macro [-h]" in err[0]
assert "Error: the following arguments are required: subcommand" in err[1]

def test_macro_create(base_app):
# Create the macro
Expand Down
2 changes: 1 addition & 1 deletion tests/test_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,7 @@ def test_cmd2_help_subcommand_completion_with_flags_before_command(scu_app):
first_match = complete_tester(text, line, begidx, endidx, scu_app)
assert first_match is not None and scu_app.completion_matches == ['bar', 'foo', 'sport']

def test_complete_help_subcommand_with_blank_command(scu_app):
def test_complete_help_subcommands_with_blank_command(scu_app):
text = ''
line = 'help "" {}'.format(text)
endidx = len(line)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_transcript.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,13 @@ def test_generate_transcript_stop(capsys):
os.close(fd)

# This should run all commands
commands = ['help', 'alias']
commands = ['help', 'set']
app._generate_transcript(commands, transcript_fname)
_, err = capsys.readouterr()
assert err.startswith("2 commands")

# Since quit returns True for stop, only the first 2 commands will run
commands = ['help', 'quit', 'alias']
commands = ['help', 'quit', 'set']
app._generate_transcript(commands, transcript_fname)
_, err = capsys.readouterr()
assert err.startswith("Command 2 triggered a stop")
Expand Down