From d782de91b0568b93a80a3bf35d6eba2376d2a0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 4 Feb 2024 11:31:09 +0100 Subject: [PATCH] feat(minecraft-extras): switch examples to compiled snippets --- .editorconfig | 6 +- code/build.gradle.kts | 1 + code/gradle/libs.versions.toml | 4 +- .../cloud/snippet/AggregateParserExample.java | 48 +++++----- .../incendo/cloud/snippet/EitherExample.java | 26 +++--- .../cloud/snippet/UUIDParseException.java | 55 +++++------ .../org/incendo/cloud/snippet/UUIDParser.java | 26 +++--- .../MinecraftExceptionHandlerExample.java | 39 ++++++++ .../minecraft/MinecraftHelpExample.java | 92 +++++++++++++++++++ docs/minecraft/minecraft-extras.md | 82 ++--------------- main.py | 16 +++- 11 files changed, 236 insertions(+), 159 deletions(-) create mode 100644 code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftExceptionHandlerExample.java create mode 100644 code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftHelpExample.java diff --git a/.editorconfig b/.editorconfig index 196c0a4..a205b23 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,10 +13,10 @@ insert_final_newline = true indent_size = 4 [*.java] -indent_size = 4 +indent_size = 2 max_line_length = 130 -tab_width = 4 -ij_continuation_indent_size = 8 +tab_width = 2 +ij_continuation_indent_size = 2 ij_formatter_off_tag = @formatter:off ij_formatter_on_tag = @formatter:on ij_formatter_tags_enabled = false diff --git a/code/build.gradle.kts b/code/build.gradle.kts index 1fff618..f883304 100644 --- a/code/build.gradle.kts +++ b/code/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { implementation(libs.cloud.core) + implementation(libs.cloud.minecraft.extras) } indra { diff --git a/code/gradle/libs.versions.toml b/code/gradle/libs.versions.toml index 1ed1cab..4f154c2 100644 --- a/code/gradle/libs.versions.toml +++ b/code/gradle/libs.versions.toml @@ -1,10 +1,12 @@ [versions] indra = "3.1.3" -cloud = "2.0.0-beta.1" +cloud = "2.0.0-SNAPSHOT" +cloudMinecraft = "2.0.0-SNAPSHOT" [plugins] indra = { id = "net.kyori.indra", version.ref = "indra" } [libraries] cloud-core = { group = "org.incendo", name = "cloud-core", version.ref = "cloud" } +cloud-minecraft-extras = { group = "org.incendo", name = "cloud-minecraft-extras", version.ref = "cloudMinecraft" } diff --git a/code/src/main/java/org/incendo/cloud/snippet/AggregateParserExample.java b/code/src/main/java/org/incendo/cloud/snippet/AggregateParserExample.java index 931fe48..1645db1 100644 --- a/code/src/main/java/org/incendo/cloud/snippet/AggregateParserExample.java +++ b/code/src/main/java/org/incendo/cloud/snippet/AggregateParserExample.java @@ -13,31 +13,31 @@ */ public class AggregateParserExample { - public void example(final Command.@NonNull Builder commandBuilder) { - // --8<-- [start:snippet] - final AggregateParser locationParser = AggregateParser - .builder() - .withComponent("world", stringParser()) - .withComponent("x", integerParser()) - .withComponent("y", integerParser()) - .withComponent("z", integerParser()) - .withMapper(Location.class, (commandContext, aggregateCommandContext) -> { - final String world = aggregateCommandContext.get("world"); - final int x = aggregateCommandContext.get("x"); - final int y = aggregateCommandContext.get("y"); - final int z = aggregateCommandContext.get("z"); - return ArgumentParseResult.successFuture(new Location(world, x, y, z)); - }).build(); - // --8<-- [end:snippet] + public void example(final Command.@NonNull Builder commandBuilder) { + // --8<-- [start:snippet] + final AggregateParser locationParser = AggregateParser + .builder() + .withComponent("world", stringParser()) + .withComponent("x", integerParser()) + .withComponent("y", integerParser()) + .withComponent("z", integerParser()) + .withMapper(Location.class, (commandContext, aggregateCommandContext) -> { + final String world = aggregateCommandContext.get("world"); + final int x = aggregateCommandContext.get("x"); + final int y = aggregateCommandContext.get("y"); + final int z = aggregateCommandContext.get("z"); + return ArgumentParseResult.successFuture(new Location(world, x, y, z)); + }).build(); + // --8<-- [end:snippet] + } + + public static final class Location { + + public Location(final String world, final int x, final int y, final int z) { } + } - public static final class Location { + public static final class CommandSender { - public Location(final String world, final int x, final int y, final int z) { - } - } - - public static final class CommandSender { - - } + } } diff --git a/code/src/main/java/org/incendo/cloud/snippet/EitherExample.java b/code/src/main/java/org/incendo/cloud/snippet/EitherExample.java index 2f6a9e7..843781e 100644 --- a/code/src/main/java/org/incendo/cloud/snippet/EitherExample.java +++ b/code/src/main/java/org/incendo/cloud/snippet/EitherExample.java @@ -13,17 +13,17 @@ */ public class EitherExample { - public void example(final Command.@NonNull Builder commandBuilder) { - // --8<-- [start:snippet] - commandBuilder.required("either", ArgumentParser.firstOf(integerParser(), booleanParser())) - .handler(context -> { - Either either = context.get("either"); - if (either.primary().isPresent()){ - int integer = either.primary().get(); - } else { - boolean bool = either.fallback().get(); - } - }); - // --8<-- [end:snippet] - } + public void example(final Command.@NonNull Builder commandBuilder) { + // --8<-- [start:snippet] + commandBuilder.required("either", ArgumentParser.firstOf(integerParser(), booleanParser())) + .handler(context -> { + Either either = context.get("either"); + if (either.primary().isPresent()) { + int integer = either.primary().get(); + } else { + boolean bool = either.fallback().get(); + } + }); + // --8<-- [end:snippet] + } } diff --git a/code/src/main/java/org/incendo/cloud/snippet/UUIDParseException.java b/code/src/main/java/org/incendo/cloud/snippet/UUIDParseException.java index b9a9a38..a28348d 100644 --- a/code/src/main/java/org/incendo/cloud/snippet/UUIDParseException.java +++ b/code/src/main/java/org/incendo/cloud/snippet/UUIDParseException.java @@ -10,33 +10,34 @@ public final class UUIDParseException extends ParserException { - private final String input; - - public UUIDParseException(final @NonNull String input, final @NonNull CommandContext context) { - super( - UUIDParser.class, - context, - StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_UUID, - CaptionVariable.of("input", input)); - this.input = input; + private final String input; + + public UUIDParseException(final @NonNull String input, final @NonNull CommandContext context) { + super( + UUIDParser.class, + context, + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_UUID, + CaptionVariable.of("input", input) + ); + this.input = input; + } + + public String input() { + return this.input; + } + + public boolean equals(final Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + final UUIDParseException that = (UUIDParseException) o; + return this.input.equals(that.input()); + } else { + return false; } + } - public String input() { - return this.input; - } - - public boolean equals(final Object o) { - if (this == o) { - return true; - } else if (o != null && this.getClass() == o.getClass()) { - final UUIDParseException that = (UUIDParseException) o; - return this.input.equals(that.input()); - } else { - return false; - } - } - - public int hashCode() { - return Objects.hash(new Object[]{this.input}); - } + public int hashCode() { + return Objects.hash(new Object[]{this.input}); + } } diff --git a/code/src/main/java/org/incendo/cloud/snippet/UUIDParser.java b/code/src/main/java/org/incendo/cloud/snippet/UUIDParser.java index f35639d..62e8807 100644 --- a/code/src/main/java/org/incendo/cloud/snippet/UUIDParser.java +++ b/code/src/main/java/org/incendo/cloud/snippet/UUIDParser.java @@ -11,19 +11,19 @@ // --8<-- [start:snippet] public class UUIDParser implements ArgumentParser { - @Override - public @NonNull ArgumentParseResult parse( - @NonNull CommandContext context, - @NonNull CommandInput commandInput - ) { - final String input = commandInput.peekString(); // Does not remove the string from the input! - try { - final UUID uuid = UUID.fromString(input); - commandInput.readString(); // Removes the string from the input. - return ArgumentParseResult.success(uuid); - } catch (final IllegalArgumentException e) { - return ArgumentParseResult.failure(new UUIDParseException(input, context)); - } + @Override + public @NonNull ArgumentParseResult parse( + @NonNull CommandContext context, + @NonNull CommandInput commandInput + ) { + final String input = commandInput.peekString(); // Does not remove the string from the input! + try { + final UUID uuid = UUID.fromString(input); + commandInput.readString(); // Removes the string from the input. + return ArgumentParseResult.success(uuid); + } catch (final IllegalArgumentException e) { + return ArgumentParseResult.failure(new UUIDParseException(input, context)); } + } } // --8<-- [end:snippet] diff --git a/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftExceptionHandlerExample.java b/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftExceptionHandlerExample.java new file mode 100644 index 0000000..cb56726 --- /dev/null +++ b/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftExceptionHandlerExample.java @@ -0,0 +1,39 @@ +package org.incendo.cloud.snippet.minecraft; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler; + +import static net.kyori.adventure.text.Component.text; + +public class MinecraftExceptionHandlerExample { + + public void nativeExceptionHandler() { + // --8<-- [start:native] + MinecraftExceptionHandler.createNative() + .decorator(component -> text() + .append(text("[Example] ", NamedTextColor.DARK_RED)) + .append(component) + .build() + ); + // --8<-- [end:native] + } + + public void completeExample(final @NonNull CommandManager manager) { + // --8<-- [start:complete] + MinecraftExceptionHandler.createNative() + .defaultHandlers() + .decorator(component -> text() + .append(text("[Example] ", NamedTextColor.DARK_RED)) + .append(component) + .build() + ).registerTo(manager); + // --8<-- [end:complete] + } + + public static final class NativeSenderType implements Audience { + + } +} diff --git a/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftHelpExample.java b/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftHelpExample.java new file mode 100644 index 0000000..89a28f8 --- /dev/null +++ b/code/src/main/java/org/incendo/cloud/snippet/minecraft/MinecraftHelpExample.java @@ -0,0 +1,92 @@ +package org.incendo.cloud.snippet.minecraft; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.component.DefaultValue; +import org.incendo.cloud.help.result.CommandEntry; +import org.incendo.cloud.minecraft.extras.AudienceProvider; +import org.incendo.cloud.minecraft.extras.MinecraftHelp; +import org.incendo.cloud.suggestion.Suggestion; +import org.incendo.cloud.suggestion.SuggestionProvider; + +import java.util.stream.Collectors; + +import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser; + +public class MinecraftHelpExample { + + public @NonNull MinecraftHelp nativeHelp(final @NonNull CommandManager commandManager) { + // --8<-- [start:native] + MinecraftHelp help = MinecraftHelp.builder() + .commandManager(commandManager) + .audienceProvider(AudienceProvider.nativeAudience()) + .commandPrefix("/helpcommand") + .colors(MinecraftHelp.helpColors(NamedTextColor.GREEN, NamedTextColor.RED, + NamedTextColor.AQUA, NamedTextColor.BLACK, NamedTextColor.WHITE + )) + /* other settings... */ + .build(); + // --8<-- [end:native] + return help; + } + + public void nonNativeHelp(final @NonNull CommandManager commandManager) { + // --8<-- [start:non_native] + AudienceProvider audienceProvider = SenderType::audience; + MinecraftHelp help = MinecraftHelp.builder() + .commandManager(commandManager) + .audienceProvider(audienceProvider) + .commandPrefix("/helpcommand") + .colors(MinecraftHelp.helpColors(NamedTextColor.GREEN, NamedTextColor.RED, + NamedTextColor.AQUA, NamedTextColor.BLACK, NamedTextColor.WHITE + )) + /* other settings... */ + .build(); + // --8<-- [end:non_native] + } + + public void helpCommand(final @NonNull CommandManager commandManager) { + final MinecraftHelp help = this.nativeHelp(commandManager); + // --8<-- [start:help_command] + commandManager.command( + commandManager.commandBuilder("helpcommand") + .optional("query", greedyStringParser(), DefaultValue.constant("")) + .handler(context -> { + help.queryCommands(context.get("query"), context.sender()); + }) + ); + // --8<-- [end:help_command] + commandManager.command( + commandManager.commandBuilder("helpcommand") + // --8<-- [start:help_suggestions] + .optional( + "query", + greedyStringParser(), + DefaultValue.constant(""), + SuggestionProvider.blocking((ctx, in) -> commandManager.createHelpHandler() + .queryRootIndex(ctx.sender()) + .entries() + .stream() + .map(CommandEntry::syntax) + .map(Suggestion::simple) + .collect(Collectors.toList()) + ) + ) + // --8<-- [end:help_suggestions] + .handler(context -> { + help.queryCommands(context.get("query"), context.sender()); + }) + ); + } + + public static final class NativeSenderType implements Audience { + + } + + public static abstract class SenderType { + + public abstract @NonNull Audience audience(); + } +} diff --git a/docs/minecraft/minecraft-extras.md b/docs/minecraft/minecraft-extras.md index c4398ba..edab0e1 100644 --- a/docs/minecraft/minecraft-extras.md +++ b/docs/minecraft/minecraft-extras.md @@ -53,20 +53,8 @@ Cloud Minecraft Extras is available through [Maven Central](https://central.sona `MinecraftHelp` is an opinionated implementation of the [help system](../core/index.md#help-generation) using Adventure components for styling and click handling. - - -
- ![Minecraft Help Index](../assets/images/minecraft/mce_help_index.png) -
Index View
-
- -
- ![Minecraft Help Verbose](../assets/images/minecraft/mce_help_verbose.png) -
Verbose View
-
+{{ figure("../assets/images/minecraft/mce_help_index.png", "Index View") }} +{{ figure("../assets/images/minecraft/mce_help_verbose.png", "Verbose View") }} All interactions with the Minecraft help system will take place through a `MinecraftHelp` instance. @@ -98,58 +86,20 @@ or you may override the defaults by using a builder: === "Native Audience" - ```java - MinecraftHelp help = MinecraftHelp.builder() - .commandManager(commandManager) - .audienceProvider(AudienceProvider.nativeProvider()) - .commandPrefix("/helpcommand") - .colors(MinecraftHelp.helpColors(/* colors... */)) - /* other settings... */ - .build(); - ``` + {{ snippet("minecraft/MinecraftHelpExample.java", section = "native", title = "", indent = 4) }} === "Other" - ```java - MinecraftHelp help = MinecraftHelp.builder() - .commandManager(commandManager) - .audienceProvider(yourAudienceProvider) - .commandPrefix("/helpcommand") - .colors(MinecraftHelp.helpColors(/* colors... */)) - /* other settings... */ - .build(); - ``` + {{ snippet("minecraft/MinecraftHelpExample.java", section="non_native", title = "", indent = 4) }} You then want to invoke `MinecraftHelp.queryCommands(query, recipient)` in order to query the commands and display the results to the recipient. -```java title="Example Help Command" -commandManager.command( - commandManager.commandBuilder("helpcommand") - .optional("query", greedyStringParser(), DefaultValue.constant("")) - .handler(context -> { - help.queryCommands(context.get("query"), context.sender()); - }) -); -``` +{{ snippet("minecraft/MinecraftHelpExample.java", section = "help_command", title = "Example Help Command") }} You may choose to add suggestions to the query argument as well: -```java title="Query Suggestions" -.optional( - "query", - greedyStringParser(), - DefaultValue.constant(""), - SuggestionProvider.blocking((ctx, in) -> commandManager.createHelpHandler() - .queryRootIndex(ctx.sender()) - .entries() - .stream() - .map(CommandEntry::syntax) - .map(Suggestion::simple) - .collect(Collectors.toList()) - ) -) -``` +{{ snippet("minecraft/MinecraftHelpExample.java", section = "help_suggestions", title = "Query Suggestions") }} ## Minecraft Exception Handler @@ -178,28 +128,12 @@ If you want to register the default handlers for all types you may use `defaultH You may supply a decorator which will transform the created components. This is useful if you want to prefix all messages, or apply specific styling. -```java title="Example decorator" -MinecraftExceptionHandler.creativeNative() - .decorator(component -> text() - .append("[Example] ", NamedTextColor.DARK_RED) - .append(component) - .build() - ); -``` +{{ snippet("minecraft/MinecraftExceptionHandlerExample.java", section = "native", title = "Example decorator") }} When you're done configuring the builder you need to apply it to the command manager by using `registerTo(CommandManager)`. -```java title="Complete example" -MinecraftExceptionHandler.createNative() - .defaultHandlers() - .decorator(component -> text() - .append("[Example] ", NamedTextColor.DARK_RED) - .append(component) - .build() - ) - .registerTo(manager); -``` +{{ snippet("minecraft/MinecraftExceptionHandlerExample.java", section = "complete", title = "Complete example") }} ### Localization diff --git a/main.py b/main.py index ca3a46c..613a5d2 100644 --- a/main.py +++ b/main.py @@ -42,14 +42,22 @@ def javadoc(link: str, title: str = None) -> str: return '[`{title}`](<{link}> "Click to open the JavaDoc")'.format(link=link, title=title) @env.macro - def snippet(path: str, section: str = "snippet", title: str = None) -> str: + def snippet(path: str, section: str = "snippet", title: str = None, indent = 0) -> str: if title is None: title = path + if title: + title = 'title="{title}"'.format(title = title) + if section is not None: path = path + ":" + section - return """ -```java title="{title}" + return ''.join((' ' * indent) + line for line in """ +```java {title} --8<-- "{path}" ``` - """.format(path=path, title=title) + """.format(path=path, title=title).splitlines(True)) + + @env.macro + def figure(path: str, caption: str) -> str: + return ("
![{caption}]({path})
{caption}
" + .format(path = path, caption = caption))