[Console] Added suggest on bad command name
This commit is contained in:
parent
2ae1f90cbe
commit
dd0d97e643
@ -557,7 +557,14 @@ class Application
|
|||||||
|
|
||||||
$abbrevs = static::getAbbreviations(array_unique($aliases));
|
$abbrevs = static::getAbbreviations(array_unique($aliases));
|
||||||
if (!isset($abbrevs[$searchName])) {
|
if (!isset($abbrevs[$searchName])) {
|
||||||
throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $name));
|
$message = sprintf('Command "%s" is not defined.', $name);
|
||||||
|
|
||||||
|
if ($alternatives = $this->findAlternativeCommands($searchName)) {
|
||||||
|
$message .= PHP_EOL.'Did you mean one of these?'.PHP_EOL.' ';
|
||||||
|
$message .= implode(PHP_EOL.' ', $alternatives);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($abbrevs[$searchName]) > 1) {
|
if (count($abbrevs[$searchName]) > 1) {
|
||||||
@ -915,4 +922,27 @@ class Application
|
|||||||
|
|
||||||
return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
|
return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds alternative commands of $name
|
||||||
|
*
|
||||||
|
* @param string $name The full name of the command
|
||||||
|
* @return array A sorted array of similar commands
|
||||||
|
*/
|
||||||
|
private function findAlternativeCommands($name)
|
||||||
|
{
|
||||||
|
$alternatives = array();
|
||||||
|
|
||||||
|
foreach ($this->commands as $command) {
|
||||||
|
$commandName = $command->getName();
|
||||||
|
$lev = levenshtein($name, $commandName);
|
||||||
|
if ($lev <= strlen($name) / 3 || false !== strpos($commandName, $name)) {
|
||||||
|
$alternatives[$commandName] = $lev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($alternatives);
|
||||||
|
|
||||||
|
return array_keys($alternatives);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->fail('->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
$this->fail('->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
||||||
$this->assertEquals('Command "f" is not defined.', $e->getMessage(), '->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
$this->assertRegExp('/Command "f" is not defined./', $e->getMessage(), '->find() throws an \InvalidArgumentException if the abbreviation is ambiguous for a namespace');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -203,6 +203,45 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFindAlternativeCommands()
|
||||||
|
{
|
||||||
|
$application = new Application();
|
||||||
|
|
||||||
|
$application->add(new \FooCommand());
|
||||||
|
$application->add(new \Foo1Command());
|
||||||
|
$application->add(new \Foo2Command());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$application->find($commandName = 'Unknow command');
|
||||||
|
$this->fail('->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
$this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without alternatives');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$application->find($commandName = 'foo');
|
||||||
|
$this->fail('->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
$this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||||
|
$this->assertRegExp('/foo:bar/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar"');
|
||||||
|
$this->assertRegExp('/foo1:bar/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo1:bar"');
|
||||||
|
$this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar1"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if "foo1" command throw an "\InvalidArgumentException" and does not contain
|
||||||
|
// "foo:bar" as alternative because "foo1" is too far from "foo:bar"
|
||||||
|
try {
|
||||||
|
$application->find($commandName = 'foo1');
|
||||||
|
$this->fail('->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
|
||||||
|
$this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
|
||||||
|
$this->assertFalse(strpos($e->getMessage(), 'foo:bar'), '->find() throws an \InvalidArgumentException if command does not exist, without "foo:bar" alternative');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetCatchExceptions()
|
public function testSetCatchExceptions()
|
||||||
{
|
{
|
||||||
$application = new Application();
|
$application = new Application();
|
||||||
|
Reference in New Issue
Block a user