13
13
14
14
use Symfony \Component \Console \Descriptor \TextDescriptor ;
15
15
use Symfony \Component \Console \Descriptor \XmlDescriptor ;
16
+ use Symfony \Component \Console \Exception \AmbiguousCommandException ;
17
+ use Symfony \Component \Console \Exception \AmbiguousNamespaceException ;
16
18
use Symfony \Component \Console \Exception \ExceptionInterface ;
19
+ use Symfony \Component \Console \Exception \InvalidArgumentException ;
20
+ use Symfony \Component \Console \Exception \InvalidCommandNameException ;
21
+ use Symfony \Component \Console \Exception \UnknownCommandException ;
22
+ use Symfony \Component \Console \Exception \UnknownNamespaceException ;
17
23
use Symfony \Component \Console \Helper \DebugFormatterHelper ;
18
24
use Symfony \Component \Console \Helper \ProcessHelper ;
19
25
use Symfony \Component \Console \Helper \QuestionHelper ;
41
47
use Symfony \Component \Console \Event \ConsoleTerminateEvent ;
42
48
use Symfony \Component \Console \Exception \CommandNotFoundException ;
43
49
use Symfony \Component \Console \Exception \LogicException ;
50
+ use Symfony \Component \Console \Question \ChoiceQuestion ;
51
+ use Symfony \Component \Console \Question \ConfirmationQuestion ;
44
52
use Symfony \Component \EventDispatcher \EventDispatcherInterface ;
45
53
46
54
/**
@@ -186,7 +194,30 @@ public function doRun(InputInterface $input, OutputInterface $output)
186
194
}
187
195
188
196
// the command name MUST be the first element of the input
189
- $ command = $ this ->find ($ name );
197
+ do {
198
+ try {
199
+ $ command = $ this ->find ($ name );
200
+ } catch (CommandNotFoundException $ e ) {
201
+ $ alternatives = $ e ->getAlternatives ();
202
+ if (0 === count ($ alternatives ) || !$ input ->isInteractive () || !$ this ->getHelperSet ()->has ('question ' )) {
203
+ throw $ e ;
204
+ }
205
+
206
+ $ helper = $ this ->getHelperSet ()->get ('question ' );
207
+ $ question = new ChoiceQuestion (strtok ($ e ->getMessage (), "\n" ).' Please select one of these suggested commands? ' , $ alternatives );
208
+ $ question ->setMaxAttempts (1 );
209
+
210
+ try {
211
+ $ name = $ helper ->ask ($ input , $ output , $ question );
212
+ } catch (InvalidArgumentException $ ex ) {
213
+ throw $ e ;
214
+ }
215
+
216
+ if (null === $ name ) {
217
+ throw $ e ;
218
+ }
219
+ }
220
+ } while (!isset ($ command ));
190
221
191
222
$ this ->runningCommand = $ command ;
192
223
$ exitCode = $ this ->doRunCommand ($ command , $ input , $ output );
@@ -444,7 +475,8 @@ public function getNamespaces()
444
475
*
445
476
* @return string A registered namespace
446
477
*
447
- * @throws CommandNotFoundException When namespace is incorrect or ambiguous
478
+ * @throws UnknownNamespaceException When namespace is incorrect
479
+ * @throws AmbiguousNamespaceException When namespace is ambiguous
448
480
*/
449
481
public function findNamespace ($ namespace )
450
482
{
@@ -453,24 +485,12 @@ public function findNamespace($namespace)
453
485
$ namespaces = preg_grep ('{^ ' .$ expr .'} ' , $ allNamespaces );
454
486
455
487
if (empty ($ namespaces )) {
456
- $ message = sprintf ('There are no commands defined in the "%s" namespace. ' , $ namespace );
457
-
458
- if ($ alternatives = $ this ->findAlternatives ($ namespace , $ allNamespaces )) {
459
- if (1 == count ($ alternatives )) {
460
- $ message .= "\n\nDid you mean this? \n " ;
461
- } else {
462
- $ message .= "\n\nDid you mean one of these? \n " ;
463
- }
464
-
465
- $ message .= implode ("\n " , $ alternatives );
466
- }
467
-
468
- throw new CommandNotFoundException ($ message , $ alternatives );
488
+ throw new UnknownNamespaceException ($ namespace , $ this ->findAlternatives ($ namespace , $ allNamespaces , array ()));
469
489
}
470
490
471
491
$ exact = in_array ($ namespace , $ namespaces , true );
472
492
if (count ($ namespaces ) > 1 && !$ exact ) {
473
- throw new CommandNotFoundException ( sprintf ( ' The namespace "%s" is ambiguous (%s). ' , $ namespace , $ this -> getAbbreviationSuggestions ( array_values ( $ namespaces))), array_values ( $ namespaces ) );
493
+ throw new AmbiguousNamespaceException ( $ namespace , $ namespaces );
474
494
}
475
495
476
496
return $ exact ? $ namespace : reset ($ namespaces );
@@ -486,7 +506,8 @@ public function findNamespace($namespace)
486
506
*
487
507
* @return Command A Command instance
488
508
*
489
- * @throws CommandNotFoundException When command name is incorrect or ambiguous
509
+ * @throws UnknownCommandException When command name is incorrect
510
+ * @throws AmbiguousCommandException When command name is ambiguous
490
511
*/
491
512
public function find ($ name )
492
513
{
@@ -500,18 +521,7 @@ public function find($name)
500
521
$ this ->findNamespace (substr ($ name , 0 , $ pos ));
501
522
}
502
523
503
- $ message = sprintf ('Command "%s" is not defined. ' , $ name );
504
-
505
- if ($ alternatives = $ this ->findAlternatives ($ name , $ allCommands )) {
506
- if (1 == count ($ alternatives )) {
507
- $ message .= "\n\nDid you mean this? \n " ;
508
- } else {
509
- $ message .= "\n\nDid you mean one of these? \n " ;
510
- }
511
- $ message .= implode ("\n " , $ alternatives );
512
- }
513
-
514
- throw new CommandNotFoundException ($ message , $ alternatives );
524
+ throw new UnknownCommandException ($ name , $ this ->findAlternatives ($ name , $ allCommands , array ()));
515
525
}
516
526
517
527
// filter out aliases for commands which are already on the list
@@ -526,9 +536,7 @@ public function find($name)
526
536
527
537
$ exact = in_array ($ name , $ commands , true );
528
538
if (count ($ commands ) > 1 && !$ exact ) {
529
- $ suggestions = $ this ->getAbbreviationSuggestions (array_values ($ commands ));
530
-
531
- throw new CommandNotFoundException (sprintf ('Command "%s" is ambiguous (%s). ' , $ name , $ suggestions ), array_values ($ commands ));
539
+ throw new AmbiguousCommandException ($ name , array_values ($ commands ));
532
540
}
533
541
534
542
return $ this ->get ($ exact ? $ name : reset ($ commands ));
@@ -984,18 +992,6 @@ private function getConsoleMode()
984
992
}
985
993
}
986
994
987
- /**
988
- * Returns abbreviated suggestions in string format.
989
- *
990
- * @param array $abbrevs Abbreviated suggestions to convert
991
- *
992
- * @return string A formatted string of abbreviated suggestions
993
- */
994
- private function getAbbreviationSuggestions ($ abbrevs )
995
- {
996
- return sprintf ('%s, %s%s ' , $ abbrevs [0 ], $ abbrevs [1 ], count ($ abbrevs ) > 2 ? sprintf (' and %d more ' , count ($ abbrevs ) - 2 ) : '' );
997
- }
998
-
999
995
/**
1000
996
* Returns the namespace part of the command name.
1001
997
*
0 commit comments