Add tab-completion API. Fixes BUKKIT-2181. Adds BUKKIT-2602

CommandMap contains a method that will auto-complete commands
appropriately. Before the first space, it searches for commands of which
the sender has permission. After the first space, it delegates to the
individual command.

Vanilla commands contain implementations to mimic vanilla
implementation. Exception would be give, that allows for name matching;
a feature we already allowed as part of the command is now supported for
auto-complete as well.

Plugin commands can get a tab completer set to delegate the completion
for. If no tab completer is set, it can check the executor to see if it
implements the tab completion interface. It will also attempt to chain
calls if null gets returned from these interfaces. Plugins also
implement the new TabCompleter interface, to add ease-of-use for plugin
developers, similar to the onCommand() method.

The default command implementation simply searches for player names.

To help facilitate command completion, a utility class was added with
two functions. One checks two strings, to see if the specified string
starts with (ignoring case) the second. The other method uses the first
to selectively copy elements from one collection to another.

By: Score_Under <seejay.11@gmail.com>
This commit is contained in:
Bukkit/Spigot
2012-10-09 14:54:12 -05:00
parent 74f83f3098
commit 14c7734fb1
43 changed files with 904 additions and 51 deletions

View File

@@ -0,0 +1,49 @@
package org.bukkit.util;
import java.util.Collection;
import org.apache.commons.lang.Validate;
public class StringUtil {
/**
* Copies all elements from the iterable collection of originals to the collection provided.
*
* @param token String to search for
* @param originals An iterable collection of strings to filter.
* @param collection The collection to add matches to
* @return the collection provided that would have the elements copied into
* @throws UnsupportedOperationException if the collection is immutable and originals contains a string which starts with the specified search string.
* @throws IllegalArgumentException if any parameter is is null
* @throws IllegalArgumentException if originals contains a null element. <b>Note: the collection may be modified before this is thrown</b>
*/
public static <T extends Collection<String>> T copyPartialMatches(final String token, final Iterable<String> originals, final T collection) throws UnsupportedOperationException, IllegalArgumentException {
Validate.notNull(token, "Search token cannot be null");
Validate.notNull(collection, "Collection cannot be null");
Validate.notNull(originals, "Originals cannot be null");
for (String string : originals) {
if (startsWithIgnoreCase(string, token)) {
collection.add(string);
}
}
return collection;
}
/**
* This method uses a substring to check case-insensitive equality. This means the internal array does not need to be copied like a toLowerCase() call would.
*
* @param string String to check
* @param prefix Prefix of string to compare
* @return true if provided string starts with, ignoring case, the prefix provided
* @throws NullPointerException if prefix is null
* @throws IllegalArgumentException if string is null
*/
public static boolean startsWithIgnoreCase(final String string, final String prefix) throws IllegalArgumentException, NullPointerException {
Validate.notNull(string, "Cannot check a null string for a match");
if (string.length() < prefix.length()) {
return false;
}
return string.substring(0, prefix.length()).equalsIgnoreCase(prefix);
}
}