Made better cmd error msgs.
ArAbstractSelect will euggest a matching option if, an invalid arg was passed & a matching one exists at. If an invalid subcommand aliases were passed, a matching subcommand will be suggested. After feedback from MonMarty a few misc messages was changed.
This commit is contained in:
parent
f3ad2a40ba
commit
6176369f35
@ -7,7 +7,10 @@ public class Lang
|
||||
|
||||
public static final String COMMAND_SENDER_MUST_BE_PLAYER = "<b>This command can only be used by ingame players.";
|
||||
public static final String COMMAND_SENDER_MUSNT_BE_PLAYER = "<b>This command can not be used by ingame players.";
|
||||
public static final String COMMAND_TO_FEW_ARGS = "<b>Too few arguments. <i>Use like this:";
|
||||
public static final String COMMAND_TO_MANY_ARGS = "<b>Strange arguments %s<b>.";
|
||||
public static final String COMMAND_TO_MANY_ARGS2 = "<i>Use the command like this:";
|
||||
public static final String COMMAND_TOO_FEW_ARGS = "<b>Not enough command input. <i>You should use it like this:";
|
||||
public static final String COMMAND_TOO_MANY_ARGS = "<b>Too much command input %s<b>.";
|
||||
public static final String COMMAND_TOO_MANY_ARGS2 = "<i>You should use the command like this:";
|
||||
public static final String COMMAND_NO_SUCH_SUB = "<b>The server couldn't find the command \"<c>%s<b>\".";
|
||||
public static final String COMMAND_SUGGEST_SUB = "<i>Maybe you could try %s";
|
||||
public static final String COMMAND_GET_HELP = "<i>Use %s <i>to see commands.";
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@ -102,6 +103,7 @@ public class MassiveCommand
|
||||
protected List<MassiveCommand> subCommands;
|
||||
public List<MassiveCommand> getSubCommands() { return this.subCommands; }
|
||||
public void setSubCommands(List<MassiveCommand> subCommands) { this.subCommands = subCommands; }
|
||||
public boolean isParentCommand() { return this.getSubCommands().size() > 0; }
|
||||
|
||||
public MassiveCommand getSubCommand(String alias)
|
||||
{
|
||||
@ -437,8 +439,8 @@ public class MassiveCommand
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
msg(Lang.COMMAND_TO_FEW_ARGS);
|
||||
sender.sendMessage(this.getUseageTemplate());
|
||||
msg(Lang.COMMAND_TOO_FEW_ARGS);
|
||||
sendMessage(this.getUseageTemplate());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -447,11 +449,33 @@ public class MassiveCommand
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
// Get the to many string slice
|
||||
List<String> theToMany = args.subList(this.getRequiredArgs().size() + this.optionalArgs.size(), args.size());
|
||||
msg(Lang.COMMAND_TO_MANY_ARGS, Txt.implodeCommaAndDot(theToMany, Txt.parse("<aqua>%s"), Txt.parse("<b>, "), Txt.parse("<b> and "), ""));
|
||||
msg(Lang.COMMAND_TO_MANY_ARGS2);
|
||||
sender.sendMessage(this.getUseageTemplate());
|
||||
if (this.isParentCommand())
|
||||
{
|
||||
String arg = this.arg(0);
|
||||
|
||||
// Try Levenshtein
|
||||
List<String> matches = this.getSimilarSubcommandAliases(arg, this.getMaxLevenshteinDistanceForArg(arg));
|
||||
|
||||
msg(Lang.COMMAND_NO_SUCH_SUB, this.getUseageTemplate() + " " + arg);
|
||||
if ( ! matches.isEmpty())
|
||||
{
|
||||
String suggest = Txt.parse(Txt.implodeCommaAnd(matches, "<i>, <c>", " <i>or <c>"));
|
||||
msg(Lang.COMMAND_SUGGEST_SUB, this.getUseageTemplate() + " " + suggest);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg(Lang.COMMAND_GET_HELP, this.getUseageTemplate());
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the too many string slice
|
||||
List<String> theTooMany = args.subList(this.getRequiredArgs().size() + this.optionalArgs.size(), args.size());
|
||||
msg(Lang.COMMAND_TOO_MANY_ARGS, Txt.implodeCommaAndDot(theTooMany, Txt.parse("<aqua>%s"), Txt.parse("<b>, "), Txt.parse("<b> and "), ""));
|
||||
msg(Lang.COMMAND_TOO_MANY_ARGS2);
|
||||
sendMessage(this.getUseageTemplate());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -462,6 +486,47 @@ public class MassiveCommand
|
||||
return this.isArgsValid(args, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// MATCHING SUGGESTIONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public List<String> getSimilarAliases(String arg, int maxLevenshteinDistance)
|
||||
{
|
||||
arg = arg.toLowerCase();
|
||||
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for (String alias : this.getAliases())
|
||||
{
|
||||
String aliaslc = alias.toLowerCase();
|
||||
int distance = StringUtils.getLevenshteinDistance(arg, aliaslc);
|
||||
if (distance > maxLevenshteinDistance) continue;
|
||||
matches.add(alias);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
public List<String> getSimilarSubcommandAliases(String arg, int maxLevenshteinDistance)
|
||||
{
|
||||
// Try Levenshtein
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for (MassiveCommand sub : this.getSubCommands())
|
||||
{
|
||||
matches.addAll(sub.getSimilarAliases(arg, maxLevenshteinDistance));
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
public int getMaxLevenshteinDistanceForArg(String arg)
|
||||
{
|
||||
if (arg.length() <= 1) return 0; // When dealing with 1 character aliases, there is way too many options. So we don't suggest.
|
||||
if (arg.length() <= 3) return 1; // When dealing with low length aliases, there too many options. So we won't suggest much
|
||||
if (arg.length() < 8) return 2; // 2 is default.
|
||||
|
||||
return 3; // If it were 8 characters or more, we end up here. Because many characters allow for more typos.
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// HELP AND USAGE INFORMATION
|
||||
// -------------------------------------------- //
|
||||
|
@ -1,7 +1,10 @@
|
||||
package com.massivecraft.massivecore.cmd.arg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveException;
|
||||
@ -33,36 +36,68 @@ public abstract class ARAbstractSelect<T> extends ArgReaderAbstract<T>
|
||||
{
|
||||
T result = this.select(arg, sender);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
MassiveException exception = new MassiveException();
|
||||
exception.addMsg("<b>No %s matches \"<h>%s<b>\".", this.typename(), arg);
|
||||
|
||||
if (this.canList(sender))
|
||||
{
|
||||
Collection<String> names = this.altNames(sender);
|
||||
if (names.size() == 0)
|
||||
{
|
||||
exception.addMsg("<i>Note: There is no %s available.", this.typename());
|
||||
}
|
||||
else if (names.size() > LIST_COUNT_MAX)
|
||||
{
|
||||
exception.addMsg("<i>More than %d alternatives available.", LIST_COUNT_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
String format = Txt.parse("<h>%s");
|
||||
String comma = Txt.parse("<i>, ");
|
||||
String and = Txt.parse(" <i>or ");
|
||||
String dot = Txt.parse("<i>.");
|
||||
exception.addMsg("<i>Use %s", Txt.implodeCommaAndDot(names, format, comma, and, dot));
|
||||
}
|
||||
}
|
||||
|
||||
throw exception;
|
||||
}
|
||||
if (result != null) return result;
|
||||
|
||||
return result;
|
||||
MassiveException exception = new MassiveException();
|
||||
exception.addMsg("<b>No %s matches \"<h>%s<b>\".", this.typename(), arg);
|
||||
|
||||
if (this.canList(sender))
|
||||
{
|
||||
Collection<String> names = this.altNames(sender);
|
||||
|
||||
// Try Levenshtein
|
||||
List<String> matches = this.getMatchingAltNames(arg, sender, this.getMaxLevenshteinDistanceForArg(arg));
|
||||
|
||||
if (names.isEmpty())
|
||||
{
|
||||
exception.addMsg("<i>Note: There is no %s available.", this.typename());
|
||||
}
|
||||
else if ( ! matches.isEmpty() && matches.size() < LIST_COUNT_MAX)
|
||||
{
|
||||
// For some reason the arguments doesn't get parsed.
|
||||
String suggest = Txt.parse(Txt.implodeCommaAnd(matches, "<i>, <h>", " <i>or <h>"));
|
||||
exception.addMsg("<i>Did you mean <h>%s<i>?", suggest);
|
||||
}
|
||||
else if (names.size() > LIST_COUNT_MAX)
|
||||
{
|
||||
exception.addMsg("<i>More than %d alternatives available.", LIST_COUNT_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
String format = Txt.parse("<h>%s");
|
||||
String comma = Txt.parse("<i>, ");
|
||||
String and = Txt.parse(" <i>or ");
|
||||
String dot = Txt.parse("<i>.");
|
||||
exception.addMsg("<i>Use %s", Txt.implodeCommaAndDot(names, format, comma, and, dot));
|
||||
}
|
||||
}
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
public List<String> getMatchingAltNames(String arg, CommandSender sender, int maxLevenshteinDistance)
|
||||
{
|
||||
arg = arg.toLowerCase();
|
||||
|
||||
// Try Levenshtein
|
||||
List<String> matches = new ArrayList<String>();
|
||||
|
||||
for (String alias : this.altNames(sender))
|
||||
{
|
||||
String aliaslc = alias.toLowerCase();
|
||||
int distance = StringUtils.getLevenshteinDistance(arg, aliaslc);
|
||||
if (distance > maxLevenshteinDistance) continue;
|
||||
matches.add(alias);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
public int getMaxLevenshteinDistanceForArg(String arg)
|
||||
{
|
||||
if (arg.length() <= 1) return 0; // When dealing with 1 character aliases, there is way too many options.
|
||||
if (arg.length() < 8) return 1; // 1 is default.
|
||||
|
||||
return 2; // If it were 8 characters or more, we end up here. Because many characters allow for more typos.
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user