refactor(HelpCommand): rewrite to paginate and show all usages, overall more helpful

This commit is contained in:
xgraza
2026-01-25 02:25:53 -06:00
parent d9a5789b42
commit 39237f60c3
2 changed files with 58 additions and 23 deletions
@@ -21,6 +21,7 @@ public abstract class Command extends Feature {
private final String description;
public Command(String[] aliases, String description) {
super(aliases[0]);
this.aliases = aliases;
this.description = description;
}
@@ -1,17 +1,24 @@
package me.alpha432.oyvey.features.commands.impl;
import com.google.common.collect.Iterables;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode;
import me.alpha432.oyvey.features.commands.Command;
import me.alpha432.oyvey.manager.CommandManager;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.StringJoiner;
import static me.alpha432.oyvey.features.commands.argument.CommandArgumentType.command;
import static me.alpha432.oyvey.features.commands.argument.CommandArgumentType.getCommand;
import static me.alpha432.oyvey.features.commands.argument.NumberArgumentType.getNumber;
import static me.alpha432.oyvey.features.commands.argument.NumberArgumentType.number;
public class HelpCommand extends Command {
private static final int ITEMS_PER_PAGE = 5;
public HelpCommand() {
super(new String[]{"help", "commands", "h", "cmds"},
"Displays all executable commands and additional information");
@@ -19,31 +26,58 @@ public class HelpCommand extends Command {
@Override
public void createArgumentBuilder(LiteralArgumentBuilder<CommandManager> builder) {
var defaultContext = (com.mojang.brigadier.Command<CommandManager>) (ctx) -> {
List<Command> commands = ctx.getSource().getCommands()
.stream()
.filter(Command::isShown)
.toList();
StringJoiner joiner = new StringJoiner(", ");
for (Command executor : commands) {
joiner.add(executor.getAliases()[0]);
}
return success("{gray} Commands (%s): {reset} %s", commands.size(), joiner);
};
builder.then(argument("command", command())
builder.then(argument("page", number(Integer.class))
.executes((ctx) ->
helpCommand(getNumber(Integer.class, ctx, "page")).run(ctx)))
.then(argument("command_name", command())
.executes((ctx) -> {
Command command = getCommand(ctx, "command");
StringJoiner joiner = new StringJoiner(", ");
for (String alias : command.getAliases()) {
joiner.add(alias);
Command command = getCommand(ctx, "command_name");
sendMessage("Usages for %s:", command.getName());
ParseResults<CommandManager> results = ctx.getSource().getDispatcher()
.parse(command.getName(), ctx.getSource());
if (results.getContext().getNodes().isEmpty()) {
return success("No usages available");
}
sendMessage("{gray} Aliases (%s): {reset} %s",
command.getAliases().length, joiner);
return success("{gray} Description: {reset} %s",
Objects.requireNonNullElse(command.getDescription(), DEFAULT_COMMAND_DESCRIPTION));
Map<CommandNode<CommandManager>, String> smartUsages = ctx.getSource().getDispatcher().getSmartUsage(
Iterables.getLast(results.getContext().getNodes()).getNode(), ctx.getSource());
for (String usage : smartUsages.values()) {
sendMessage(".%s %s", results.getReader().getString(), usage);
}
return success();
}))
.executes(defaultContext);
.executes((ctx) -> helpCommand(1).run(ctx));
}
private com.mojang.brigadier.Command<CommandManager> helpCommand(int page) {
return (ctx) -> {
List<Command> commands = ctx.getSource().getCommands()
.stream().filter(Command::isShown).toList();
int pageIndex = page;
int pages = (int) Math.ceil((double) commands.size() / ITEMS_PER_PAGE);
if (pageIndex > pages) {
pageIndex = 1;
}
List<Command> paginated = commands.subList((pageIndex - 1) * ITEMS_PER_PAGE,
Math.min(commands.size(), pageIndex * ITEMS_PER_PAGE));
sendMessage("Commands (%s):", commands.size());
for (Command command : paginated) {
StringJoiner joiner = new StringJoiner(", ");
for (String alias : command.getAliases()) {
joiner.add(alias);
}
sendMessage("{dark_gray} %s: {reset}\n %s",
joiner, command.getDescription());
}
return success("Page %s/%s", pageIndex, pages);
};
}
}