reworked parsing
This commit is contained in:
parent
8897579a12
commit
ac6a95232e
22 changed files with 360 additions and 441 deletions
156
.idea/workspace.xml
generated
156
.idea/workspace.xml
generated
|
|
@ -5,15 +5,28 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="6414223f-1761-4683-97f5-9dab59d6c44a" name="Changes" comment=".">
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/CommandHandlerTest.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/CommandParserTest.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/ENV.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser2/AbstractCommandParser.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser2/InvocationCommandParser.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser2/SuggestionCommandParser.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/build.gradle.kts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/CommandParser.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/CommandParser.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/BaseDependenciesConvention.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/BaseDependenciesConvention.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/ScrowPublishConvention.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/ScrowPublishConvention.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/configureScrowRepo.kt" beforeDir="false" afterPath="$PROJECT_DIR$/../build-logic/convention/src/main/kotlin/scrow/configureScrowRepo.kt" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/TODO" beforeDir="false" afterPath="$PROJECT_DIR$/TODO" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/build.gradle.kts" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle.kts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/BukkitKenCommand.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/TabCompleteListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-bukkit/src/main/java/de/kentoj/kencommandapi/TabCompleteListener.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/CommandHandler.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/node/CommandNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/literal/Literal.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/node/RootCommandNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/literal/RootLiteral.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/CommandParser.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/parser/ParseResult.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/HasPermissionMethod.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/api/platform/HasPermissionMethod.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/CommandNodeImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/LiteralImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/RootCommandNodeImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/main/java/de/kentoj/kencommandapi/internal/RootLiteralImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/CommandHandlerTest.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/CommandHandlerTest.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/CommandParserTest.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/ENV.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-core/src/test/java/de/kentoj/kencommandapi/api/parser/ENV.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/CommandAPI.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/kencommandapi-velocity/src/main/java/de/kentoj/kencommandapi/VelocityCommand.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
|
@ -58,6 +71,13 @@
|
|||
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
|
||||
<item name="Tasks" type="e4a08cd1:TasksNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
|
||||
<item name="KenCommandAPI" type="2d1252cf:ModuleNode" />
|
||||
<item name="Tasks" type="e4a08cd1:TasksNode" />
|
||||
<item name="build" type="c8890929:TasksNode$1" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
|
||||
<item name="KenCommandAPI" type="f1a62948:ProjectNode" />
|
||||
|
|
@ -114,41 +134,41 @@
|
|||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [:kencommandapi-core:de.kentoj.kencommandapi.Main.main()].executor": "Run",
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [build].executor": "Run",
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [publish].executor": "Run",
|
||||
"Gradle.CommandParserTest.checkArgumentExpected.executor": "Run",
|
||||
"Gradle.Download Sources.executor": "Run",
|
||||
"Gradle.KenCommandAPI [:de.kencommand.Main.main()].executor": "Run",
|
||||
"Gradle.KenCommandAPI [assemble].executor": "Run",
|
||||
"Gradle.KenCommandAPI [buildEnvironment].executor": "Run",
|
||||
"Gradle.KenCommandAPI [build].executor": "Run",
|
||||
"Gradle.KenCommandAPI [clean test].executor": "Run",
|
||||
"Gradle.KenCommandAPI [clean].executor": "Run",
|
||||
"Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository].executor": "Run",
|
||||
"Gradle.KenCommandAPI [publish].executor": "Run",
|
||||
"Gradle.KenCommandAPI [test].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [build].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [generatePomFileForKenCommandAPIBukkitPublication].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [publishAllPublicationsToScrowRepository].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [publish].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-velocity [publish].executor": "Run",
|
||||
"Gradle.kencommandapi-core [build].executor": "Run",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "/home/a/src/scrow/KenCommandAPI/kencommandapi-core",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.15",
|
||||
"project.structure.side.proportion": "0.6268199",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager"
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [:kencommandapi-core:de.kentoj.kencommandapi.Main.main()].executor": "Run",
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [build].executor": "Run",
|
||||
"Gradle./home/a/src/kento2/KenCommandAPI/kencommandapi-core [publish].executor": "Run",
|
||||
"Gradle.CommandParserTest.checkArgumentExpected.executor": "Run",
|
||||
"Gradle.Download Sources.executor": "Run",
|
||||
"Gradle.KenCommandAPI [:de.kencommand.Main.main()].executor": "Run",
|
||||
"Gradle.KenCommandAPI [assemble].executor": "Run",
|
||||
"Gradle.KenCommandAPI [buildEnvironment].executor": "Run",
|
||||
"Gradle.KenCommandAPI [build].executor": "Run",
|
||||
"Gradle.KenCommandAPI [clean test].executor": "Run",
|
||||
"Gradle.KenCommandAPI [clean].executor": "Run",
|
||||
"Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository].executor": "Run",
|
||||
"Gradle.KenCommandAPI [publish].executor": "Run",
|
||||
"Gradle.KenCommandAPI [test].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [build].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [generatePomFileForKenCommandAPIBukkitPublication].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [publishAllPublicationsToScrowRepository].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-bukkit [publish].executor": "Run",
|
||||
"Gradle.KenCommandAPI:kencommandapi-velocity [publish].executor": "Run",
|
||||
"Gradle.kencommandapi-core [build].executor": "Run",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "/home/a/src/scrow/core",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.15",
|
||||
"project.structure.side.proportion": "0.6268199",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager"
|
||||
}
|
||||
}]]></component>
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CreateClassDialog.RecentsKey">
|
||||
<recent name="de.kentoj.kencommandapi.api" />
|
||||
|
|
@ -166,11 +186,11 @@
|
|||
<recent name="$PROJECT_DIR$/kencommandapi-core" />
|
||||
</key>
|
||||
<key name="CopyClassDialog.RECENTS_KEY">
|
||||
<recent name="de.kentoj.kencommandapi.api.parser2" />
|
||||
<recent name="de.kentoj.kencommandapi.api.invocation" />
|
||||
<recent name="de.kentoj.kencommandapi.internal" />
|
||||
<recent name="de.kentoj.kencommandapi.api" />
|
||||
<recent name="de.kentoj.kencommandapi.impl" />
|
||||
<recent name="de.kentoj.kencommandapi.api.structure.argument.types" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunAnythingCache">
|
||||
|
|
@ -182,7 +202,7 @@
|
|||
<command value="gradlew test" />
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Gradle.KenCommandAPI [test]">
|
||||
<component name="RunManager" selected="Gradle.KenCommandAPI [publish]">
|
||||
<configuration name="CommandParserTest.checkArgumentExpected" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
|
|
@ -207,6 +227,28 @@
|
|||
<RunAsTest>true</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="KenCommandAPI [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="build" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="KenCommandAPI [clean test]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
|
|
@ -230,28 +272,6 @@
|
|||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="KenCommandAPI [publishAllPublicationsToScrowRepository]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="publishAllPublicationsToScrowRepository" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="KenCommandAPI [publish]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
|
|
@ -298,11 +318,11 @@
|
|||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="Gradle.KenCommandAPI [publish]" />
|
||||
<item itemvalue="Gradle.KenCommandAPI [build]" />
|
||||
<item itemvalue="Gradle.KenCommandAPI [test]" />
|
||||
<item itemvalue="Gradle.KenCommandAPI [clean test]" />
|
||||
<item itemvalue="Gradle.CommandParserTest.checkArgumentExpected" />
|
||||
<item itemvalue="Gradle.KenCommandAPI [publish]" />
|
||||
<item itemvalue="Gradle.KenCommandAPI [publishAllPublicationsToScrowRepository]" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
|
|
|
|||
5
TODO
5
TODO
|
|
@ -1,4 +1 @@
|
|||
- use version catalog
|
||||
- fix missing ArgumentExpected error at first arg or smth (maybe all args are shifted ???)
|
||||
- make sure permissions of literals work
|
||||
- fix suggestions/tab completion
|
||||
- suggest next literal/argument
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
group = "de.kentoj.scrow"
|
||||
version = "0.32"
|
||||
version = "0.33-SNAPSHOT"
|
||||
|
||||
subprojects {
|
||||
group = rootProject.group
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package de.kentoj.kencommandapi;
|
||||
|
||||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
@ -10,18 +10,18 @@ import java.util.Arrays;
|
|||
|
||||
public class BukkitKenCommand extends Command {
|
||||
|
||||
private final RootCommandNode<CommandSender> rootNode;
|
||||
private final RootLiteral<CommandSender> rootNode;
|
||||
private final CommandHandler<CommandSender> commandHandler;
|
||||
|
||||
protected BukkitKenCommand(
|
||||
CommandHandler<CommandSender> commandHandler,
|
||||
RootCommandNode<CommandSender> rootNode
|
||||
RootLiteral<CommandSender> rootLiteral
|
||||
) {
|
||||
super(rootNode.getNames()[0]);
|
||||
super(rootLiteral.getNames()[0]);
|
||||
this.commandHandler = commandHandler;
|
||||
this.rootNode = rootNode;
|
||||
this.setAliases(Arrays.asList(rootNode.getNames()));
|
||||
this.setPermission(rootNode.getPermission());
|
||||
this.rootNode = rootLiteral;
|
||||
this.setAliases(Arrays.asList(rootLiteral.getNames()));
|
||||
this.setPermission(rootLiteral.getPermission());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package de.kentoj.kencommandapi;
|
||||
|
||||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.parser.CommandParser;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
|
|
@ -17,12 +16,11 @@ import java.util.List;
|
|||
public class CommandAPI {
|
||||
|
||||
private final CommandHandler<CommandSender> commandHandler;
|
||||
private final List<RootCommandNode<CommandSender>> registeredNodes = new ArrayList<>();
|
||||
private final List<RootLiteral<CommandSender>> registeredNodes = new ArrayList<>();
|
||||
private final SimpleCommandMap commandMap;
|
||||
|
||||
public CommandAPI(Plugin plugin) {
|
||||
this.commandHandler = new CommandHandler<>(new CommandParser<>(Permissible::hasPermission),
|
||||
CommandSender::sendMessage, Permissible::hasPermission);
|
||||
this.commandHandler = new CommandHandler<>(CommandSender::sendMessage, Permissible::hasPermission);
|
||||
Bukkit.getPluginManager().registerEvents(new TabCompleteListener(this, commandHandler), plugin);
|
||||
|
||||
try {
|
||||
|
|
@ -34,7 +32,7 @@ public class CommandAPI {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable RootCommandNode<CommandSender> getRegistered(String name) {
|
||||
@Nullable RootLiteral<CommandSender> getRegistered(String name) {
|
||||
for (var node : registeredNodes) {
|
||||
for (String nodeName : node.getNames()) {
|
||||
if (nodeName.equals(name)) return node;
|
||||
|
|
@ -43,7 +41,7 @@ public class CommandAPI {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void register(RootCommandNode<CommandSender> rootNode) {
|
||||
public void register(RootLiteral<CommandSender> rootNode) {
|
||||
registeredNodes.add(rootNode);
|
||||
commandMap.register(rootNode.getNames()[0], new BukkitKenCommand(commandHandler, rootNode));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class TabCompleteListener implements Listener {
|
||||
|
||||
|
|
@ -17,11 +19,11 @@ public class TabCompleteListener implements Listener {
|
|||
public void onAsyncTabComplete(AsyncTabCompleteEvent ev) {
|
||||
if (!ev.isCommand()) return;
|
||||
|
||||
var args = ev.getBuffer().split(" ");
|
||||
var args = ev.getBuffer().substring(1).split(" ");
|
||||
var label = args[0];
|
||||
var rootNode = commandAPI.getRegistered(label);
|
||||
if (rootNode == null) return;
|
||||
ev.setHandled(true);
|
||||
ev.setCompletions(commandHandler.getSuggestions(rootNode, ev.getSender(), args));
|
||||
ev.setCompletions(commandHandler.getSuggestions(rootNode, ev.getSender(), Arrays.copyOfRange(args, 1, args.length)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,66 +1,46 @@
|
|||
package de.kentoj.kencommandapi.api;
|
||||
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandContext;
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.parser.CommandParser;
|
||||
import de.kentoj.kencommandapi.api.parser.ParseResult;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import de.kentoj.kencommandapi.api.parser2.InvocationCommandParser;
|
||||
import de.kentoj.kencommandapi.api.parser2.SuggestionCommandParser;
|
||||
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
|
||||
import de.kentoj.kencommandapi.api.platform.SendMessageMethod;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CommandHandler<T> {
|
||||
|
||||
private final CommandParser<T> commandParser;
|
||||
private final SendMessageMethod<T> sendMessageMethod;
|
||||
private final HasPermissionMethod<T> hasPermissionMethod;
|
||||
|
||||
public void invoke(RootCommandNode<T> rootNode, T sender, String[] args) {
|
||||
var parseResult = commandParser.parseLiteral(rootNode, sender, args, true);
|
||||
if (!(parseResult instanceof ParseResult.Success<T>)) {
|
||||
sendMessageMethod.send(sender, rootNode.getMessageStyle().err(parseResult.getMessage()));
|
||||
return;
|
||||
private final InvocationCommandParser<T> invocationParser;
|
||||
private final SuggestionCommandParser<T> suggestionParser;
|
||||
|
||||
public CommandHandler(SendMessageMethod<T> sendMessageMethod, HasPermissionMethod<T> hasPermissionMethod) {
|
||||
this.sendMessageMethod = sendMessageMethod;
|
||||
invocationParser = new InvocationCommandParser<>(hasPermissionMethod);
|
||||
suggestionParser = new SuggestionCommandParser<>(hasPermissionMethod);
|
||||
}
|
||||
|
||||
var ctx = new CommandContext<>(sender, ((ParseResult.Success<T>) parseResult).getParsedArguments());
|
||||
assert parseResult.getLiteral().getExecutor() != null;
|
||||
parseResult.getLiteral().getExecutor().execute(ctx).whenComplete((result, ex) -> {
|
||||
@SuppressWarnings("CodeBlock2Expr")
|
||||
public void invoke(RootLiteral<T> rootLiteral, T sender, String[] args) {
|
||||
invocationParser.invoke(rootLiteral, sender, args)
|
||||
.ifSuccessOrElse(data -> {
|
||||
var ctx = new CommandContext<>(sender, data.getArguments());
|
||||
data.getExecutor().execute(ctx).whenComplete((result, ex) -> {
|
||||
if (ex != null)
|
||||
sendMessageMethod.send(sender, rootNode.getMessageStyle().exception(ex));
|
||||
result.ifFailure(failure ->
|
||||
sendMessageMethod.send(sender, rootNode.getMessageStyle().err(failure)));
|
||||
sendMessageMethod.send(sender, rootLiteral.getMessageStyle().exception(ex));
|
||||
result.ifFailure(err ->
|
||||
sendMessageMethod.send(sender, rootLiteral.getMessageStyle().err(err)));
|
||||
});
|
||||
}, err -> {
|
||||
sendMessageMethod.send(sender, rootLiteral.getMessageStyle().err(err));
|
||||
});
|
||||
}
|
||||
|
||||
public List<String> getSuggestions(RootCommandNode<T> rootNode, T sender, String[] args) {
|
||||
var parseResult = commandParser.parseLiteral(rootNode, sender, args, false);
|
||||
|
||||
if (parseResult instanceof ParseResult.ArgumentExpected<T>) {
|
||||
var arg = ((ParseResult.ArgumentExpected<T>) parseResult).getArgument();
|
||||
return arg.getSuggestionProvider().suggest(sender);
|
||||
}
|
||||
|
||||
String filter = null;
|
||||
if (parseResult instanceof ParseResult.UnknownLiteral<T>)
|
||||
filter = ((ParseResult.UnknownLiteral<T>) parseResult).getInput();
|
||||
else if (parseResult instanceof ParseResult.NoPermission<T>)
|
||||
filter = ((ParseResult.NoPermission<T>) parseResult).getInput();
|
||||
return getSuggestions(sender, parseResult.getLiteral(), filter);
|
||||
}
|
||||
|
||||
private List<String> getSuggestions(T sender, CommandNode<T> literal, @Nullable String filter) {
|
||||
var stream = literal.getLiterals().stream()
|
||||
.filter(lit -> lit.getPermission() != null && hasPermissionMethod.hasPermission(sender, lit.getPermission()))
|
||||
.map(CommandNode::getNames)
|
||||
.flatMap(Arrays::stream);
|
||||
if (filter != null)
|
||||
stream = stream.filter(f -> f.toLowerCase().contains(filter.toLowerCase()));
|
||||
|
||||
return stream.toList();
|
||||
public List<String> getSuggestions(RootLiteral<T> rootNode, T sender, String[] args) {
|
||||
return suggestionParser.getSuggestions(rootNode, sender, args);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +1,23 @@
|
|||
package de.kentoj.kencommandapi.api.node;
|
||||
package de.kentoj.kencommandapi.api.literal;
|
||||
|
||||
import de.kentoj.kencommandapi.api.platform.MessageStyle;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||
import de.kentoj.kencommandapi.internal.CommandNodeImpl;
|
||||
import de.kentoj.kencommandapi.internal.RootCommandNodeImpl;
|
||||
import de.kentoj.kencommandapi.internal.LiteralImpl;
|
||||
import de.kentoj.kencommandapi.internal.RootLiteralImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface CommandNode<T> {
|
||||
static <T> CommandNode<T> node(String... name) {
|
||||
return new CommandNodeImpl<>(name);
|
||||
public interface Literal<T> {
|
||||
static <T> Literal<T> literal(String... name) {
|
||||
return new LiteralImpl<>(name);
|
||||
}
|
||||
|
||||
static <T> RootCommandNode<T> rootNode(MessageStyle messageStyle, String...name) {
|
||||
return new RootCommandNodeImpl<>(messageStyle, name);
|
||||
static <T> RootLiteral<T> rootLiteral(MessageStyle messageStyle, String...name) {
|
||||
return new RootLiteralImpl<>(messageStyle, name);
|
||||
}
|
||||
|
||||
@NotNull String[] getNames();
|
||||
|
|
@ -32,7 +32,8 @@ public interface CommandNode<T> {
|
|||
|
||||
/**
|
||||
* @throws IllegalArgumentException if there is already an argument with the same id
|
||||
* @throws IllegalStateException if a greedy argument was added to the node previously
|
||||
* @throws IllegalStateException if a greedy argument was added to the literal previously
|
||||
* @throws IllegalStateException if the literal already has a child literal assigned to it
|
||||
*/
|
||||
<V> void addArgument(CommandArgument<T, V> argument);
|
||||
|
||||
|
|
@ -48,13 +49,14 @@ public interface CommandNode<T> {
|
|||
|
||||
/**
|
||||
* @throws IllegalArgumentException if there is already a literal with the same name
|
||||
* @throws IllegalStateException if a greedy argument was added to the node previously
|
||||
* @throws IllegalStateException if a greedy argument was added to the literal previously
|
||||
* @throws IllegalStateException if the literal already has an argument assigned to it
|
||||
*/
|
||||
void addLiteral(@NotNull CommandNode<T> commandNode);
|
||||
void addLiteral(@NotNull Literal<T> literal);
|
||||
|
||||
@Nullable CommandNode<T> getLiteral(@NotNull String name);
|
||||
@Nullable Literal<T> getLiteral(@NotNull String name);
|
||||
|
||||
@NotNull Set<CommandNode<T>> getLiterals();
|
||||
@NotNull Set<Literal<T>> getLiterals();
|
||||
|
||||
@Nullable String getPermission();
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package de.kentoj.kencommandapi.api.node;
|
||||
package de.kentoj.kencommandapi.api.literal;
|
||||
|
||||
import de.kentoj.kencommandapi.api.platform.MessageStyle;
|
||||
|
||||
public interface RootCommandNode<T> extends CommandNode<T> {
|
||||
public interface RootLiteral<T> extends Literal<T> {
|
||||
|
||||
MessageStyle getMessageStyle();
|
||||
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
package de.kentoj.kencommandapi.api.parser;
|
||||
|
||||
import com.leakyabstractions.result.api.Result;
|
||||
import com.leakyabstractions.result.core.Results;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
|
||||
import de.kentoj.kencommandapi.internal.ParsedArgumentImpl;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CommandParser<T> {
|
||||
|
||||
private final HasPermissionMethod<T> hasPermissionMethod;
|
||||
|
||||
public ParseResult<T> parseLiteral(RootCommandNode<T> rootNode, T sender, String[] args, boolean parseArgs) {
|
||||
CommandNode<T> cur = rootNode;
|
||||
final Iterator<String> argStrIter = Arrays.stream(args).iterator();
|
||||
final Map<String, ParsedArgument<T, ?>> parsedArguments = new HashMap<>();
|
||||
|
||||
while (true) {
|
||||
for (var nodeArg : cur.getArguments()) {
|
||||
var parsed = parseArgument(rootNode, nodeArg, argStrIter, sender, parseArgs);
|
||||
if (parsed.hasFailure())
|
||||
return parsed.getFailure().orElseThrow();
|
||||
if (parseArgs)
|
||||
parsedArguments.put(nodeArg.getId(), parsed.getSuccess().orElseThrow());
|
||||
}
|
||||
|
||||
if (!argStrIter.hasNext()) {
|
||||
if (cur.getExecutor() == null)
|
||||
return new ParseResult.LiteralExpected<>(cur);
|
||||
return new ParseResult.Success<>(cur, parsedArguments);
|
||||
}
|
||||
|
||||
var argStr = argStrIter.next();
|
||||
var nextNode = cur.getLiteral(argStr);
|
||||
if (nextNode == null)
|
||||
return new ParseResult.UnknownLiteral<>(cur, argStr);
|
||||
if (nextNode.getPermission() != null && !hasPermissionMethod.hasPermission(sender, nextNode.getPermission()))
|
||||
return new ParseResult.NoPermission<>(cur, argStr);
|
||||
cur = nextNode;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Result<ParsedArgument<T, Object>, ParseResult<T>> parseArgument(
|
||||
CommandNode<T> node,
|
||||
CommandArgument<T, ?> nodeArg,
|
||||
Iterator<String> args,
|
||||
T sender,
|
||||
boolean parseArgs
|
||||
) {
|
||||
if (!args.hasNext()) {
|
||||
if (nodeArg.getDefaultValueProvider() == null)
|
||||
return Results.failure(new ParseResult.ArgumentExpected<>(node, nodeArg));
|
||||
var value = nodeArg.getDefaultValueProvider().apply(sender);
|
||||
return Results.success(toParsed(value, nodeArg));
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
var argStr = getRawArgument(args, nodeArg);
|
||||
if (parseArgs) {
|
||||
try {
|
||||
value = nodeArg.getType().parseInput(argStr);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return Results.failure(new ParseResult.IllegalArgument<>(node, nodeArg, ex.getMessage(), argStr));
|
||||
}
|
||||
}
|
||||
|
||||
var parsedArg = new ParsedArgumentImpl<>(value, (CommandArgument<T, Object>) nodeArg);
|
||||
return Results.success(parsedArg);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ParsedArgument<T, Object> toParsed(Object value, CommandArgument<T, ?> arg) {
|
||||
return new ParsedArgumentImpl<>(value, (CommandArgument<T, Object>) arg);
|
||||
}
|
||||
|
||||
private String getRawArgument(Iterator<String> args, CommandArgument<T, ?> arg) {
|
||||
StringBuilder rawArgument = new StringBuilder();
|
||||
|
||||
if (arg.getType().isGreedy()) {
|
||||
while (args.hasNext()) {
|
||||
rawArgument.append(" ");
|
||||
rawArgument.append(args.next());
|
||||
}
|
||||
rawArgument.deleteCharAt(0);
|
||||
} else {
|
||||
rawArgument = new StringBuilder(args.next());
|
||||
}
|
||||
|
||||
return rawArgument.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package de.kentoj.kencommandapi.api.parser;
|
||||
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract sealed class ParseResult<T> permits ParseResult.IllegalArgument, ParseResult.ArgumentExpected,
|
||||
ParseResult.LiteralExpected, ParseResult.NoPermission, ParseResult.Success, ParseResult.UnknownLiteral {
|
||||
|
||||
/**
|
||||
* @return last successfully literal
|
||||
*/
|
||||
public abstract CommandNode<T> getLiteral();
|
||||
|
||||
public abstract String getMessage();
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class ArgumentExpected<T> extends ParseResult<T> {
|
||||
@Getter
|
||||
private final CommandNode<T> literal;
|
||||
@Getter
|
||||
private final CommandArgument<T, ?> argument;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Argument expected: " + argument.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class UnknownLiteral<T> extends ParseResult<T> {
|
||||
private final CommandNode<T> previousLiteral;
|
||||
@Getter
|
||||
private final String input;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Unknown subcommand: " + input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandNode<T> getLiteral() {
|
||||
return previousLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class LiteralExpected<T> extends ParseResult<T> {
|
||||
@Getter
|
||||
private final CommandNode<T> literal;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Subcommand expected";
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class Success<T> extends ParseResult<T> {
|
||||
@Getter
|
||||
private final CommandNode<T> literal;
|
||||
@Getter
|
||||
private final Map<String, ParsedArgument<T, ?>> parsedArguments;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class NoPermission<T> extends ParseResult<T> {
|
||||
@Getter
|
||||
private final CommandNode<T> literal;
|
||||
@Getter
|
||||
private final String input;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Unknown subcommand: " + input;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static final class IllegalArgument<T> extends ParseResult<T> {
|
||||
@Getter
|
||||
private final CommandNode<T> literal;
|
||||
private final CommandArgument<T, ?> argument;
|
||||
private final String message;
|
||||
/**
|
||||
* Input passed to the parser
|
||||
*/
|
||||
@Getter
|
||||
private final String argStr;
|
||||
|
||||
public IllegalArgument(CommandNode<T> literal, CommandArgument<T, ?> argument, Throwable throwable, String argStr) {
|
||||
this.literal = literal;
|
||||
this.argument = argument;
|
||||
this.argStr = argStr;
|
||||
while (throwable.getMessage() == null && throwable.getCause() != null)
|
||||
throwable = throwable.getCause();
|
||||
message = throwable.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Illegal argument '" + argStr + "' for " + argument.getId() + ": " + message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package de.kentoj.kencommandapi.api.parser2;
|
||||
|
||||
import com.leakyabstractions.result.api.Result;
|
||||
import com.leakyabstractions.result.core.Results;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.literal.Literal;
|
||||
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractCommandParser<T> {
|
||||
|
||||
private final HasPermissionMethod<T> hasPermission;
|
||||
|
||||
protected boolean hasPermission(T sender, Literal<T> literal) {
|
||||
if (literal.getPermission() == null) return true;
|
||||
return hasPermission.test(sender, literal.getPermission());
|
||||
}
|
||||
|
||||
protected String parseInput(String[] args, AtomicInteger index, boolean isGreedy) {
|
||||
if (!isGreedy)
|
||||
return args[index.getAndIncrement()];
|
||||
|
||||
var ret = String.join(" ", Arrays.copyOfRange(args, index.get(), args.length));
|
||||
index.set(args.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected Result<Object, String> parseArgument(CommandArgument<T, Object> argument, String input) {
|
||||
try {
|
||||
return Results.success(argument.getType().parseInput(input));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return Results.failure("Illegal argument '" + input + "' for " + argument.getId() + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package de.kentoj.kencommandapi.api.parser2;
|
||||
|
||||
import com.leakyabstractions.result.api.Result;
|
||||
import com.leakyabstractions.result.core.Results;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||
import de.kentoj.kencommandapi.api.literal.Literal;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
|
||||
import de.kentoj.kencommandapi.internal.ParsedArgumentImpl;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class InvocationCommandParser<T> extends AbstractCommandParser<T> {
|
||||
|
||||
public InvocationCommandParser(HasPermissionMethod<T> hasPermission) {
|
||||
super(hasPermission);
|
||||
}
|
||||
|
||||
public Result<ExecutionData, String> invoke(
|
||||
RootLiteral<T> rootLiteral,
|
||||
T sender,
|
||||
String[] args
|
||||
) {
|
||||
Map<String, ParsedArgument<T, ?>> parsedArguments = new HashMap<>();
|
||||
Literal<T> currentLiteral = rootLiteral;
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
|
||||
while (true) {
|
||||
for (var _argument : currentLiteral.getArguments()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var argument = ((CommandArgument<T, Object>) _argument);
|
||||
|
||||
Object value;
|
||||
if (index.get() >= args.length) {
|
||||
if (argument.getDefaultValueProvider() == null)
|
||||
return Results.failure("Argument expected: " + argument.getId());
|
||||
value = argument.getDefaultValueProvider().apply(sender);
|
||||
} else {
|
||||
var input = parseInput(args, index, argument.getType().isGreedy());
|
||||
var parseResult = parseArgument(argument, input);
|
||||
if (parseResult.hasFailure()) return parseResult.mapSuccess(__ -> null);
|
||||
value = parseResult.getSuccess().orElseThrow();
|
||||
}
|
||||
|
||||
parsedArguments.put(argument.getId(), new ParsedArgumentImpl<>(value, argument));
|
||||
}
|
||||
|
||||
if (index.get() >= args.length) {
|
||||
if (currentLiteral.getExecutor() == null)
|
||||
return Results.failure("Literal expected");
|
||||
break;
|
||||
}
|
||||
|
||||
var literalName = args[index.getAndIncrement()];
|
||||
var nextLiteral = currentLiteral.getLiteral(literalName);
|
||||
if (nextLiteral == null || !hasPermission(sender, nextLiteral))
|
||||
return Results.failure("Unknown literal: " + literalName);
|
||||
currentLiteral = nextLiteral;
|
||||
}
|
||||
|
||||
return Results.success(new ExecutionData(currentLiteral.getExecutor(), parsedArguments));
|
||||
}
|
||||
|
||||
@Value
|
||||
public class ExecutionData {
|
||||
CommandExecutor<T> executor;
|
||||
Map<String, ParsedArgument<T, ?>> arguments;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package de.kentoj.kencommandapi.api.parser2;
|
||||
|
||||
import de.kentoj.kencommandapi.api.literal.Literal;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import de.kentoj.kencommandapi.api.platform.HasPermissionMethod;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SuggestionCommandParser<T> extends AbstractCommandParser<T> {
|
||||
|
||||
public SuggestionCommandParser(HasPermissionMethod<T> hasPermission) {
|
||||
super(hasPermission);
|
||||
}
|
||||
|
||||
public List<String> getSuggestions(
|
||||
RootLiteral<T> rootNode,
|
||||
T sender,
|
||||
String[] args
|
||||
) {
|
||||
Literal<T> currentLiteral = rootNode;
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
|
||||
while (true) {
|
||||
for (var argument : currentLiteral.getArguments()) {
|
||||
// TODO somewhere suggest next argument at trailing space
|
||||
if (index.getAndIncrement() >= args.length)
|
||||
return argument.getSuggestionProvider().suggest(sender);
|
||||
if (argument.getType().isGreedy())
|
||||
index.set(args.length);
|
||||
}
|
||||
|
||||
if (index.get() >= args.length) {
|
||||
// TODO suggest next argument at trailing space
|
||||
if (currentLiteral.getExecutor() == null)
|
||||
return suggestions(currentLiteral, sender).toList();
|
||||
}
|
||||
|
||||
var input = args[index.getAndIncrement()];
|
||||
var nextLiteral = currentLiteral.getLiteral(input);
|
||||
if (nextLiteral == null || !hasPermission(sender, nextLiteral)) {
|
||||
var finalInput = input.toLowerCase();
|
||||
return suggestions(currentLiteral, sender)
|
||||
.filter(name -> name.toLowerCase().startsWith(finalInput))
|
||||
.toList();
|
||||
}
|
||||
|
||||
currentLiteral = nextLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
private Stream<String> suggestions(Literal<T> literal, T sender) {
|
||||
return literal.getLiterals().stream()
|
||||
.filter(lit -> hasPermission(sender, lit))
|
||||
.map(Literal::getNames)
|
||||
.flatMap(Arrays::stream);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,5 @@ package de.kentoj.kencommandapi.api.platform;
|
|||
|
||||
@FunctionalInterface
|
||||
public interface HasPermissionMethod<T> {
|
||||
boolean hasPermission(T sender, String permission);
|
||||
boolean test(T sender, String permission);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package de.kentoj.kencommandapi.internal;
|
||||
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import de.kentoj.kencommandapi.api.literal.Literal;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||
import lombok.Getter;
|
||||
|
|
@ -13,12 +13,12 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandNodeImpl<T> implements CommandNode<T> {
|
||||
public class LiteralImpl<T> implements Literal<T> {
|
||||
|
||||
@Getter
|
||||
private final String[] names;
|
||||
@Getter
|
||||
private final Set<CommandNode<T>> literals = new HashSet<>();
|
||||
private final Set<Literal<T>> literals = new HashSet<>();
|
||||
@Getter
|
||||
private final List<CommandArgument<T, ?>> arguments = new ArrayList<>();
|
||||
|
||||
|
|
@ -34,22 +34,22 @@ public class CommandNodeImpl<T> implements CommandNode<T> {
|
|||
@Setter
|
||||
private @Nullable String permission = null;
|
||||
|
||||
public CommandNodeImpl(String[] names) {
|
||||
public LiteralImpl(String[] names) {
|
||||
if (names.length == 0) throw new IllegalArgumentException("at least one name is required");
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLiteral(@NotNull CommandNode<T> commandNode) {
|
||||
public void addLiteral(@NotNull Literal<T> literal) {
|
||||
if (isGreedy()) throw new IllegalStateException("can't add literal to a node with a greedy argument");
|
||||
for (String name : commandNode.getNames())
|
||||
for (String name : literal.getNames())
|
||||
if (getLiteral(name) != null)
|
||||
throw new IllegalArgumentException("literal with same name already exists");
|
||||
literals.add(commandNode);
|
||||
literals.add(literal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandNode<T> getLiteral(@NotNull String name) {
|
||||
public Literal<T> getLiteral(@NotNull String name) {
|
||||
for (var literal : literals)
|
||||
for (String literalName : literal.getNames())
|
||||
if (literalName.equalsIgnoreCase(name)) return literal;
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
package de.kentoj.kencommandapi.internal;
|
||||
|
||||
import de.kentoj.kencommandapi.api.platform.MessageStyle;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class RootCommandNodeImpl<T> extends CommandNodeImpl<T> implements RootCommandNode<T> {
|
||||
public class RootLiteralImpl<T> extends LiteralImpl<T> implements RootLiteral<T> {
|
||||
@Setter
|
||||
@Getter
|
||||
private MessageStyle messageStyle;
|
||||
|
||||
public RootCommandNodeImpl(MessageStyle messageStyle, String[] names) {
|
||||
public RootLiteralImpl(MessageStyle messageStyle, String[] names) {
|
||||
super(names);
|
||||
this.messageStyle = messageStyle;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package de.kentoj.kencommandapi.api.parser;
|
|||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType;
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import de.kentoj.kencommandapi.api.literal.Literal;
|
||||
import de.kentoj.kencommandapi.api.platform.MessageStyle;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
@ -14,19 +14,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
public class CommandHandlerTest {
|
||||
|
||||
@Test
|
||||
void testSuggestions() {
|
||||
var rootNode = CommandNode.rootNode(MessageStyle.PLAIN, "someRootNode");
|
||||
void suggestArgument() {
|
||||
var rootNode = Literal.rootLiteral(MessageStyle.PLAIN, "someRootNode");
|
||||
var arg = CommandArgument.arg("someArg", new StringArgumentType<>());
|
||||
arg.setSuggestionProvider(__ -> List.of("a", "b", "c"));
|
||||
rootNode.addArgument(arg);
|
||||
rootNode.setExecutor(ENV.EMPTY_EXECUTOR);
|
||||
|
||||
var handler = new CommandHandler<>(
|
||||
new CommandParser<>((__, ___) -> true),
|
||||
(__, ___) -> {},
|
||||
(__, ___) -> true
|
||||
);
|
||||
var handler = new CommandHandler<>((__, ___) -> {}, (__, ___) -> true);
|
||||
var suggestions = handler.getSuggestions(rootNode, ENV.SENDER, new String[0]);
|
||||
assertEquals(List.of("a", "b", "c"), suggestions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void suggestLiterals() {
|
||||
var rootNode = Literal.rootLiteral(MessageStyle.PLAIN, "someRootNode");
|
||||
var literal1 = Literal.literal("lit1");
|
||||
var literal2 = Literal.literal("lit2");
|
||||
rootNode.addLiteral(literal1);
|
||||
rootNode.addLiteral(literal2);
|
||||
|
||||
var handler = new CommandHandler<>((__, ___) -> {}, (__, ___) -> true);
|
||||
var suggestions = handler.getSuggestions(rootNode, ENV.SENDER, new String[0]);
|
||||
assertEquals(List.of("lit1", "lit2"), suggestions.stream().sorted().toList());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
package de.kentoj.kencommandapi.api.parser;
|
||||
|
||||
import com.leakyabstractions.result.core.Results;
|
||||
import de.kentoj.kencommandapi.api.argument.CommandArgument;
|
||||
import de.kentoj.kencommandapi.api.argument.types.StringArgumentType;
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||
import de.kentoj.kencommandapi.api.invocation.ParsedArgument;
|
||||
import de.kentoj.kencommandapi.api.node.CommandNode;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.platform.MessageStyle;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
|
||||
public class CommandParserTest {
|
||||
|
||||
@Test
|
||||
void checkArgumentExpected() {
|
||||
RootCommandNode<Object> node = CommandNode.rootNode(MessageStyle.PLAIN, "someRootNode");
|
||||
var arg = CommandArgument.arg("someArg", new StringArgumentType<>(false));
|
||||
node.addArgument(arg);
|
||||
|
||||
var parsed = ENV.PARSER.parseLiteral(node, ENV.SENDER, new String[]{}, false);
|
||||
assertInstanceOf(ParseResult.ArgumentExpected.class, parsed);
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkGreedyStrings() {
|
||||
RootCommandNode<Object> node = CommandNode.rootNode(MessageStyle.PLAIN, "someRootNode");
|
||||
var arg = CommandArgument.arg("someArg", new StringArgumentType<>(true));
|
||||
node.addArgument(arg);
|
||||
node.setExecutor(ENV.EMPTY_EXECUTOR);
|
||||
|
||||
var parsed = ENV.PARSER.parseLiteral(node, ENV.SENDER, new String[]{"part1", "part2"}, true);
|
||||
Map<String, ParsedArgument<Object, ?>> parsedStr = ((ParseResult.Success<Object>) parsed).getParsedArguments();
|
||||
String str = (String) parsedStr.get("someArg").getValue();
|
||||
assertEquals("part1 part2", str);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
package de.kentoj.kencommandapi.api.parser;
|
||||
|
||||
import com.leakyabstractions.result.core.Results;
|
||||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.invocation.CommandExecutor;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ENV {
|
||||
public static final CommandParser<Object> PARSER = new CommandParser<>((__, ___) -> true);
|
||||
public static final CommandHandler<Object> PARSER =
|
||||
new CommandHandler<>((__, ___) -> {}, (__, ___) -> true);
|
||||
public static final Object SENDER = new Object();
|
||||
public static final CommandExecutor<Object> EMPTY_EXECUTOR = __ ->
|
||||
CompletableFuture.completedFuture(Results.success(new Object()));
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ package de.kentoj.kencommandapi;
|
|||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.parser.CommandParser;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
@ -13,13 +12,10 @@ import java.util.Arrays;
|
|||
public class CommandAPI {
|
||||
|
||||
private final ProxyServer server;
|
||||
private final CommandHandler<CommandSource> commandHandler = new CommandHandler<>(
|
||||
new CommandParser<>(CommandSource::hasPermission),
|
||||
CommandSource::sendMessage,
|
||||
CommandSource::hasPermission
|
||||
);
|
||||
private final CommandHandler<CommandSource> commandHandler =
|
||||
new CommandHandler<>(CommandSource::sendMessage, CommandSource::hasPermission);
|
||||
|
||||
public void register(RootCommandNode<CommandSource> rootNode) {
|
||||
public void register(RootLiteral<CommandSource> rootNode) {
|
||||
var cm = server.getCommandManager();
|
||||
var meta = cm.metaBuilder(rootNode.getNames()[0])
|
||||
.aliases(Arrays.copyOfRange(rootNode.getNames(), 1, rootNode.getNames().length))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package de.kentoj.kencommandapi;
|
|||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.command.SimpleCommand;
|
||||
import de.kentoj.kencommandapi.api.CommandHandler;
|
||||
import de.kentoj.kencommandapi.api.node.RootCommandNode;
|
||||
import de.kentoj.kencommandapi.api.literal.RootLiteral;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -12,7 +12,7 @@ import java.util.List;
|
|||
public class VelocityCommand implements SimpleCommand {
|
||||
|
||||
private final CommandHandler<CommandSource> commandHandler;
|
||||
private final RootCommandNode<CommandSource> rootNode;
|
||||
private final RootLiteral<CommandSource> rootNode;
|
||||
|
||||
@Override
|
||||
public void execute(Invocation invocation) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue