Bug 1057694 - Command suggestions in mach. r=gps
This commit is contained in:
@@ -29,11 +29,12 @@ class NoCommandError(MachError):
|
||||
class UnknownCommandError(MachError):
|
||||
"""Raised when we attempted to execute an unknown command."""
|
||||
|
||||
def __init__(self, command, verb):
|
||||
def __init__(self, command, verb, suggested_commands=None):
|
||||
MachError.__init__(self)
|
||||
|
||||
self.command = command
|
||||
self.verb = verb
|
||||
self.suggested_commands = suggested_commands or []
|
||||
|
||||
class UnrecognizedArgumentError(MachError):
|
||||
"""Raised when an unknown argument is passed to mach."""
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import sys
|
||||
|
||||
from operator import itemgetter
|
||||
@@ -105,12 +106,21 @@ class CommandAction(argparse.Action):
|
||||
else:
|
||||
raise NoCommandError()
|
||||
|
||||
handler = self._mach_registrar.command_handlers.get(command)
|
||||
# Command suggestion
|
||||
if command not in self._mach_registrar.command_handlers:
|
||||
# We first try to look for a valid command that is very similar to the given command.
|
||||
suggested_commands = difflib.get_close_matches(command, self._mach_registrar.command_handlers.keys(), cutoff=0.8)
|
||||
# If we find more than one matching command, or no command at all, we give command suggestions instead
|
||||
# (with a lower matching threshold). All commands that start with the given command (for instance: 'mochitest-plain',
|
||||
# 'mochitest-chrome', etc. for 'mochitest-') are also included.
|
||||
if len(suggested_commands) != 1:
|
||||
suggested_commands = set(difflib.get_close_matches(command, self._mach_registrar.command_handlers.keys(), cutoff=0.5))
|
||||
suggested_commands |= {cmd for cmd in self._mach_registrar.command_handlers if cmd.startswith(command)}
|
||||
raise UnknownCommandError(command, 'run', suggested_commands)
|
||||
sys.stderr.write("We're assuming the '%s' command is '%s' and we're executing it for you.\n\n" % (command, suggested_commands[0]))
|
||||
command = suggested_commands[0]
|
||||
|
||||
# FUTURE consider looking for commands with similar names and
|
||||
# suggest or run them.
|
||||
if not handler:
|
||||
raise UnknownCommandError(command, 'run')
|
||||
handler = self._mach_registrar.command_handlers.get(command)
|
||||
|
||||
# FUTURE
|
||||
# If we wanted to conditionally enable commands based on whether
|
||||
|
||||
@@ -78,10 +78,14 @@ Run |mach help| to show a list of commands.
|
||||
|
||||
UNKNOWN_COMMAND_ERROR = r'''
|
||||
It looks like you are trying to %s an unknown mach command: %s
|
||||
|
||||
%s
|
||||
Run |mach help| to show a list of commands.
|
||||
'''.lstrip()
|
||||
|
||||
SUGGESTED_COMMANDS_MESSAGE = r'''
|
||||
Did you want to %s any of these commands instead: %s?
|
||||
'''
|
||||
|
||||
UNRECOGNIZED_ARGUMENT_ERROR = r'''
|
||||
It looks like you passed an unrecognized argument into mach.
|
||||
|
||||
@@ -388,7 +392,8 @@ To see more help for a specific command, run:
|
||||
print(NO_COMMAND_ERROR)
|
||||
return 1
|
||||
except UnknownCommandError as e:
|
||||
print(UNKNOWN_COMMAND_ERROR % (e.verb, e.command))
|
||||
suggestion_message = SUGGESTED_COMMANDS_MESSAGE % (e.verb, ', '.join(e.suggested_commands)) if e.suggested_commands else ''
|
||||
print(UNKNOWN_COMMAND_ERROR % (e.verb, e.command, suggestion_message))
|
||||
return 1
|
||||
except UnrecognizedArgumentError as e:
|
||||
print(UNRECOGNIZED_ARGUMENT_ERROR % (e.command,
|
||||
|
||||
Reference in New Issue
Block a user