From 822c9235f49d839258f74c233c8336ef7fd7f41a Mon Sep 17 00:00:00 2001 From: Yves P Date: Mon, 31 Jul 2017 23:11:47 +0200 Subject: [PATCH] Improve the logic to find the best guess from an unknown item (command or option) --- src/Console/ConsoleOptionParser.php | 30 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Console/ConsoleOptionParser.php b/src/Console/ConsoleOptionParser.php index f10502732de..31f2b9c1180 100644 --- a/src/Console/ConsoleOptionParser.php +++ b/src/Console/ConsoleOptionParser.php @@ -793,7 +793,7 @@ public function getCommandError($command) { $rootCommand = $this->getCommand(); $subcommands = array_keys((array)$this->subcommands()); - $bestGuess = $this->findClosestCommand($command, $subcommands); + $bestGuess = $this->findClosestItem($command, $subcommands); $out = []; @@ -819,21 +819,31 @@ public function getCommandError($command) } /** - * Tries to guess the command the user originally wanted using the levenshtein algorithm. + * Tries to guess the item name the user originally wanted using the levenshtein algorithm. * - * @param string $command Unknown command name trying to be dispatched. - * @param array $subcommands List of subcommands name this shell supports. - * @return string|null The closest name to the command submitted by the user. + * @param string $needle Unknown item (either a subcommand name or an option for instance) trying to be used. + * @param array $haystack List of items available for the type $needle belongs to. + * @return string|null The closest name to the item submitted by the user. */ - protected function findClosestCommand($command, $subcommands) + protected function findClosestItem($needle, $haystack) { $bestGuess = null; - foreach ($subcommands as $subcommand) { - $score = levenshtein($command, $subcommand); + foreach ($haystack as $item) { + if (preg_match('/^' . $needle . '/', $item, $matches)) { + return $item; + } + } + + foreach ($haystack as $item) { + if (preg_match('/' . $needle . '/', $item, $matches)) { + return $item; + } + + $score = levenshtein($needle, $item); if (!isset($bestScore) || $score < $bestScore) { - $bestScore = $score; - $bestGuess = $subcommand; + $bestScore = levenshtein($needle, $item); + $bestGuess = $item; } }