-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Console: sorting command suggestions #10893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
👍 |
What this function tries to do is to find best matching command, so if you type |
What about this? 1.If the exact string can be found in one of the commands (for example Alternatively in case one a second list could be shown with the levenshtein matches. (but i think two lists below each other are confusing and maybe too long) |
@flip111 Your suggestion looks good to me. |
So i made this now private function permutation($array) {
switch (count($array)) {
case 0:
case 1:
return array($array);
}
foreach ($array as $k => $v) {
$copy = $array;
unset($copy[$k]);
foreach ($this->permutation($copy) as $other) {
$other[] = $v;
$return[] = $other;
}
}
return $return;
}
/**
* Finds alternative of $name among $collection,
* if nothing is found in $collection, try in $abbrevs.
*
* @param string $name The string
* @param array|\Traversable $collection The collection
*
* @return array A sorted array of similar string
*/
private function findAlternatives($name, $collection)
{
$alternatives = array();
$nameParts = explode(':', $name);
$namePartsCount = count($nameParts);
foreach ($collection as $item) {
// Saving the collectionParts by item, we might need them later
$collectionParts[$item] = explode(':', $item);
$notFoundCount = count(array_diff($nameParts, $collectionParts[$item]));
if ($notFoundCount < $namePartsCount) {
$alternatives[] = $item;
}
}
if (count($alternatives) !== 0) {
sort($alternatives);
return $alternatives;
}
foreach ($collectionParts as $fullName => $parts) {
$score = PHP_INT_MAX;
// Find all different orders of how to match collectionName to name
// use the best match
foreach ($this->permutation($parts) as $i => $parts2) {
// We can only match one part onto one subname
$parts2 = array_slice($parts2, 0, $namePartsCount);
$scoreAllParts = 0;
foreach ($parts2 as $i2 => $part2) {
// We suppose it's more likely that the user gets the command
// wrong the longer it is. So we compensate by the name length.
$scoreAllParts += levenshtein($nameParts[$i2], $part2) / count($nameParts[$i2]);
}
if ($scoreAllParts < $score) {
$score = $scoreAllParts;
}
}
$alternatives[$fullName] = $score;
}
// Don't return result which are too unlikely to match
$alternatives = array_filter($alternatives, function($el) {
return $el <= 3;
});
// Sort by levenshtein first, then alfabetically
array_multisort($alternatives, array_values($alternatives), SORT_ASC, array_keys($alternatives), SORT_ASC);
return array_keys($alternatives);
} results:
I think the original implementation was confusing and also had some weird edge cases. For this implementation there probably need to be some unit tests but that's still a hurdle to take ^^ |
the results looks good to me, thats what i expected. another improvement coould be if "Did you mean" has exactly one result, the console ould ask you interactively if the command should be executed! |
@flip111 +1 |
ping @fabpot what do you think about the interactive shell to execute the command? |
@javiereguiluz, I think this shouldn't be a problem, thanks for the suggestion; I'll investigate and try to come up with a PR for this. |
… found (javiereguiluz) This PR was squashed before being merged into the 3.3-dev branch (closes #19887). Discussion ---------- Sort alternatives alphabetically when a command is not found | Q | A | | --- | --- | | Branch? | master | | Bug fix? | no | | New feature? | yes | | BC breaks? | no | | Deprecations? | no | | Tests pass? | yes | | Fixed tickets | #10893 | | License | MIT | | Doc PR | - | Commits ------- ba6c946 Sort commands like a human would do f04b1bd Sort alternatives alphabetically when a command is not found
The function to get the alternative commands does some kind of sorting on a
$threshold
variable as it looks like. The function docblock does not describe this functionality and i don't understand why it would not just order alphabetically which seems much more user friendly??Typing
console doctrine
gives:And alphabetically this would look like:
For example
doctrine:migrations
are now grouped togetherThe text was updated successfully, but these errors were encountered: