mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-19 10:12:50 +08:00
73 lines
1.9 KiB
C#
73 lines
1.9 KiB
C#
namespace Spectre.Console.Cli;
|
|
|
|
internal static class CommandSuggestor
|
|
{
|
|
private const float SmallestDistance = 2f;
|
|
|
|
public static CommandInfo? Suggest(CommandModel model, CommandInfo? command, string name)
|
|
{
|
|
var result = (CommandInfo?)null;
|
|
|
|
var container = command ?? (ICommandContainer)model;
|
|
if (command?.IsDefaultCommand ?? false)
|
|
{
|
|
// Default commands have no children,
|
|
// so use the root commands here.
|
|
container = model;
|
|
}
|
|
|
|
var score = float.MaxValue;
|
|
foreach (var child in container.Commands.Where(x => !x.IsHidden))
|
|
{
|
|
var temp = Score(child.Name, name);
|
|
if (temp < score)
|
|
{
|
|
score = temp;
|
|
result = child;
|
|
}
|
|
}
|
|
|
|
if (score <= SmallestDistance)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static float Score(string source, string target)
|
|
{
|
|
source = source.ToUpperInvariant();
|
|
target = target.ToUpperInvariant();
|
|
|
|
var n = source.Length;
|
|
var m = target.Length;
|
|
|
|
if (n == 0)
|
|
{
|
|
return m;
|
|
}
|
|
|
|
if (m == 0)
|
|
{
|
|
return n;
|
|
}
|
|
|
|
var d = new int[n + 1, m + 1];
|
|
Enumerable.Range(0, n + 1).ToList().ForEach(i => d[i, 0] = i);
|
|
Enumerable.Range(0, m + 1).ToList().ForEach(i => d[0, i] = i);
|
|
|
|
for (var sourceIndex = 1; sourceIndex <= n; sourceIndex++)
|
|
{
|
|
for (var targetIndex = 1; targetIndex <= m; targetIndex++)
|
|
{
|
|
var cost = (target[targetIndex - 1] == source[sourceIndex - 1]) ? 0 : 1;
|
|
d[sourceIndex, targetIndex] = Math.Min(
|
|
Math.Min(d[sourceIndex - 1, targetIndex] + 1, d[sourceIndex, targetIndex - 1] + 1),
|
|
d[sourceIndex - 1, targetIndex - 1] + cost);
|
|
}
|
|
}
|
|
|
|
return d[n, m];
|
|
}
|
|
} |