From f28e4393db408c44684dd6287cb811a00eeece97 Mon Sep 17 00:00:00 2001 From: Dico Date: Thu, 27 Sep 2018 07:53:58 +0100 Subject: Streamline command help a little bit --- .../io/dico/dicore/command/ICommandAddress.java | 18 +++++++ .../dicore/command/ModifiableCommandAddress.java | 51 +++++++++++++++++--- .../io/dico/dicore/command/RootCommandAddress.java | 13 +++-- .../command/chat/AbstractChatController.java | 2 +- .../dico/dicore/command/chat/help/HelpPages.java | 2 +- .../command/chat/help/HelpTopicModifier.java | 4 +- .../dico/dicore/command/chat/help/IHelpTopic.java | 9 ++-- .../chat/help/defaults/DefaultPageBuilder.java | 2 +- .../chat/help/defaults/DescriptionHelpTopic.java | 2 +- .../chat/help/defaults/SubcommandsHelpTopic.java | 30 ++++++------ .../chat/help/defaults/SyntaxHelpTopic.java | 56 ++++++++++++++-------- .../chat/help/insertion/HelpComponentInserter.java | 2 +- .../command/chat/help/insertion/Insertions.java | 4 +- .../dicore/command/parameter/ParameterList.java | 8 ++++ 14 files changed, 146 insertions(+), 57 deletions(-) diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java index befdefa..fb0d7b4 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java @@ -5,6 +5,7 @@ import io.dico.dicore.command.parameter.ArgumentBuffer; import io.dico.dicore.command.predef.PredefinedCommand; import org.bukkit.command.CommandSender; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -109,6 +110,23 @@ public interface ICommandAddress { */ boolean isDepthLargerThan(int depth); + /** + * @return true if this address has any children. + */ + boolean hasChildren(); + + /** + * @return total number of children, not considering any aliases + */ + int getNumberOfRealChildren(); + + /** + * Get an unmodifiable view of all main keys of the children of this address. + * + * @return the main keys + */ + Collection getChildrenMainKeys(); + /** * Get an unmodifiable view of the children of this address. * Values might be duplicated for aliases. diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java index 484eb5e..6871462 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java @@ -10,10 +10,13 @@ import java.util.*; public abstract class ModifiableCommandAddress implements ICommandAddress { Map children; + Collection childrenMainKeys = Collections.emptyList(); + // the chat controller as configured by the programmer IChatController chatController; // cache for the algorithm that finds the first chat controller going up the tree transient IChatController chatControllerCache; + ModifiableCommandAddress helpChild; public ModifiableCommandAddress() { @@ -110,6 +113,21 @@ public abstract class ModifiableCommandAddress implements ICommandAddress { return false; } + @Override + public boolean hasChildren() { + return !children.isEmpty(); + } + + @Override + public int getNumberOfRealChildren() { + return childrenMainKeys.size(); + } + + @Override + public Collection getChildrenMainKeys() { + return Collections.unmodifiableCollection(childrenMainKeys); + } + @Override public Map getChildren() { return Collections.unmodifiableMap(children); @@ -140,7 +158,16 @@ public abstract class ModifiableCommandAddress implements ICommandAddress { } Iterator names = mChild.modifiableNamesIterator(); - children.put(names.next(), mChild); + String mainKey = names.next(); + + if (!childrenMainKeys.contains(mainKey)) { + if (!(childrenMainKeys instanceof ArrayList)) { + childrenMainKeys = new ArrayList<>(); + } + childrenMainKeys.add(mainKey); + } + + children.put(mainKey, mChild); while (names.hasNext()) { String name = names.next(); @@ -168,19 +195,29 @@ public abstract class ModifiableCommandAddress implements ICommandAddress { } if (removeAliases) { - for (Iterator iterator = keyTarget.namesModifiable.iterator(); iterator.hasNext(); ) { + Iterator iterator = keyTarget.namesModifiable.iterator(); + boolean first = true; + while (iterator.hasNext()) { String alias = iterator.next(); ChildCommandAddress aliasTarget = getChild(key); if (aliasTarget == keyTarget) { + if (first) { + childrenMainKeys.remove(alias); + } children.remove(alias); - iterator.remove(); } + iterator.remove(); + first = false; } - continue; - } - children.remove(key); - keyTarget.namesModifiable.remove(key); + } else { + if (key.equals(keyTarget.getMainKey())) { + childrenMainKeys.remove(key); + } + + children.remove(key); + keyTarget.namesModifiable.remove(key); + } } } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java index 7577808..c76bd14 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java @@ -217,9 +217,14 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom try { ICommandAddress target = getCommandTarget(context, buffer); - List out = target.hasCommand() - ? target.getCommand().tabComplete(sender, target, location, buffer.getUnaffectingCopy()) - : Collections.emptyList(); + + List out; + if (target.hasCommand()) { + context.targetAcquired(target, target.getCommand(), buffer); + out = target.getCommand().tabCompleteWithContext(context, location); + } else { + out = Collections.emptyList(); + } int cursor = buffer.getCursor(); String input; @@ -230,7 +235,7 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom } boolean wrapped = false; - for (String child : target.getChildren().keySet()) { + for (String child : target.getChildrenMainKeys()) { if (child.toLowerCase().startsWith(input)) { if (!wrapped) { out = new ArrayList<>(out); diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatController.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatController.java index d88e852..858337a 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatController.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatController.java @@ -88,7 +88,7 @@ public class AbstractChatController implements IChatController { case DESCRIPTION: return Formatting.GREEN; case SYNTAX: - return Formatting.BLUE; + return Formatting.AQUA; case HIGHLIGHT: return Formatting.RED; case SUBCOMMAND: diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java index 5798b3c..4382d93 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java @@ -82,7 +82,7 @@ public class HelpPages { } public @NotNull String getSyntax(Permissible viewer, ExecutionContext context, ICommandAddress address) { - List components = syntaxTopic.getComponents(address, viewer, context); + List components = syntaxTopic.getComponents(address, viewer, context, false); if (components.isEmpty()) { return getHelpPage(viewer, context, address, 1); } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java index a44822b..7aeb304 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java @@ -15,8 +15,8 @@ public abstract class HelpTopicModifier implements IHelpTopic { } @Override - public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context) { - return modify(delegate.getComponents(target, viewer, context), target, viewer, context); + public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) { + return modify(delegate.getComponents(target, viewer, context, true), target, viewer, context); } protected abstract List modify(List components, ICommandAddress target, Permissible viewer, ExecutionContext context); diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java index 618109e..0b3fba2 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java @@ -11,12 +11,13 @@ public interface IHelpTopic { /** * Get the components of this help topic * - * @param target The address of the command to provide help about - * @param viewer The permissible that the page will be shown to (null -> choose a default set). - * @param context Context of the command execution + * @param target The address of the command to provide help about + * @param viewer The permissible that the page will be shown to (null -> choose a default set). + * @param context Context of the command execution + * @param isForPage A boolean indicating if the components are to be used in a page (for help) * @return a mutable list of components to include in the help pages */ - List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context); + List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage); } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java index aaf4d1e..f5b7cdb 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java @@ -20,7 +20,7 @@ public class DefaultPageBuilder implements IPageBuilder { List components = new LinkedList<>(); for (IHelpTopic topic : helpTopics) { - components.addAll(topic.getComponents(target, viewer, context)); + components.addAll(topic.getComponents(target, viewer, context, true)); } PageBorders pageBorders = null; diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java index d1a6445..fb8de57 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java @@ -16,7 +16,7 @@ import java.util.List; public class DescriptionHelpTopic implements IHelpTopic { @Override - public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context) { + public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) { List out = new ArrayList<>(); Formatting format = context.getFormat(EMessageType.DESCRIPTION); diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java index 1e9922f..59912cd 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java @@ -11,29 +11,31 @@ import io.dico.dicore.command.predef.PredefinedCommand; import org.bukkit.command.CommandSender; import org.bukkit.permissions.Permissible; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; public class SubcommandsHelpTopic implements IHelpTopic { @Override - public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context) { - List out = new ArrayList<>(); - Map children = target.getChildren(); - if (children.isEmpty()) { - //System.out.println("No subcommands"); - return out; + public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) { + Collection mainKeys = target.getChildrenMainKeys(); + if (mainKeys.isEmpty()) { + return Collections.emptyList(); } + List result = new ArrayList<>(); + + mainKeys = new ArrayList<>(target.getChildrenMainKeys()); + ((ArrayList) mainKeys).sort(null); + CommandSender sender = viewer instanceof CommandSender ? (CommandSender) viewer : context.getSender(); - children.values().stream().distinct().forEach(child -> { - if ((!child.hasCommand() || child.getCommand().isVisibleTo(sender)) && !(child instanceof PredefinedCommand)) { - out.add(getComponent(child, viewer, context)); + for (String key : mainKeys) { + ICommandAddress child = target.getChild(key); + if ((child.hasChildren() || child.hasUserDeclaredCommand()) && child.getCommand().isVisibleTo(sender)) { + result.add(getComponent(child, viewer, context)); } - }); + } - return out; + return result; } public IHelpComponent getComponent(ICommandAddress child, Permissible viewer, ExecutionContext context) { diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java index 7c0bc9d..25392c8 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java @@ -19,56 +19,74 @@ import java.util.Map; public class SyntaxHelpTopic implements IHelpTopic { @Override - public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context) { + public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) { if (!target.hasCommand()) { return Collections.emptyList(); } - String line = context.getFormat(EMessageType.SYNTAX) + "Syntax: " - + context.getFormat(EMessageType.INSTRUCTION) + target.getAddress() - + ' ' + getShortSyntax(target, context); + if (target.hasChildren()) { + if (!isForPage) { + // HelpPages will send help instead of syntax, which might in turn include syntax as well. + return Collections.emptyList(); + } + + if (!target.hasUserDeclaredCommand() && !target.getCommand().getParameterList().hasAnyParameters()) { + // no point adding syntax at all + return Collections.emptyList(); + } + } + + StringBuilder line = new StringBuilder(); + if (isForPage) + line.append(context.getFormat(EMessageType.SYNTAX)) + .append("Syntax: "); + + line.append('/') + .append(context.getFormat(EMessageType.INSTRUCTION)) + .append(target.getAddress()) + .append(' '); + + addShortSyntax(line, target, context); - return Collections.singletonList(new SimpleHelpComponent(line)); + return Collections.singletonList(new SimpleHelpComponent(line.toString())); } - private static String getShortSyntax(ICommandAddress target, ExecutionContext ctx) { - StringBuilder syntax = new StringBuilder(); - if (target.hasCommand()) { + private static void addShortSyntax(StringBuilder builder, ICommandAddress address, ExecutionContext ctx) { + if (address.hasCommand()) { Formatting syntaxColor = ctx.getFormat(EMessageType.SYNTAX); Formatting highlight = ctx.getFormat(EMessageType.HIGHLIGHT); - syntax.append(syntaxColor); + builder.append(syntaxColor); - Command command = target.getCommand(); + Command command = address.getCommand(); ParameterList list = command.getParameterList(); Parameter repeated = list.getRepeatedParameter(); int requiredCount = list.getRequiredCount(); List> indexedParameters = list.getIndexedParameters(); for (int i = 0, n = indexedParameters.size(); i < n; i++) { - syntax.append(i < requiredCount ? " <" : " ["); + builder.append(i < requiredCount ? " <" : " ["); Parameter param = indexedParameters.get(i); - syntax.append(param.getName()); + builder.append(param.getName()); if (param == repeated) { - syntax.append(highlight).append("...").append(syntaxColor); + builder.append(highlight).append("...").append(syntaxColor); } - syntax.append(i < requiredCount ? '>' : ']'); + builder.append(i < requiredCount ? '>' : ']'); } Map> parametersByName = list.getParametersByName(); for (Parameter param : parametersByName.values()) { if (param.isFlag()) { - syntax.append(" [").append(param.getName()); + builder.append(" [").append(param.getName()); if (param.expectsInput()) { - syntax.append(" <").append(param.getName()).append(">"); + builder.append(" <").append(param.getName()).append(">"); } - syntax.append(']'); + builder.append(']'); } } } else { - syntax.append(' '); + builder.append(' '); } - return syntax.toString(); } } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java index f8ae713..b043deb 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java @@ -24,7 +24,7 @@ public class HelpComponentInserter extends HelpTopicModifier { for (int i = insertions.size() - 1; i >= 0; i--) { IInsertion insertion = insertions.get(i); int idx = insertion.insertionIndex(components, target, viewer, context); - List inserted = insertion.getComponents(target, viewer, context); + List inserted = insertion.getComponents(target, viewer, context, true); components.addAll(idx, inserted); } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java index 042cd72..39b2784 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java @@ -17,8 +17,8 @@ public class Insertions { public static IInsertion combine(IHelpTopic topic, IInsertionFunction function) { return new IInsertion() { @Override - public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context) { - return topic.getComponents(target, viewer, context); + public List getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) { + return topic.getComponents(target, viewer, context, true); } @Override diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java index 582d20a..459ced5 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java @@ -60,6 +60,14 @@ public class ParameterList { return this; } + public boolean hasAnyParameters() { + return !byName.isEmpty(); + } + + public int getIndexedParameterCount() { + return indexedParameters.size(); + } + public List> getIndexedParameters() { return Collections.unmodifiableList(indexedParameters); } -- cgit v1.2.3