Refactor Completions to be registerable - Fixes #8

Is this almost ready?! Someone try!
This commit is contained in:
Aikar
2017-04-18 21:05:38 -04:00
parent d4d2c490ca
commit 42bf77bcef
9 changed files with 107 additions and 48 deletions
@@ -365,7 +365,7 @@ public abstract class BaseCommand extends Command {
if ("@players".equals(completion)) {
return super.tabComplete(sender, commandLabel, args);
}
List<String> cmds = CommandCompletions.of(sender, completion, input);
List<String> cmds = manager.getCommandCompletions().of(sender, completion, input);
if (cmds.isEmpty()) {
cmds = ImmutableList.of(input);
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package co.aikar.commands;
import org.bukkit.entity.EntityType;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BukkitCommandCompletions extends CommandCompletions {
BukkitCommandCompletions() {
super();
registerCompletion("mobs", (sender, completionConfig, input) -> {
final Stream<String> normal = Stream.of(EntityType.values())
.map(entityType -> CommandUtil.simplifyString(entityType.getName()));
return normal.collect(Collectors.toList());
});
}
}
@@ -33,8 +33,8 @@ import org.bukkit.entity.Player;
public class BukkitCommandContexts extends CommandContexts {
BukkitCommandContexts(CommandManager manager) {
super(manager);
BukkitCommandContexts() {
super();
registerContext(OnlinePlayer.class, (c) -> {
final String playercheck = c.popFirstArg();
@@ -25,6 +25,7 @@ package co.aikar.commands;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.bukkit.plugin.Plugin;
import java.util.Map;
@@ -34,24 +35,36 @@ public class BukkitCommandManager implements CommandManager {
@SuppressWarnings("WeakerAccess")
protected final Plugin plugin;
private CommandContexts contexts;
private CommandCompletions completions;
public BukkitCommandManager(Plugin plugin) {
this.plugin = plugin;
this.contexts = new CommandContexts(this);
}
@Override
public CommandContexts getCommandContexts() {
if (this.contexts == null) {
this.contexts = new BukkitCommandContexts();
}
return contexts;
}
@Override
public CommandCompletions getCommandCompletions() {
if (this.completions == null) {
this.completions = new BukkitCommandCompletions();
}
return completions;
}
@Override
public boolean register(BaseCommand command) {
command.manager = this;
final String plugin = this.plugin.getName().toLowerCase();
final CommandMap commandMap = Bukkit.getServer().getCommandMap();
boolean allSuccess = true;
for (Map.Entry<String, Command> entry : command.registeredCommands.entrySet()) {
if (!Bukkit.getServer().getCommandMap().register(entry.getKey().toLowerCase(), plugin, entry.getValue())) {
if (!commandMap.register(entry.getKey().toLowerCase(), plugin, entry.getValue())) {
allSuccess = false;
}
}
@@ -28,47 +28,55 @@ import com.google.common.collect.Lists;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public final class CommandCompletions {
private CommandCompletions() {}
@SuppressWarnings("WeakerAccess")
public class CommandCompletions {
private Map<String, CommandCompletionHandler> completionMap = new HashMap<>();
private static final List<String> EMPTY = ImmutableList.of();
public static List<String> of(CommandSender sender, String completion, String input) {
public CommandCompletions() {
registerCompletion("range", (sender, completionConfig, input) -> {
if (completionConfig == null) {
return ImmutableList.of();
}
final String[] ranges = CommandPatterns.DASH.split(completionConfig);
int start;
int end;
if (ranges.length != 2) {
start = 0;
end = CommandUtil.parseInt(ranges[0], 0);
} else {
start = CommandUtil.parseInt(ranges[0], 0);
end = CommandUtil.parseInt(ranges[1], 0);
}
return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
});
registerCompletion("timeunits", (sender, completionConfig, input) -> ImmutableList.of("hours", "days", "weeks", "months", "minutes"));
}
public CommandCompletionHandler registerCompletion(String id, CommandCompletionHandler handler) {
return this.completionMap.put("@" + id.toLowerCase(), handler);
}
public List<String> of(CommandSender sender, String completion, String input) {
if (completion == null) {
return ImmutableList.of();
}
String[] complete = CommandPatterns.COLON.split(completion, 2);
switch (complete[0]) {
case "@range":
if (complete.length == 1) {
return ImmutableList.of();
}
final String[] ranges = CommandPatterns.DASH.split(complete[1]);
int start;
int end;
if (ranges.length != 2) {
start = 0;
end = CommandUtil.parseInt(ranges[0], 0);
} else {
start = CommandUtil.parseInt(ranges[0], 0);
end = CommandUtil.parseInt(ranges[1], 0);
}
return IntStream.rangeClosed(start, end).mapToObj(Integer::toString).collect(Collectors.toList());
case "@timeunits":
return ImmutableList.of("hours", "days", "weeks", "months", "minutes");
case "@mobs":
final Stream<String> normal = Stream.of(EntityType.values())
.map(entityType -> CommandUtil.simplifyString(entityType.getName()));
return normal.collect(Collectors.toList());
default:
return Lists.newArrayList(CommandPatterns.PIPE.split(completion));
CommandCompletionHandler handler = this.completionMap.get(complete[0].toLowerCase());
if (handler != null) {
return handler.getCompletions(sender, complete.length == 1 ? null : complete[1], input);
}
return Lists.newArrayList(CommandPatterns.PIPE.split(completion));
}
public interface CommandCompletionHandler {
List<String> getCompletions(CommandSender sender, String completionConfig, String input);
}
}
@@ -25,29 +25,20 @@ package co.aikar.commands;
import co.aikar.commands.annotation.Single;
import co.aikar.commands.annotation.Split;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Values;
import co.aikar.commands.contexts.ContextResolver;
import co.aikar.commands.contexts.OnlinePlayer;
import co.aikar.commands.contexts.SenderAwareContextResolver;
import com.google.common.collect.Maps;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Map;
@SuppressWarnings("WeakerAccess")
public class CommandContexts {
private final CommandManager manager;
private final Map<Class<?>, ContextResolver<?>> contextMap = Maps.newHashMap();
CommandContexts(CommandManager manager) {
this.manager = manager;
CommandContexts() {
registerContext(Integer.class, (c) -> {
try {
return CommandUtil.parseNumber(c.popFirstArg(), c.hasFlag("suffixes")).intValue();
@@ -37,7 +37,7 @@ import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
/*@Data*/ public class CommandExecutionContext {
public class CommandExecutionContext {
private final RegisteredCommand cmd;
private final Parameter param;
private final CommandSender sender;
@@ -26,11 +26,17 @@ package co.aikar.commands;
public interface CommandManager {
/**
* Gets the command contexts registered
* Gets the command contexts manager
* @return Command Contexts
*/
CommandContexts getCommandContexts();
/**
* Gets the command completions manager
* @return
*/
CommandCompletions getCommandCompletions();
/**
* Registers a command with ACF
*
@@ -151,7 +151,7 @@ public class RegisteredCommand {
final String[] split = CommandPatterns.PIPE.split(values.value());
Set<String> possible = Sets.newHashSet();
for (String s : split) {
List<String> check = CommandCompletions.of(sender, s, arg);
List<String> check = this.scope.manager.getCommandCompletions().of(sender, s, arg);
if (!check.isEmpty()) {
possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList()));
} else {