diff --git a/src/main/java/com/mojang/brigadier/builder/LiteralArgumentBuilder.java b/src/main/java/com/mojang/brigadier/builder/LiteralArgumentBuilder.java index 779f7600..349736f9 100644 --- a/src/main/java/com/mojang/brigadier/builder/LiteralArgumentBuilder.java +++ b/src/main/java/com/mojang/brigadier/builder/LiteralArgumentBuilder.java @@ -9,6 +9,8 @@ public class LiteralArgumentBuilder extends ArgumentBuilder> { private final String literal; + private boolean isCaseInsensitive = false; + protected LiteralArgumentBuilder(final String literal) { this.literal = literal; } @@ -26,9 +28,16 @@ public String getLiteral() { return literal; } + public boolean isCaseInsensitive() { return isCaseInsensitive; } + + public LiteralArgumentBuilder caseInsensitive(boolean isCaseInsensitive) { + this.isCaseInsensitive = isCaseInsensitive; + return getThis(); + } + @Override public LiteralCommandNode build() { - final LiteralCommandNode result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork()); + final LiteralCommandNode result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), isCaseInsensitive()); for (final CommandNode argument : getArguments()) { result.addChild(argument); diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java index 47f8e3db..a0e93c60 100644 --- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java @@ -8,6 +8,7 @@ import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -82,7 +83,13 @@ public void addChild(final CommandNode node) { } else { children.put(node.getName(), node); if (node instanceof LiteralCommandNode) { - literals.put(node.getName(), (LiteralCommandNode) node); + LiteralCommandNode literalNode = (LiteralCommandNode)node; + + if (literalNode.isCaseInsensitive()) { + literals.put(node.getName().toLowerCase(), (LiteralCommandNode) node); + } else { + literals.put(node.getName(), (LiteralCommandNode) node); + } } else if (node instanceof ArgumentCommandNode) { arguments.put(node.getName(), (ArgumentCommandNode) node); } @@ -158,7 +165,13 @@ public Collection> getRelevantNodes(final StringReader } final String text = input.getString().substring(cursor, input.getCursor()); input.setCursor(cursor); - final LiteralCommandNode literal = literals.get(text); + + boolean caseInsensitive = false; + if (this instanceof LiteralCommandNode) { + caseInsensitive = ((LiteralCommandNode)this).isCaseInsensitive(); + } + + final LiteralCommandNode literal = literals.get(caseInsensitive ? text.toLowerCase() : text); if (literal != null) { return Collections.singleton(literal); } else { diff --git a/src/main/java/com/mojang/brigadier/tree/LiteralCommandNode.java b/src/main/java/com/mojang/brigadier/tree/LiteralCommandNode.java index 85a89040..70877b6b 100644 --- a/src/main/java/com/mojang/brigadier/tree/LiteralCommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/LiteralCommandNode.java @@ -23,11 +23,14 @@ public class LiteralCommandNode extends CommandNode { private final String literal; private final String literalLowerCase; + private boolean isCaseInsensitive = false; - public LiteralCommandNode(final String literal, final Command command, final Predicate requirement, final CommandNode redirect, final RedirectModifier modifier, final boolean forks) { + public LiteralCommandNode(final String literal, final Command command, final Predicate requirement, final CommandNode redirect, final RedirectModifier modifier, final boolean forks, + final boolean isCaseInsensitive) { super(command, requirement, redirect, modifier, forks); this.literal = literal; this.literalLowerCase = literal.toLowerCase(Locale.ROOT); + this.isCaseInsensitive = isCaseInsensitive; } public String getLiteral() { @@ -39,6 +42,12 @@ public String getName() { return literal; } + public boolean isCaseInsensitive() { return isCaseInsensitive; } + + public void caseInsensitive(boolean isCaseInsensitive) { + this.isCaseInsensitive = isCaseInsensitive; + } + @Override public void parse(final StringReader reader, final CommandContextBuilder contextBuilder) throws CommandSyntaxException { final int start = reader.getCursor(); @@ -55,7 +64,17 @@ private int parse(final StringReader reader) { final int start = reader.getCursor(); if (reader.canRead(literal.length())) { final int end = start + literal.length(); - if (reader.getString().substring(start, end).equals(literal)) { + + boolean foundMatch = false; + String subString = reader.getString().substring(start, end); + + if (isCaseInsensitive) { + foundMatch = subString.equalsIgnoreCase(literal); + } else { + foundMatch = subString.equals(literal); + } + + if (foundMatch) { reader.setCursor(end); if (!reader.canRead() || reader.peek() == ' ') { return end; diff --git a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java index f2bab4a9..93b3c5c5 100644 --- a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java +++ b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java @@ -4,6 +4,8 @@ package com.mojang.brigadier; import com.google.common.collect.Lists; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -61,6 +63,15 @@ public void testCreateAndExecuteCommand() throws Exception { verify(command).run(any(CommandContext.class)); } + @SuppressWarnings("unchecked") + @Test + public void testCreateAndExecuteCaseInsensitiveCommand() throws Exception { + subject.register(literal("Foo").then(argument("bar", integer()).executes(command)).caseInsensitive(true)); + + assertThat(subject.execute("foo 123", source), is(42)); + verify(command).run(any(CommandContext.class)); + } + @SuppressWarnings("unchecked") @Test public void testCreateAndExecuteOffsetCommand() throws Exception { @@ -70,6 +81,14 @@ public void testCreateAndExecuteOffsetCommand() throws Exception { verify(command).run(any(CommandContext.class)); } + @Test + public void testCreateAndExecuteCaseInsensitiveOffsetCommand() throws Exception { + subject.register(literal("Foo").executes(command).caseInsensitive(true)); + + assertThat(subject.execute(inputWithOffset("/foo", 1), source), is(42)); + verify(command).run(any(CommandContext.class)); + } + @SuppressWarnings("unchecked") @Test public void testCreateAndMergeCommands() throws Exception { diff --git a/src/test/java/com/mojang/brigadier/tree/LiteralCommandNodeTest.java b/src/test/java/com/mojang/brigadier/tree/LiteralCommandNodeTest.java index a053ceac..0c58ab82 100644 --- a/src/test/java/com/mojang/brigadier/tree/LiteralCommandNodeTest.java +++ b/src/test/java/com/mojang/brigadier/tree/LiteralCommandNodeTest.java @@ -47,6 +47,18 @@ public void testParse() throws Exception { assertThat(reader.getRemaining(), equalTo(" bar")); } + @Test + public void testCaseInsensitiveParse() throws Exception { + try { + node.caseInsensitive(true); + final StringReader reader = new StringReader("FoO bar"); + node.parse(reader, contextBuilder); + assertThat(reader.getRemaining(), equalTo(" bar")); + } finally { + node.caseInsensitive(false); + } + } + @Test public void testParseExact() throws Exception { final StringReader reader = new StringReader("foo");