Skip to content

Commit 6eef2ec

Browse files
Adjust angle and rotation parsers for better suggestions, add more tests
1 parent 796ac84 commit 6eef2ec

File tree

3 files changed

+105
-11
lines changed

3 files changed

+105
-11
lines changed

cloud-bukkit/src/main/java/org/incendo/cloud/bukkit/parser/rotation/AngleParser.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,6 @@ public final class AngleParser<C> implements ArgumentParser<C, Angle>, BlockingS
9191
try {
9292
final boolean empty = commandInput.peekString().isEmpty() || commandInput.peek() == ' ';
9393
angle = empty ? 0 : commandInput.readFloat();
94-
95-
// You can have a prefix without a number, in which case we wouldn't consume the
96-
// subsequent whitespace. We do it manually.
97-
if (commandInput.hasRemainingInput() && commandInput.peek() == ' ') {
98-
commandInput.read();
99-
}
10094
} catch (final Exception e) {
10195
return ArgumentParseResult.failure(new FloatParser.FloatParseException(
10296
input,

cloud-bukkit/src/main/java/org/incendo/cloud/bukkit/parser/rotation/RotationParser.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,34 @@ public final class RotationParser<C> implements ArgumentParser<C, Rotation>, Blo
126126
final @NonNull CommandContext<C> commandContext,
127127
final @NonNull CommandInput input
128128
) {
129-
final int toSkip = Math.min(2, input.remainingTokens()) - 1;
130-
final StringBuilder prefix = new StringBuilder();
131-
for (int i = 0; i < toSkip; i++) {
132-
prefix.append(input.readStringSkipWhitespace()).append(" ");
129+
final CommandInput inputCopy = input.copy();
130+
131+
int idx = input.cursor();
132+
for (int i = 0; i < 2; i++) {
133+
input.skipWhitespace();
134+
idx = input.cursor();
135+
136+
if (!input.hasRemainingInput()) {
137+
break;
138+
}
139+
140+
final ArgumentParseResult<Angle> angle = this.angleParser.parse(
141+
commandContext,
142+
input
143+
);
144+
145+
if (angle.failure().isPresent() || !input.hasRemainingInput()) {
146+
break;
147+
}
133148
}
149+
input.cursor(idx);
134150

135151
if (input.hasRemainingInput() && input.peek() == '~') {
136-
prefix.append(input.read());
152+
input.moveCursor(1);
137153
}
138154

155+
final String prefix = inputCopy.difference(input, true);
156+
139157
return IntegerParser.getSuggestions(
140158
SUGGESTION_RANGE,
141159
input

cloud-bukkit/src/test/java/org/incendo/cloud/bukkit/parser/RotationArgumentTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,32 @@
2323
//
2424
package org.incendo.cloud.bukkit.parser;
2525

26+
import java.util.Arrays;
27+
import java.util.Collections;
28+
import java.util.List;
29+
import java.util.function.Function;
30+
import java.util.stream.Collectors;
2631
import java.util.stream.Stream;
2732
import org.bukkit.Location;
2833
import org.bukkit.command.CommandSender;
2934
import org.checkerframework.checker.nullness.qual.NonNull;
35+
import org.incendo.cloud.CommandManager;
3036
import org.incendo.cloud.bukkit.parser.rotation.Rotation;
3137
import org.incendo.cloud.bukkit.parser.rotation.RotationParser;
3238
import org.incendo.cloud.bukkit.util.ServerTest;
3339
import org.incendo.cloud.context.CommandInput;
40+
import org.incendo.cloud.execution.ExecutionCoordinator;
41+
import org.incendo.cloud.internal.CommandRegistrationHandler;
3442
import org.incendo.cloud.parser.ArgumentParseResult;
43+
import org.incendo.cloud.parser.flag.CommandFlag;
44+
import org.incendo.cloud.suggestion.Suggestion;
3545
import org.junit.jupiter.params.ParameterizedTest;
3646
import org.junit.jupiter.params.provider.Arguments;
3747
import org.junit.jupiter.params.provider.MethodSource;
3848
import org.junit.jupiter.params.provider.ValueSource;
3949

4050
import static com.google.common.truth.Truth.assertThat;
51+
import static org.junit.jupiter.api.Assertions.assertEquals;
4152
import static org.junit.jupiter.params.provider.Arguments.arguments;
4253

4354
public class RotationArgumentTest extends ServerTest {
@@ -95,4 +106,75 @@ void Parse_InvalidAngle_Failure(final @NonNull String input) {
95106
assertThat(result.parsedValue()).isEmpty();
96107
}
97108

109+
@ParameterizedTest
110+
@MethodSource
111+
void suggestions(final String input, final List<String> expectedSuggestions) {
112+
final CommandManager<CommandSender> manager = new CommandManager<CommandSender>(
113+
ExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler()
114+
) {
115+
@Override
116+
public boolean hasPermission(@NonNull CommandSender sender, @NonNull String permission) {
117+
return true;
118+
}
119+
};
120+
121+
manager.command(
122+
manager.commandBuilder("rotation")
123+
.required("rotation", RotationParser.rotationParser())
124+
);
125+
126+
final Function<String, String> suggestion = s -> "rotation " + s;
127+
assertEquals(
128+
expectedSuggestions,
129+
manager.suggestionFactory().suggestImmediately(this.commandContext().sender(), suggestion.apply(input))
130+
.list().stream().map(Suggestion::suggestion).collect(Collectors.toList())
131+
);
132+
}
133+
134+
@ParameterizedTest
135+
@MethodSource("suggestions")
136+
void suggestionsFlag(final String input, final List<String> expectedSuggestions) {
137+
final CommandManager<CommandSender> manager = new CommandManager<CommandSender>(
138+
ExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler()
139+
) {
140+
@Override
141+
public boolean hasPermission(@NonNull CommandSender sender, @NonNull String permission) {
142+
return true;
143+
}
144+
};
145+
146+
manager.command(
147+
manager.commandBuilder("flag")
148+
.flag(CommandFlag.builder("rot").withComponent(RotationParser.rotationParser()).build())
149+
);
150+
151+
final Function<String, String> flagSuggestion = s -> "flag --rot " + s;
152+
assertEquals(
153+
expectedSuggestions,
154+
manager.suggestionFactory().suggestImmediately(this.commandContext().sender(), flagSuggestion.apply(input))
155+
.list().stream().map(Suggestion::suggestion).collect(Collectors.toList())
156+
);
157+
}
158+
159+
static Stream<Arguments> suggestions() {
160+
return Stream.of(
161+
arguments("", Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9")),
162+
arguments("1", Arrays.asList("1", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19")),
163+
arguments("1 ", Arrays.asList("1 0", "1 1", "1 2", "1 3", "1 4", "1 5", "1 6", "1 7", "1 8", "1 9")),
164+
arguments("1 1", Arrays.asList("1 1", "1 10", "1 11", "1 12", "1 13", "1 14", "1 15", "1 16", "1 17", "1 18", "1 19")),
165+
arguments("1 0", Collections.singletonList("1 0")),
166+
arguments("1 1 ", Collections.emptyList()),
167+
arguments("0", Collections.singletonList("0")),
168+
arguments("0 ", Arrays.asList("0 0", "0 1", "0 2", "0 3", "0 4", "0 5", "0 6", "0 7", "0 8", "0 9")),
169+
arguments("0 1", Arrays.asList("0 1", "0 10", "0 11", "0 12", "0 13", "0 14", "0 15", "0 16", "0 17", "0 18", "0 19")),
170+
arguments("0 0", Collections.singletonList("0 0")),
171+
arguments("0 0 ", Collections.emptyList()),
172+
arguments("~", Arrays.asList("~0", "~1", "~2", "~3", "~4", "~5", "~6", "~7", "~8", "~9")),
173+
arguments("~ ~", Arrays.asList("~ ~0", "~ ~1", "~ ~2", "~ ~3", "~ ~4", "~ ~5", "~ ~6", "~ ~7", "~ ~8", "~ ~9")),
174+
arguments("~0", Collections.singletonList("~0")),
175+
arguments("~1", Arrays.asList("~1", "~10", "~11", "~12", "~13", "~14", "~15", "~16", "~17", "~18", "~19")),
176+
arguments("~1 ", Arrays.asList("~1 0", "~1 1", "~1 2", "~1 3", "~1 4", "~1 5", "~1 6", "~1 7", "~1 8", "~1 9"))
177+
);
178+
}
179+
98180
}

0 commit comments

Comments
 (0)