From a26eb31a041c9657ab3c0a80e6ab91a3a3817fd5 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Thu, 8 Mar 2018 21:44:02 +0100 Subject: [PATCH 1/4] help improvements --- .../co/aikar/commands/CommandContexts.java | 9 ++++ .../java/co/aikar/commands/CommandHelp.java | 53 +++++++++++++++++++ .../java/co/aikar/commands/HelpEntry.java | 21 +++++++- .../java/co/aikar/commands/MessageKeys.java | 8 ++- languages/core/acf-core_en.properties | 6 ++- 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/co/aikar/commands/CommandContexts.java b/core/src/main/java/co/aikar/commands/CommandContexts.java index 7a0407ce..56b92577 100644 --- a/core/src/main/java/co/aikar/commands/CommandContexts.java +++ b/core/src/main/java/co/aikar/commands/CommandContexts.java @@ -232,6 +232,15 @@ public class CommandContexts helpEntries = new ArrayList<>(); + private final String commandName; private int page; private int perPage; private List search; + private HelpEntry selectedEntry; public CommandHelp(CommandManager manager, RootCommand rootCommand, CommandIssuer issuer) { this.manager = manager; this.issuer = issuer; this.perPage = manager.defaultHelpPerPage; + this.commandName = "/" + rootCommand.getCommandName(); SetMultimap subCommands = rootCommand.getSubCommands(); Set seen = new HashSet<>(); @@ -103,6 +106,16 @@ public class CommandHelp { return manager; } + public boolean isExactMatch(String command){ + for (HelpEntry helpEntry : helpEntries) { + if(helpEntry.getCommand().endsWith(" " + command)){ + selectedEntry = helpEntry; + return true; + } + } + return false; + } + public void showHelp() { showHelp(issuer, MessageKeys.HELP_FORMAT); } @@ -112,6 +125,11 @@ public class CommandHelp { } public void showHelp(CommandIssuer issuer, MessageKeyProvider format) { + if(selectedEntry != null){ + showDetailedHelp(selectedEntry, issuer); + return; + } + List helpEntries = getHelpEntries(); Iterator results = helpEntries.stream() .filter(HelpEntry::shouldShow) @@ -130,6 +148,14 @@ public class CommandHelp { return; } + if(search == null){ + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, "{command}", commandName); + }else{ + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, + "{command}", commandName, + "{search}", String.join(" ", search)); + } + while (results.hasNext()) { HelpEntry e = results.next(); if (i >= max) { @@ -153,6 +179,24 @@ public class CommandHelp { } } + public void showDetailedHelp(HelpEntry page, CommandIssuer issuer){ + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER, "{command}", page.getCommand()); + + // normal help line + String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); + for (String msg : ACFPatterns.NEWLINE.split(formatted)) { + issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + } + + // additionally detailed help for params + page.getParameters().forEach((cmd, help) -> { + String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_FORMAT, getDetailedFormatReplacements(cmd, help, page)); + for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) { + issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + } + }); + } + /** * Override this to control replacements * @param e @@ -169,6 +213,15 @@ public class CommandHelp { }; } + @NotNull + public String[] getDetailedFormatReplacements(String cmd, String help, HelpEntry page) { + //{name} {description} + return new String[] { + "{name}", cmd, + "{description}", help + }; + } + public List getHelpEntries() { return helpEntries; } diff --git a/core/src/main/java/co/aikar/commands/HelpEntry.java b/core/src/main/java/co/aikar/commands/HelpEntry.java index 9bbce995..02d3ebe8 100644 --- a/core/src/main/java/co/aikar/commands/HelpEntry.java +++ b/core/src/main/java/co/aikar/commands/HelpEntry.java @@ -23,25 +23,40 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Description; import co.aikar.commands.annotation.HelpSearchTags; +import java.lang.reflect.Parameter; +import java.util.LinkedHashMap; +import java.util.Map; + public class HelpEntry { private final RegisteredCommand command; private final String searchTags; private int searchScore = 1; + private Map parameters = new LinkedHashMap<>(); HelpEntry(RegisteredCommand command) { this.command = command; HelpSearchTags tagsAnno = command.method.getAnnotation(HelpSearchTags.class); this.searchTags = tagsAnno != null ? tagsAnno.value() : null; + + // search for parameter descriptions + for (Parameter parameter : command.method.getParameters()) { + Description description = parameter.getAnnotation(Description.class); + if(description != null){ + parameters.put(parameter.getName(), description.value()); + }else{ + //TODO also add parameters with not description? + } + } } RegisteredCommand getRegisteredCommand() { return this.command; } - public String getCommand(){ return "/" + this.command.command; } @@ -69,4 +84,8 @@ public class HelpEntry { public String getSearchTags() { return searchTags; } + + public Map getParameters() { + return parameters; + } } diff --git a/core/src/main/java/co/aikar/commands/MessageKeys.java b/core/src/main/java/co/aikar/commands/MessageKeys.java index fd7be9ba..1732f25f 100644 --- a/core/src/main/java/co/aikar/commands/MessageKeys.java +++ b/core/src/main/java/co/aikar/commands/MessageKeys.java @@ -45,10 +45,14 @@ public enum MessageKeys implements MessageKeyProvider { PLEASE_SPECIFY_AT_MOST, NOT_ALLOWED_ON_CONSOLE, COULD_NOT_FIND_PLAYER, - HELP_FORMAT, NO_COMMAND_MATCHED_SEARCH, HELP_PAGE_INFORMATION, - HELP_NO_RESULTS + HELP_NO_RESULTS, + HELP_HEADER, + HELP_FORMAT, + HELP_DETAILED_HEADER, + HELP_DETAILED_FORMAT, + HELP_SEARCH_HEADER, ; private final MessageKey key = MessageKey.of("acf-core." + this.name().toLowerCase()); diff --git a/languages/core/acf-core_en.properties b/languages/core/acf-core_en.properties index fb3a9a9e..a0f8e898 100644 --- a/languages/core/acf-core_en.properties +++ b/languages/core/acf-core_en.properties @@ -34,7 +34,11 @@ acf-core.must_be_max_length = Error: Must be at most {max} characters long. acf-core.please_specify_at_most = Error: Please specify a value at most {max}. acf-core.not_allowed_on_console = Error: Console may not execute this command. acf-core.could_not_find_player = Error: Could not find a player by the name: {search} -acf-core.help_format = {command} {parameters} {separator} {description} acf-core.no_command_matched_search = No command matched {search}. acf-core.help_page_information = - Showing page {page} of {totalpages} ({results} results). acf-core.help_no_results = Error: No more results. +acf-core.help_header = === Showing help for {command} === +acf-core.help_format = {command} {parameters} {separator} {description} +acf-core.help_detailed_header = === Showing detailed help for {command} === +acf-core.help_detailed_format = {name}: {description} +acf-core.help_search_header = === Showing help for {command} {search} === From a4c67f66a2bbdb413a87d380d678183a46883073 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Thu, 8 Mar 2018 22:39:31 +0100 Subject: [PATCH 2/4] make sure to only treat a type as sender if its not annotated with "other" --- .../co/aikar/commands/RegisteredCommand.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/co/aikar/commands/RegisteredCommand.java b/core/src/main/java/co/aikar/commands/RegisteredCommand.java index 3fcf2151..d5d2b223 100644 --- a/core/src/main/java/co/aikar/commands/RegisteredCommand.java +++ b/core/src/main/java/co/aikar/commands/RegisteredCommand.java @@ -28,6 +28,7 @@ import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; import co.aikar.commands.annotation.Default; import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Flags; import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Syntax; import co.aikar.commands.annotation.Values; @@ -105,11 +106,23 @@ public class RegisteredCommand "); + }else{ + // optional issuer aware context resolver + optionalResolvers++; + } + }else{ + // some other optional resolver + optionalResolvers++; syntaxB.append('[').append(name).append("] "); } } else { From 2f80fd4fdf204f21e53e4db61d7f1cb53986b157 Mon Sep 17 00:00:00 2001 From: MiniDigger Date: Sat, 10 Mar 2018 00:58:06 +0100 Subject: [PATCH 3/4] start with abstracting help messages out --- .../java/co/aikar/commands/CommandHelp.java | 89 ++++------- .../aikar/commands/CommandHelpFormatter.java | 138 ++++++++++++++++++ .../co/aikar/commands/CommandManager.java | 10 ++ 3 files changed, 176 insertions(+), 61 deletions(-) create mode 100644 core/src/main/java/co/aikar/commands/CommandHelpFormatter.java diff --git a/core/src/main/java/co/aikar/commands/CommandHelp.java b/core/src/main/java/co/aikar/commands/CommandHelp.java index 91f988f7..7bbab221 100644 --- a/core/src/main/java/co/aikar/commands/CommandHelp.java +++ b/core/src/main/java/co/aikar/commands/CommandHelp.java @@ -56,7 +56,7 @@ public class CommandHelp { Set seen = new HashSet<>(); subCommands.entries().forEach(e -> { String key = e.getKey(); - if (key.equals(BaseCommand.DEFAULT) || key.equals(BaseCommand.CATCHUNKNOWN)){ + if (key.equals(BaseCommand.DEFAULT) || key.equals(BaseCommand.CATCHUNKNOWN)) { return; } @@ -106,9 +106,9 @@ public class CommandHelp { return manager; } - public boolean isExactMatch(String command){ + public boolean isExactMatch(String command) { for (HelpEntry helpEntry : helpEntries) { - if(helpEntry.getCommand().endsWith(" " + command)){ + if (helpEntry.getCommand().endsWith(" " + command)) { selectedEntry = helpEntry; return true; } @@ -117,15 +117,11 @@ public class CommandHelp { } public void showHelp() { - showHelp(issuer, MessageKeys.HELP_FORMAT); + showHelp(issuer); } public void showHelp(CommandIssuer issuer) { - showHelp(issuer, MessageKeys.HELP_FORMAT); - } - - public void showHelp(CommandIssuer issuer, MessageKeyProvider format) { - if(selectedEntry != null){ + if (selectedEntry != null) { showDetailedHelp(selectedEntry, issuer); return; } @@ -140,20 +136,19 @@ public class CommandHelp { results = helpEntries.iterator(); } int totalResults = helpEntries.size(); - int min = (this.page-1) * this.perPage; // TODO: per page configurable? + int min = (this.page - 1) * this.perPage; // TODO: per page configurable? int max = min + this.perPage; + int totalPages = (int) Math.ceil((float) totalResults / (float) this.perPage); int i = 0; if (min >= totalResults) { issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_NO_RESULTS); return; } - if(search == null){ - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, "{command}", commandName); - }else{ - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, - "{command}", commandName, - "{search}", String.join(" ", search)); + if (search == null) { + manager.getHelpFormatter().printHelpHeader(issuer, commandName, page, totalPages, totalResults); + } else { + manager.getHelpFormatter().printSearchHeader(issuer, commandName, page, totalPages, totalResults, search); } while (results.hasNext()) { @@ -165,61 +160,33 @@ public class CommandHelp { continue; } - String formatted = this.manager.formatMessage(issuer, MessageType.HELP, format, getFormatReplacements(e)); - for (String msg : ACFPatterns.NEWLINE.split(formatted)) { - issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + if (search == null) { + manager.getHelpFormatter().printHelpLine(issuer, commandName, e); + } else { + manager.getHelpFormatter().printSearchLine(issuer, commandName, e, e.getSearchScore()); } } - if (min > 0 || results.hasNext()) { - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, - "{page}", "" + this.page, - "{totalpages}", ""+ (int)Math.ceil((float)totalResults / (float)this.perPage), - "{results}", "" + totalResults - ); + + boolean lastPage = !(min > 0 || results.hasNext()); + if (search == null) { + manager.getHelpFormatter().printHelpFooter(issuer, commandName, page, totalPages, totalResults, lastPage); + } else { + manager.getHelpFormatter().printSearchFooter(issuer, commandName, page, totalPages, totalResults, search, lastPage); } } - public void showDetailedHelp(HelpEntry page, CommandIssuer issuer){ - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER, "{command}", page.getCommand()); + public void showDetailedHelp(HelpEntry page, CommandIssuer issuer) { + // header + manager.getHelpFormatter().printDetailedHelpHeader(issuer, commandName, page); // normal help line - String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); - for (String msg : ACFPatterns.NEWLINE.split(formatted)) { - issuer.sendMessageInternal(ACFUtil.rtrim(msg)); - } + manager.getHelpFormatter().printHelpLine(issuer, commandName, page); // additionally detailed help for params - page.getParameters().forEach((cmd, help) -> { - String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_FORMAT, getDetailedFormatReplacements(cmd, help, page)); - for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) { - issuer.sendMessageInternal(ACFUtil.rtrim(msg)); - } - }); - } + page.getParameters().forEach((cmd, help) -> manager.getHelpFormatter().printDetailedHelpLine(issuer, commandName, page, cmd, help)); - /** - * Override this to control replacements - * @param e - * @return - */ - @NotNull - public String[] getFormatReplacements(HelpEntry e) { - //{command} {parameters} {separator} {description} - return new String[] { - "{command}", e.getCommand(), - "{parameters}", e.getParameterSyntax(), - "{separator}", e.getDescription().isEmpty() ? "" : "-", - "{description}", e.getDescription() - }; - } - - @NotNull - public String[] getDetailedFormatReplacements(String cmd, String help, HelpEntry page) { - //{name} {description} - return new String[] { - "{name}", cmd, - "{description}", help - }; + // footer + manager.getHelpFormatter().printDetailedHelpFooter(issuer, commandName, page); } public List getHelpEntries() { diff --git a/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java b/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java new file mode 100644 index 00000000..1de111c7 --- /dev/null +++ b/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016-2018 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.jetbrains.annotations.NotNull; + +import java.util.List; + +public class CommandHelpFormatter { + + private final CommandManager manager; + + public CommandHelpFormatter(CommandManager manager) { + this.manager = manager; + } + + // ######## + // # help # + // ######## + + public void printHelpHeader(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, "{command}", commandName); + } + + public void printHelpLine(CommandIssuer issuer, String commandName, HelpEntry page) { + String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); + for (String msg : ACFPatterns.NEWLINE.split(formatted)) { + issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + } + } + + public void printHelpFooter(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, boolean lastPage) { + if(lastPage)return; + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, + "{page}", "" + page, + "{totalpages}", ""+ totalPages, + "{results}", "" + totalResults + ); + } + + // ########## + // # search # + // ########## + + public void printSearchHeader(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, List search) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, + "{command}", commandName, + "{search}", String.join(" ", search)); + } + + public void printSearchLine(CommandIssuer issuer, String commandName, HelpEntry page, int score) { + String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); + for (String msg : ACFPatterns.NEWLINE.split(formatted)) { + issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + } + } + + public void printSearchFooter(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, List search, boolean lastPage) { + if(lastPage)return; + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, + "{page}", "" + page, + "{totalpages}", ""+ totalPages, + "{results}", "" + totalResults + ); + } + + // ############ + // # detailed # + // ############ + + public void printDetailedHelpHeader(CommandIssuer issuer, String commandName, HelpEntry page) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER, "{command}", page.getCommand()); + } + + public void printDetailedHelpLine(CommandIssuer issuer, String commandName, HelpEntry page, String subCommand, String paramDescription) { + String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_FORMAT, getDetailedFormatReplacements(subCommand, paramDescription, page)); + for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) { + issuer.sendMessageInternal(ACFUtil.rtrim(msg)); + } + } + + public void printDetailedHelpFooter(CommandIssuer issuer, String commandName, HelpEntry page) { + // default doesn't have a footer + } + + /** + * Override this to control replacements + * @param e + * @return + */ + @NotNull + public String[] getFormatReplacements(HelpEntry e) { + //{command} {parameters} {separator} {description} + return new String[] { + "{command}", e.getCommand(), + "{parameters}", e.getParameterSyntax(), + "{separator}", e.getDescription().isEmpty() ? "" : "-", + "{description}", e.getDescription() + }; + } + + /** + * Override this to control replacements + * @param cmd + * @param help + * @param page + * @return + */ + @NotNull + public String[] getDetailedFormatReplacements(String cmd, String help, HelpEntry page) { + //{name} {description} + return new String[] { + "{name}", cmd, + "{description}", help + }; + } +} diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java index 1f2b0e85..513ca694 100644 --- a/core/src/main/java/co/aikar/commands/CommandManager.java +++ b/core/src/main/java/co/aikar/commands/CommandManager.java @@ -71,6 +71,7 @@ public abstract class CommandManager < protected final CommandConditions conditions = new CommandConditions<>(this); protected ExceptionHandler defaultExceptionHandler = null; protected Table, String, Object> dependencies = HashBasedTable.create(); + protected CommandHelpFormatter helpFormatter = new CommandHelpFormatter(this); protected boolean usePerIssuerLocale = false; protected List> localeChangedCallbacks = Lists.newArrayList(); @@ -185,6 +186,15 @@ public abstract class CommandManager < verifyUnstableAPI("help"); this.defaultHelpPerPage = defaultHelpPerPage; } + /** @deprecated Unstable API */ @Deprecated @UnstableAPI + public void setHelpFormatter(CommandHelpFormatter helpFormatter) { + this.helpFormatter = helpFormatter; + } + + /** @deprecated Unstable API */ @Deprecated @UnstableAPI + public CommandHelpFormatter getHelpFormatter() { + return helpFormatter; + } /** * Registers a command with ACF From 8335d580f6c087f2bab304fdad1c886f027468f8 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 21 Mar 2018 22:02:48 -0400 Subject: [PATCH 4/4] Improvements to help formatter --- .../aikar/commands/BukkitCommandManager.java | 5 + .../aikar/commands/BungeeCommandManager.java | 6 ++ .../java/co/aikar/commands/CommandHelp.java | 19 ++-- .../aikar/commands/CommandHelpFormatter.java | 95 ++++++++++++------- .../co/aikar/commands/CommandManager.java | 4 + .../co/aikar/commands/JDACommandManager.java | 28 ++++-- .../aikar/commands/SpongeCommandManager.java | 5 + 7 files changed, 113 insertions(+), 49 deletions(-) diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java index e1fb03f3..ab913bff 100644 --- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java +++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java @@ -353,4 +353,9 @@ public class BukkitCommandManager extends CommandManager< this.autoDetectFromClient = autoDetectFromClient; return old; } + + @Override + public String getCommandPrefix(CommandIssuer issuer) { + return issuer.isPlayer() ? "/" : ""; + } } diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java index d8cd689c..c8a14347 100644 --- a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java @@ -207,4 +207,10 @@ public class BungeeCommandManager extends CommandManager< } } } + + + @Override + public String getCommandPrefix(CommandIssuer issuer) { + return issuer.isPlayer() ? "/" : ""; + } } diff --git a/core/src/main/java/co/aikar/commands/CommandHelp.java b/core/src/main/java/co/aikar/commands/CommandHelp.java index e626dc49..c3ab1e29 100644 --- a/core/src/main/java/co/aikar/commands/CommandHelp.java +++ b/core/src/main/java/co/aikar/commands/CommandHelp.java @@ -50,7 +50,7 @@ public class CommandHelp { this.manager = manager; this.issuer = issuer; this.perPage = manager.defaultHelpPerPage; - this.commandName = "/" + rootCommand.getCommandName(); + this.commandName = manager.getCommandPrefix(issuer) + rootCommand.getCommandName(); SetMultimap subCommands = rootCommand.getSubCommands(); Set seen = new HashSet<>(); @@ -175,21 +175,24 @@ public class CommandHelp { } } - public void showDetailedHelp(HelpEntry page, CommandIssuer issuer) { + public void showDetailedHelp(HelpEntry entry, CommandIssuer issuer) { // header - manager.getHelpFormatter().printDetailedHelpHeader(issuer, commandName, page); + CommandHelpFormatter formatter = manager.getHelpFormatter(); + formatter.printDetailedHelpHeader(issuer, commandName, entry); // normal help line - manager.getHelpFormatter().printHelpLine(issuer, commandName, page); + formatter.printHelpLine(issuer, commandName, entry); // additionally detailed help for params - for (CommandParameter param : page.getParameters()) { - manager.getHelpFormatter().printDetailedHelpLine(issuer, commandName, page, param.getName(), param.getDescription()); + for (CommandParameter param : entry.getParameters()) { + String description = param.getDescription(); + if (description != null && !description.isEmpty()) { + formatter.printDetailedHelpLine(issuer, commandName, entry, param.getName(), description); + } } - // footer - manager.getHelpFormatter().printDetailedHelpFooter(issuer, commandName, page); + formatter.printDetailedHelpFooter(issuer, commandName, entry); } public List getHelpEntries() { diff --git a/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java b/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java index 1de111c7..44203c0c 100644 --- a/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java +++ b/core/src/main/java/co/aikar/commands/CommandHelpFormatter.java @@ -39,23 +39,31 @@ public class CommandHelpFormatter { // # help # // ######## - public void printHelpHeader(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults) { - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, "{command}", commandName); + public void printHelpHeader(CommandIssuer issuer, String command, int page, int totalPages, int totalResults) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_HEADER, + "{page}", "" + page, + "{totalpages}", "" + totalPages, + "{results}", "" + totalResults, + "{command}", "" + command + ); } - public void printHelpLine(CommandIssuer issuer, String commandName, HelpEntry page) { - String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); + public void printHelpLine(CommandIssuer issuer, String command, HelpEntry page) { + String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page, command)); for (String msg : ACFPatterns.NEWLINE.split(formatted)) { issuer.sendMessageInternal(ACFUtil.rtrim(msg)); } } - public void printHelpFooter(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, boolean lastPage) { - if(lastPage)return; + public void printHelpFooter(CommandIssuer issuer, String command, int page, int totalPages, int totalResults, boolean lastPage) { + if (lastPage) { + return; + } issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, "{page}", "" + page, - "{totalpages}", ""+ totalPages, - "{results}", "" + totalResults + "{totalpages}", "" + totalPages, + "{results}", "" + totalResults, + "{command}", "" + command ); } @@ -63,57 +71,72 @@ public class CommandHelpFormatter { // # search # // ########## - public void printSearchHeader(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, List search) { - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, - "{command}", commandName, - "{search}", String.join(" ", search)); + public void printSearchHeader(CommandIssuer issuer, String command, int page, int totalPages, int totalResults, List search) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_SEARCH_HEADER, getPaginationFormatReplacements(command, page, totalPages, totalResults, search)); } - public void printSearchLine(CommandIssuer issuer, String commandName, HelpEntry page, int score) { - String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page)); + public void printSearchLine(CommandIssuer issuer, String command, HelpEntry page, int score) { + String formatted = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_FORMAT, getFormatReplacements(page, command)); for (String msg : ACFPatterns.NEWLINE.split(formatted)) { issuer.sendMessageInternal(ACFUtil.rtrim(msg)); } } - public void printSearchFooter(CommandIssuer issuer, String commandName, int page, int totalPages, int totalResults, List search, boolean lastPage) { - if(lastPage)return; - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, - "{page}", "" + page, - "{totalpages}", ""+ totalPages, - "{results}", "" + totalResults + public void printSearchFooter(CommandIssuer issuer, String command, int page, int totalPages, int totalResults, List search, boolean lastPage) { + if (lastPage) { + return; + } + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_PAGE_INFORMATION, getPaginationFormatReplacements(command, page, totalPages, totalResults, search) ); } + // ############ // # detailed # // ############ - public void printDetailedHelpHeader(CommandIssuer issuer, String commandName, HelpEntry page) { - issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER, "{command}", page.getCommand()); + public void printDetailedHelpHeader(CommandIssuer issuer, String command, HelpEntry entry) { + issuer.sendMessage(MessageType.HELP, MessageKeys.HELP_DETAILED_HEADER, + "{command}", entry.getCommand(), + "{command}", command + ); } - public void printDetailedHelpLine(CommandIssuer issuer, String commandName, HelpEntry page, String subCommand, String paramDescription) { - String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_FORMAT, getDetailedFormatReplacements(subCommand, paramDescription, page)); + public void printDetailedHelpLine(CommandIssuer issuer, String rootCommand, HelpEntry entry, String subCommand, String paramDescription) { + String formattedMsg = this.manager.formatMessage(issuer, MessageType.HELP, MessageKeys.HELP_DETAILED_FORMAT, getDetailedFormatReplacements(subCommand, paramDescription, entry, rootCommand)); for (String msg : ACFPatterns.NEWLINE.split(formattedMsg)) { issuer.sendMessageInternal(ACFUtil.rtrim(msg)); } } - public void printDetailedHelpFooter(CommandIssuer issuer, String commandName, HelpEntry page) { + public void printDetailedHelpFooter(CommandIssuer issuer, String command, HelpEntry page) { // default doesn't have a footer } + @NotNull + public String[] getPaginationFormatReplacements(String command, int page, int totalPages, int totalResults, List search) { + return new String[]{ + "{search}", String.join(" ", search), + "{command}", command, + "{rootcommand}", command, + "{page}", "" + page, + "{totalpages}", "" + totalPages, + "{results}", "" + totalResults + }; + } + /** * Override this to control replacements + * * @param e + * @param command * @return */ - @NotNull - public String[] getFormatReplacements(HelpEntry e) { + public String[] getFormatReplacements(HelpEntry e, String command) { //{command} {parameters} {separator} {description} - return new String[] { + return new String[]{ "{command}", e.getCommand(), + "{rootcommand}", command, "{parameters}", e.getParameterSyntax(), "{separator}", e.getDescription().isEmpty() ? "" : "-", "{description}", e.getDescription() @@ -122,17 +145,21 @@ public class CommandHelpFormatter { /** * Override this to control replacements - * @param cmd - * @param help + * + * @param name + * @param description * @param page + * @param rootCommand * @return */ @NotNull - public String[] getDetailedFormatReplacements(String cmd, String help, HelpEntry page) { + public String[] getDetailedFormatReplacements(String name, String description, HelpEntry page, String rootCommand) { //{name} {description} - return new String[] { - "{name}", cmd, - "{description}", help + return new String[]{ + "{name}", name, + "{command}", page.getCommand(), + "{rootcommand}", rootCommand, + "{description}", description }; } } diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java index 2977fe63..96277a18 100644 --- a/core/src/main/java/co/aikar/commands/CommandManager.java +++ b/core/src/main/java/co/aikar/commands/CommandManager.java @@ -504,4 +504,8 @@ public abstract class CommandManager < Annotations getAnnotations() { return annotations; } + + public String getCommandPrefix(CommandIssuer issuer) { + return ""; + } } diff --git a/jda/src/main/java/co/aikar/commands/JDACommandManager.java b/jda/src/main/java/co/aikar/commands/JDACommandManager.java index df336b59..19d13c71 100644 --- a/jda/src/main/java/co/aikar/commands/JDACommandManager.java +++ b/jda/src/main/java/co/aikar/commands/JDACommandManager.java @@ -220,13 +220,7 @@ public class JDACommandManager extends CommandManager< Message message = event.getMessage(); String msg = message.getContentDisplay(); - CommandConfig config = this.defaultConfig; - if (this.configProvider != null) { - CommandConfig provided = this.configProvider.provide(event); - if (provided != null) { - config = provided; - } - } + CommandConfig config = getCommandConfig(event); String prefixFound = null; for (String prefix : config.getCommandPrefixes()) { @@ -255,4 +249,24 @@ public class JDACommandManager extends CommandManager< } rootCommand.execute(this.getCommandIssuer(event), cmd, args); } + + private CommandConfig getCommandConfig(MessageReceivedEvent event) { + CommandConfig config = this.defaultConfig; + if (this.configProvider != null) { + CommandConfig provided = this.configProvider.provide(event); + if (provided != null) { + config = provided; + } + } + return config; + } + + + @Override + public String getCommandPrefix(CommandIssuer issuer) { + MessageReceivedEvent event = ((JDACommandEvent) issuer).getEvent(); + CommandConfig commandConfig = getCommandConfig(event); + List prefixes = commandConfig.getCommandPrefixes(); + return prefixes.isEmpty() ? "" : prefixes.get(0); + } } diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java index 811c25d6..383711bd 100644 --- a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java +++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java @@ -197,4 +197,9 @@ public class SpongeCommandManager extends CommandManager< public SpongeConditionContext createConditionContext(CommandIssuer issuer, String config) { return new SpongeConditionContext((SpongeCommandIssuer) issuer, config); } + + @Override + public String getCommandPrefix(CommandIssuer issuer) { + return issuer.isPlayer() ? "/" : ""; + } }