Skip to content

Commit a02314e

Browse files
committed
Improved UnknownSubcommandException, added StringUtils.levenshteinNearest utility method.
1 parent 07a080a commit a02314e

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

src/main/java/fr/zcraft/quartzlib/components/commands/exceptions/UnknownSubcommandException.java

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import fr.zcraft.quartzlib.components.rawtext.RawText;
77
import fr.zcraft.quartzlib.components.rawtext.RawTextPart;
88
import fr.zcraft.quartzlib.tools.text.StringUtils;
9+
import java.util.List;
10+
import java.util.stream.Collectors;
911
import org.bukkit.ChatColor;
1012
import org.bukkit.command.CommandSender;
1113
import org.jetbrains.annotations.Nullable;
@@ -33,10 +35,14 @@ public RawText display(CommandSender sender) {
3335

3436
if (nearest != null) {
3537
text = text.then("\n" + CHAT_PREFIX).color(ChatColor.AQUA)
36-
.then(" " + I.t("Did you mean") + ": ").color(ChatColor.GRAY)
38+
.then(" " + I.t("Did you mean: ")).color(ChatColor.GRAY)
3739
.then("/").color(ChatColor.WHITE)
38-
.then(getParents() + " ").color(ChatColor.AQUA)
39-
.then(nearest).color(ChatColor.DARK_AQUA);
40+
.then(getParents() + " ").style(ChatColor.AQUA, ChatColor.UNDERLINE)
41+
.hover(I.t("Click to insert this command"))
42+
.suggest("/" + getParents() + " " + nearest)
43+
.then(nearest).style(ChatColor.DARK_AQUA, ChatColor.UNDERLINE)
44+
.hover(I.t("Click to insert this command"))
45+
.suggest("/" + getParents() + " " + nearest);
4046
}
4147

4248
return text.build();
@@ -46,20 +52,12 @@ public RawText display(CommandSender sender) {
4652

4753
@Nullable
4854
private String getNearestCommand() {
49-
String nearest = null;
50-
int nearestDistance = MAX_DISTANCE;
55+
List<String> names = commandGroup.getSubCommands()
56+
.stream()
57+
.map(CommandNode::getName)
58+
.collect(Collectors.toList());
5159

52-
for (CommandNode subCommand : commandGroup.getSubCommands()) {
53-
String name = subCommand.getName();
54-
int distance = StringUtils.levenshteinDistance(attemptedSubcommand, name);
55-
56-
if (distance < nearestDistance) {
57-
nearest = name;
58-
nearestDistance = distance;
59-
}
60-
}
61-
62-
return nearest;
60+
return StringUtils.levenshteinNearest(attemptedSubcommand, names, MAX_DISTANCE);
6361
}
6462

6563
private String getParents() {

src/main/java/fr/zcraft/quartzlib/tools/text/StringUtils.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
11
package fr.zcraft.quartzlib.tools.text;
22

3+
import org.jetbrains.annotations.Nullable;
4+
35
/**
46
* Various string-related utilities.
57
*/
68
public final class StringUtils {
79
private StringUtils() {
810
}
911

12+
/**
13+
* Find the nearest from a given string among the given list of candidates,
14+
* computed based on a Levenshtein Distance.
15+
* <p>The string must be from at most a given maximum distance of all candidates, else null is returned.</p>
16+
* @param toTest The string to test.
17+
* @param candidates The list of candidates.
18+
* @param maxDistance The maximum distance.
19+
* @param <T> The type of CharSequence to test (usually String)
20+
* @return The nearest candidate to the string to test, if found within maxDistance.
21+
*/
22+
@Nullable
23+
public static <T extends CharSequence> T levenshteinNearest(T toTest, Iterable<T> candidates, int maxDistance) {
24+
T nearest = null;
25+
int nearestDistance = maxDistance;
26+
27+
for (T subCommand : candidates) {
28+
int distance = StringUtils.levenshteinDistance(toTest, subCommand);
29+
30+
if (distance < nearestDistance) {
31+
nearest = subCommand;
32+
nearestDistance = distance;
33+
}
34+
}
35+
36+
return nearest;
37+
}
38+
1039
/**
1140
* Compute the distance of Levenshtein Distance between two strings.
1241
*

0 commit comments

Comments
 (0)