diff --git a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index a72a6586e..377f75871 100644 --- a/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java +++ b/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java @@ -87,6 +87,12 @@ public abstract class CommandsManager { */ protected Injector injector; + /** + * Mapping of commands (not including aliases) with a description. This + * is only for top level commands. + */ + protected Map helpMessages = new HashMap(); + /** * Register an class that contains commands (denoted by {@link Command}. * If no dependency injector is specified, then the methods of the @@ -189,11 +195,32 @@ public abstract class CommandsManager { // Build a list of commands and their usage details, at least for // root level commands if (parent == null) { - if (cmd.usage().length() == 0) { - descs.put(cmd.aliases()[0], cmd.desc()); + final String commandName = cmd.aliases()[0]; + final String desc = cmd.desc(); + + final String usage = cmd.usage(); + if (usage.length() == 0) { + descs.put(commandName, desc); } else { - descs.put(cmd.aliases()[0], cmd.usage() + " - " + cmd.desc()); + descs.put(commandName, usage + " - " + desc); } + + String help = cmd.help(); + if (help.length() == 0) { + help = desc; + } + + final CharSequence arguments = getArguments(cmd); + for (String alias : cmd.aliases()) { + final String helpMessage = "/"+alias+" "+arguments+"\n\n"+help; + final String key = alias.replaceAll("/", ""); + String previous = helpMessages.put(key, helpMessage); + + if (previous != null && !previous.replaceAll("^/[^ ]+ ", "").equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) { + helpMessages.put(key, previous+"\n\n"+helpMessage); + } + } + } // Add the command to the registered command list for return @@ -233,6 +260,15 @@ public abstract class CommandsManager { return descs; } + /** + * Get a map from command name to help message. This is only for root commands. + * + * @return + */ + public Map getHelpMessages() { + return helpMessages; + } + /** * Get the usage string for a command. * @@ -250,17 +286,7 @@ public abstract class CommandsManager { command.append(args[i]); command.append(' '); } - if (cmd.flags().length() > 0) { - String flags = cmd.flags().replaceAll(".:", ""); - if (flags.length() > 0) { - command.append("[-"); - for (int i = 0; i < flags.length(); ++i) { - command.append(flags.charAt(i)); - } - command.append("] "); - } - } - command.append(cmd.usage()); + command.append(getArguments(cmd)); final String help = cmd.help(); if (!help.isEmpty()) { @@ -271,6 +297,26 @@ public abstract class CommandsManager { return command.toString(); } + protected CharSequence getArguments(Command cmd) { + final String flags = cmd.flags(); + + final StringBuilder command2 = new StringBuilder(); + if (flags.length() > 0) { + String flagString = flags.replaceAll(".:", ""); + if (flagString.length() > 0) { + command2.append("[-"); + for (int i = 0; i < flagString.length(); ++i) { + command2.append(flagString.charAt(i)); + } + command2.append("] "); + } + } + + command2.append(cmd.usage()); + + return command2; + } + /** * Get the usage string for a nested command. * diff --git a/src/main/java/com/sk89q/worldedit/WorldEdit.java b/src/main/java/com/sk89q/worldedit/WorldEdit.java index 957506d14..94b8ac278 100644 --- a/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -983,6 +983,13 @@ public class WorldEdit { return commands.getCommands(); } + /** + * @return the commands + */ + public CommandsManager getCommandsManager() { + return commands; + } + /** * * @param player diff --git a/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java b/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java index 0343944fd..c8ef6f448 100644 --- a/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java +++ b/src/main/java/com/sk89q/worldedit/commands/UtilityCommands.java @@ -20,9 +20,13 @@ package com.sk89q.worldedit.commands; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; +import com.sk89q.minecraft.util.commands.CommandsManager; import com.sk89q.minecraft.util.commands.Logging; import static com.sk89q.minecraft.util.commands.Logging.LogMode.*; import com.sk89q.worldedit.*; @@ -426,4 +430,48 @@ public class UtilityCommands { int removed = player.getWorld().removeEntities(type, origin, radius); player.print("Marked " + removed + " entit(ies) for removal."); } + + @Command( + aliases = { "/help" }, + usage = "[]", + desc = "Displays help for the given command or lists all commands.", + min = 0, + max = -1 + ) + public static void help(CommandContext args, WorldEdit we, + LocalSession session, LocalPlayer player, EditSession editSession) + throws WorldEditException { + + final CommandsManager commandsManager = we.getCommandsManager(); + + if (args.argsLength() == 0) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + SortedSet commands = new TreeSet(commandsManager.getCommands().keySet()); + + for (String command : commands) { + if (!first) { + sb.append(", "); + } + + sb.append('/'); + sb.append(command); + first = false; + } + + player.print(sb.toString()); + + return; + } + + String command = args.getJoinedStrings(0).replaceAll("/", ""); + + String helpMessage = commandsManager.getHelpMessages().get(command); + if (helpMessage == null) { + player.printError("Unknown command '" + command + "'."); + return; + } + + player.print(helpMessage); + } }