[Console] Added abbreviation into search for bad command / namespace

This commit is contained in:
Grégoire Pineau 2012-02-12 17:53:56 +01:00
parent c6203bcffa
commit 8abf50639a

View File

@ -491,7 +491,11 @@ class Application
if (!isset($abbrevs[$part])) { if (!isset($abbrevs[$part])) {
$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
if ($alternatives = $this->findAlternativeNamespace($namespace)) { if (1 <= $i) {
$part = implode(':',$found).':'.$part;
}
if ($alternatives = $this->findAlternativeNamespace($part, $abbrevs)) {
$message .= "\n\nDid you mean one of these?\n "; $message .= "\n\nDid you mean one of these?\n ";
$message .= implode("\n ", $alternatives); $message .= implode("\n ", $alternatives);
} }
@ -562,11 +566,11 @@ class Application
} }
} }
$abbrevs = static::getAbbreviations(array_unique($aliases)); $aliases = static::getAbbreviations(array_unique($aliases));
if (!isset($abbrevs[$searchName])) { if (!isset($aliases[$searchName])) {
$message = sprintf('Command "%s" is not defined.', $name); $message = sprintf('Command "%s" is not defined.', $name);
if ($alternatives = $this->findAlternativeCommands($searchName)) { if ($alternatives = $this->findAlternativeCommands($searchName, $abbrevs)) {
$message .= "\n\nDid you mean one of these?\n "; $message .= "\n\nDid you mean one of these?\n ";
$message .= implode("\n ", $alternatives); $message .= implode("\n ", $alternatives);
} }
@ -574,11 +578,11 @@ class Application
throw new \InvalidArgumentException($message); throw new \InvalidArgumentException($message);
} }
if (count($abbrevs[$searchName]) > 1) { if (count($aliases[$searchName]) > 1) {
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($abbrevs[$searchName]))); throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $this->getAbbreviationSuggestions($aliases[$searchName])));
} }
return $this->get($abbrevs[$searchName][0]); return $this->get($aliases[$searchName][0]);
} }
/** /**
@ -933,45 +937,49 @@ class Application
/** /**
* Finds alternative commands of $name * Finds alternative commands of $name
* *
* @param string $name The full name of the command * @param string $name The full name of the command
* @param array $abbrevs The abbreviations
* *
* @return array A sorted array of similar commands * @return array A sorted array of similar commands
*/ */
private function findAlternativeCommands($name) private function findAlternativeCommands($name, $abbrevs)
{ {
$getNameCallback = function($command) { $callback = function($item) {
return $command->getName(); return $item->getName();
}; };
return $this->findAlternatives($name, $this->commands, $getNameCallback); return $this->findAlternatives($name, $this->commands, $abbrevs, $callback);
} }
/** /**
* Finds alternative namespace of $name * Finds alternative namespace of $name
* *
* @param string $name The full name of the namespace * @param string $name The full name of the namespace
* @param array $abbrevs The abbreviations
* *
* @return array A sorted array of similar namespace * @return array A sorted array of similar namespace
*/ */
private function findAlternativeNamespace($name) private function findAlternativeNamespace($name, $abbrevs)
{ {
return $this->findAlternatives($name, $this->getNamespaces()); return $this->findAlternatives($name, $this->getNamespaces(), $abbrevs);
} }
/** /**
* Finds alternative of $name among $collection * Finds alternative of $name among $collection,
* if nothing is found in $collection, try in $abbrevs
* *
* @param string $name The string * @param string $name The string
* @param array|Traversable $collection The collection * @param array|Traversable $collection The collecion
* @param Closure|string|array $callback The callable to transform item before comparison * @param array $abbrevs The abbreviations
* @param Closure|string|array $callback The callable to transform collection item before comparison
* *
* @return array A sorted array of similar string * @return array A sorted array of similar string
*/ */
private function findAlternatives($name, $collection, $callback = null) { private function findAlternatives($name, $collection, $abbrevs, $callback = null) {
$alternatives = array(); $alternatives = array();
foreach ($collection as $item) { foreach ($collection as $item) {
if (null !== $callback) { if(null !== $callback) {
$item = call_user_func($callback, $item); $item = call_user_func($callback, $item);
} }
@ -981,6 +989,17 @@ class Application
} }
} }
if (!$alternatives) {
foreach ($abbrevs as $key => $values) {
$lev = levenshtein($name, $key);
if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
foreach ($values as $value) {
$alternatives[$value] = $lev;
}
}
}
}
asort($alternatives); asort($alternatives);
return array_keys($alternatives); return array_keys($alternatives);