Port doc printer to Kotlin, heavily improve

This commit is contained in:
Kenzie Togami 2019-06-05 23:26:57 -07:00
parent e69aedf059
commit d46cd78e14
No known key found for this signature in database
GPG Key ID: 5D200B325E157A81
4 changed files with 341 additions and 452 deletions

View File

@ -7,3 +7,5 @@ include 'worldedit-libs'
include "worldedit-$it"
}
include "worldedit-libs:core:ap"
include "worldedit-core:doctools"

View File

@ -0,0 +1,19 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.3.31"
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
repositories {
jcenter()
}
dependencies {
"implementation"(project(":worldedit-libs:core:ap"))
"implementation"(project(":worldedit-core"))
"implementation"(kotlin("stdlib-jdk8"))
}

View File

@ -0,0 +1,320 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.util
import com.google.common.base.Strings
import com.sk89q.worldedit.WorldEdit
import com.sk89q.worldedit.command.BiomeCommands
import com.sk89q.worldedit.command.ChunkCommands
import com.sk89q.worldedit.command.ClipboardCommands
import com.sk89q.worldedit.command.ExpandCommands
import com.sk89q.worldedit.command.GeneralCommands
import com.sk89q.worldedit.command.GenerationCommands
import com.sk89q.worldedit.command.HistoryCommands
import com.sk89q.worldedit.command.NavigationCommands
import com.sk89q.worldedit.command.RegionCommands
import com.sk89q.worldedit.command.ScriptingCommands
import com.sk89q.worldedit.command.SelectionCommands
import com.sk89q.worldedit.command.SnapshotUtilCommands
import com.sk89q.worldedit.command.ToolCommands
import com.sk89q.worldedit.command.ToolUtilCommands
import com.sk89q.worldedit.command.UtilityCommands
import com.sk89q.worldedit.command.util.PermissionCondition
import com.sk89q.worldedit.util.formatting.text.TextComponent
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer
import org.enginehub.piston.Command
import org.enginehub.piston.TextConfig
import org.enginehub.piston.part.SubCommandPart
import org.enginehub.piston.util.HelpGenerator
import java.nio.file.Files
import java.nio.file.Paths
import java.util.stream.Stream
import kotlin.streams.toList
import org.enginehub.piston.annotation.Command as CommandAnnotation
class DocumentationPrinter private constructor() {
private val serializer = PlainComponentSerializer({ "" }, TranslatableComponent::key)
private val commands = WorldEdit.getInstance().platformManager.platformCommandManager.commandManager.allCommands
.map { it.name to it }.toList().toMap()
private val cmdOutput = StringBuilder()
private val permsOutput = StringBuilder()
private suspend inline fun <reified T> SequenceScope<String>.yieldAllCommandsIn() {
for (method in T::class.java.methods) {
val cmdAnno = method.getDeclaredAnnotation(CommandAnnotation::class.java)
if (cmdAnno != null) {
yield(cmdAnno.name)
}
}
}
private fun writeAllCommands() {
writeHeader()
dumpSection("General Commands") {
yield("worldedit")
yieldAllCommandsIn<HistoryCommands>()
yieldAllCommandsIn<GeneralCommands>()
}
dumpSection("Navigation Commands") {
yieldAllCommandsIn<NavigationCommands>()
}
dumpSection("Selection Commands") {
yieldAllCommandsIn<SelectionCommands>()
yieldAllCommandsIn<ExpandCommands>()
}
dumpSection("Region Commands") {
yieldAllCommandsIn<RegionCommands>()
}
dumpSection("Generation Commands") {
yieldAllCommandsIn<GenerationCommands>()
}
dumpSection("Schematic and Clipboard Commands") {
yield("schematic")
yieldAllCommandsIn<ClipboardCommands>()
}
dumpSection("Tool Commands") {
yieldAllCommandsIn<ToolCommands>()
yieldAllCommandsIn<ToolUtilCommands>()
}
dumpSection("Super Pickaxe Commands") {
yield("superpickaxe")
}
dumpSection("Brush Commands") {
yield("brush")
}
dumpSection("Biome Commands") {
yieldAllCommandsIn<BiomeCommands>()
}
dumpSection("Chunk Commands") {
yieldAllCommandsIn<ChunkCommands>()
}
dumpSection("Snapshot Commands") {
yieldAllCommandsIn<SnapshotUtilCommands>()
yield("snapshot")
}
dumpSection("Scripting Commands") {
yieldAllCommandsIn<ScriptingCommands>()
}
dumpSection("Utility Commands") {
yieldAllCommandsIn<UtilityCommands>()
}
writeFooter()
}
private fun writeHeader() {
cmdOutput.appendln("""
========
Commands
========
.. contents::
:local:
.. tip::
Arguments enclosed in ``[ ]`` are optional, those enclosed in ``< >`` are required.
""".trim())
permsOutput.appendln("""
===========
Permissions
===========
By default, no one can use WorldEdit. In order for yourself, moderators, and players to use WorldEdit, you must provide the proper permissions. One way is to provide op to moderators and administrators (unless disabled in the :doc:`configuration <config>`), but providing the permission nodes on this page (through a permissions plugin) is the more flexible.
You can give the ``worldedit.*`` permission to give yourself and other administrators full access to WorldEdit.
Commands
=========
See the :doc:`commands` page for an explanation of some of these commands.
.. csv-table::
:header: Command, Permission
:widths: 15, 25
""".trim())
permsOutput.appendln()
}
private fun writeFooter() {
permsOutput.appendln()
permsOutput.append("""
Other Permissions
==================
.. csv-table::
:header: Permission, Explanation
:widths: 15, 25
``worldedit.navigation.jumpto.tool``,"Allows usage of the navigation wand's ``/jumpto`` shortcut (left click)."
``worldedit.navigation.thru.tool``,"Allows usage of the navigation wand's ``/thru`` shortcut (right click)."
``worldedit.anyblock``,"Allows usage of blocks in the :doc:`disallowed-blocks <config>` config option."
``worldedit.limit.unrestricted``,"Allows setting the limit via the ``//limit`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`, as well as other limit bypasses."
``worldedit.timeout.unrestricted``,"Allows setting the calculation timeout via the ``//timeout`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`."
``worldedit.inventory.unrestricted``,"Override the ``use-inventory`` option if enabled in the :doc:`configuration <config>`."
``worldedit.override.bedrock``,"Allows breaking of bedrock with the super-pickaxe tool."
``worldedit.override.data-cycler``,"Allows cycling non-whitelisted blocks with the data cycler tool."
``worldedit.setnbt``,"Allows setting `extra data <https://minecraft.gamepedia.com/Block_entity>`_ on blocks (such as signs, chests, etc)."
``worldedit.report.pastebin``,"Allows uploading report files to pastebin automatically for the ``/worldedit report`` :doc:`command <commands>`."
""".trim())
}
private fun dumpSection(title: String, addCommandNames: suspend SequenceScope<String>.() -> Unit) {
cmdOutput.append("\n").append(title).append("\n").append(Strings.repeat("~", title.length)).append("\n")
val prefix = TextConfig.getCommandPrefix()
val commands = sequence(addCommandNames).map { this.commands.getValue(it) }.toList()
cmdsToPerms(commands, prefix)
for (command in commands) {
writeCommandBlock(command, prefix, Stream.empty())
command.parts.stream().filter { p -> p is SubCommandPart }
.flatMap { p -> (p as SubCommandPart).commands.stream() }
.forEach { sc ->
writeCommandBlock(sc, prefix + command.name + " ", Stream.of(command))
}
}
}
private fun cmdsToPerms(cmds: List<Command>, prefix: String) {
cmds.forEach { c ->
permsOutput.append(" ").append(cmdToPerm(prefix, c)).append("\n")
c.parts.filter { p -> p is SubCommandPart }
.map { p -> p as SubCommandPart }
.forEach { scp ->
cmdsToPerms(scp.commands.sortedBy { it.name }, prefix + c.name + " ")
}
}
}
private fun cmdToPerm(prefix: String, c: Command): String {
val cond = c.condition
val permissions = when {
cond is PermissionCondition && cond.permissions.isNotEmpty() ->
cond.permissions.joinToString(", ") { "``$it``" }
else -> ""
}
return "``$prefix${c.name}``,\"$permissions\""
}
private fun writeCommandBlock(command: Command, prefix: String, parents: Stream<Command>) {
val name = prefix + command.name
val entries = commandTableEntries(command, parents)
cmdOutput.appendln(".. raw:: html")
cmdOutput.appendln()
cmdOutput.appendln(""" <span id="command-${linkSafe(name)}"></span>""")
cmdOutput.appendln()
cmdOutput.append(".. topic:: ``$name``")
if (!command.aliases.isEmpty()) {
command.aliases.joinTo(cmdOutput, ", ",
prefix = " (or ",
postfix = ")",
transform = { "``$prefix$it``" })
}
cmdOutput.appendln().appendln()
cmdOutput.appendln("""
| .. csv-table::
| :widths: 8, 15
""".trimMargin())
cmdOutput.appendln()
for ((k, v) in entries) {
val rstSafe = v.replace("\"", "\\\"").replace("\n", "\n" + " ".repeat(2))
cmdOutput.append(" ".repeat(2))
.append(k)
.append(",")
.append('"')
.append(rstSafe)
.append('"').appendln()
}
cmdOutput.appendln()
}
private fun linkSafe(text: String) = text.replace(" ", "-")
private fun commandTableEntries(command: Command, parents: Stream<Command>): Map<String, String> {
return sequence {
val desc = command.description.run {
when {
command.footer.isPresent -> append(
TextComponent.builder("\n\n").append(command.footer.get())
)
else -> this
}
}
yield("**Description**" to serializer.serialize(desc))
val cond = command.condition
if (cond is PermissionCondition && cond.permissions.isNotEmpty()) {
val perms = cond.permissions.joinToString(", ") { "``$it``" }
yield("**Permissions**" to perms)
}
val usage = serializer.serialize(HelpGenerator.create(Stream.concat(parents, Stream.of(command)).toList()).usage)
yield("**Usage**" to "``$usage``")
// Part descriptions
command.parts.filterNot { it is SubCommandPart }
.forEach {
val title = "\u2001\u2001``" + serializer.serialize(it.textRepresentation) + "``"
yield(title to serializer.serialize(it.description))
}
}.toMap()
}
companion object {
/**
* Generates documentation.
*/
@JvmStatic
fun main(args: Array<String>) {
val printer = DocumentationPrinter()
printer.writeAllCommands()
writeOutput("commands.rst", printer.cmdOutput.toString())
writeOutput("permissions.rst", printer.permsOutput.toString())
WorldEdit.getInstance().sessionManager.unload()
}
private fun writeOutput(file: String, output: String) {
Files.newBufferedWriter(Paths.get(file)).use {
it.write(output)
}
}
}
}

View File

@ -1,452 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.util;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.ApplyBrushCommands;
import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BiomeCommandsRegistration;
import com.sk89q.worldedit.command.BrushCommands;
import com.sk89q.worldedit.command.BrushCommandsRegistration;
import com.sk89q.worldedit.command.ChunkCommands;
import com.sk89q.worldedit.command.ChunkCommandsRegistration;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.ClipboardCommandsRegistration;
import com.sk89q.worldedit.command.ExpandCommands;
import com.sk89q.worldedit.command.GeneralCommands;
import com.sk89q.worldedit.command.GeneralCommandsRegistration;
import com.sk89q.worldedit.command.GenerationCommands;
import com.sk89q.worldedit.command.GenerationCommandsRegistration;
import com.sk89q.worldedit.command.HistoryCommands;
import com.sk89q.worldedit.command.HistoryCommandsRegistration;
import com.sk89q.worldedit.command.NavigationCommands;
import com.sk89q.worldedit.command.NavigationCommandsRegistration;
import com.sk89q.worldedit.command.PaintBrushCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.RegionCommandsRegistration;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.SchematicCommandsRegistration;
import com.sk89q.worldedit.command.ScriptingCommands;
import com.sk89q.worldedit.command.ScriptingCommandsRegistration;
import com.sk89q.worldedit.command.SelectionCommands;
import com.sk89q.worldedit.command.SelectionCommandsRegistration;
import com.sk89q.worldedit.command.SnapshotCommands;
import com.sk89q.worldedit.command.SnapshotCommandsRegistration;
import com.sk89q.worldedit.command.SnapshotUtilCommands;
import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration;
import com.sk89q.worldedit.command.SuperPickaxeCommands;
import com.sk89q.worldedit.command.SuperPickaxeCommandsRegistration;
import com.sk89q.worldedit.command.ToolCommands;
import com.sk89q.worldedit.command.ToolCommandsRegistration;
import com.sk89q.worldedit.command.ToolUtilCommands;
import com.sk89q.worldedit.command.ToolUtilCommandsRegistration;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.command.UtilityCommandsRegistration;
import com.sk89q.worldedit.command.WorldEditCommands;
import com.sk89q.worldedit.command.WorldEditCommandsRegistration;
import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.formatting.text.serializer.ComponentSerializer;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.TextConfig;
import org.enginehub.piston.gen.CommandRegistration;
import org.enginehub.piston.impl.CommandManagerImpl;
import org.enginehub.piston.impl.CommandManagerServiceImpl;
import org.enginehub.piston.part.SubCommandPart;
import org.enginehub.piston.util.HelpGenerator;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class DocumentationPrinter {
/**
* Generates documentation.
*
* @param args arguments
*/
public static void main(String[] args) throws IOException {
final DocumentationPrinter printer = new DocumentationPrinter();
printer.writeAllCommands();
writeOutput("commands.rst", printer.cmdOutput.toString());
writeOutput("permissions.rst", printer.permsOutput.toString());
WorldEdit.getInstance().getSessionManager().unload();
}
private static void writeOutput(String file, String output) throws IOException {
File outfile = new File(file);
Files.write(output, outfile, StandardCharsets.UTF_8);
}
private final ComponentSerializer<Component, TextComponent, String> serializer
= new PlainComponentSerializer(kb -> "", TranslatableComponent::key);
private final CommandRegistrationHandler registration;
private final CommandManagerServiceImpl commandManagerService;
private final WorldEdit worldEdit = WorldEdit.getInstance();
private StringBuilder cmdOutput;
private StringBuilder permsOutput;
private Field mgrCmdField;
private DocumentationPrinter() {
this.cmdOutput = new StringBuilder();
this.permsOutput = new StringBuilder();
this.registration = new CommandRegistrationHandler(ImmutableList.of());
this.commandManagerService = new CommandManagerServiceImpl();
try {
Field field = CommandManagerImpl.class.getDeclaredField("commands");
field.setAccessible(true);
this.mgrCmdField = field;
} catch (NoSuchFieldException ignored) {
}
}
private <CI> void registerSubCommands(CommandManager parent, String name, List<String> aliases, String desc,
CommandRegistration<CI> registration, CI instance) {
registerSubCommands(parent, name, aliases, desc, registration, instance, m -> {});
}
private <CI> void registerSubCommands(CommandManager parent, String name, List<String> aliases, String desc,
CommandRegistration<CI> registration, CI instance,
Consumer<CommandManager> additionalConfig) {
parent.register(name, cmd -> {
cmd.aliases(aliases);
cmd.description(TextComponent.of(desc));
cmd.action(Command.Action.NULL_ACTION);
CommandManager manager = createManager();
this.registration.register(
manager,
registration,
instance
);
additionalConfig.accept(manager);
cmd.addPart(SubCommandPart.builder(TranslatableComponent.of("worldedit.argument.action"),
TextComponent.of("Sub-command to run."))
.withCommands(manager.getAllCommands().collect(Collectors.toList()))
.required()
.build());
});
}
private void writeAllCommands() {
writeHeader();
CommandManager manager;
manager = createManager();
registerSubCommands(
manager,
"worldedit",
ImmutableList.of("we"),
"WorldEdit commands",
WorldEditCommandsRegistration.builder(),
new WorldEditCommands(worldEdit)
);
this.registration.register(
manager,
HistoryCommandsRegistration.builder(),
new HistoryCommands(worldEdit)
);
this.registration.register(
manager,
GeneralCommandsRegistration.builder(),
new GeneralCommands(worldEdit)
);
dumpSection("General Commands", manager);
manager = createManager();
this.registration.register(
manager,
NavigationCommandsRegistration.builder(),
new NavigationCommands(worldEdit)
);
dumpSection("Navigation Commands", manager);
manager = createManager();
this.registration.register(
manager,
SelectionCommandsRegistration.builder(),
new SelectionCommands(worldEdit)
);
ExpandCommands.register(registration, manager, commandManagerService);
dumpSection("Selection Commands", manager);
manager = createManager();
this.registration.register(
manager,
RegionCommandsRegistration.builder(),
new RegionCommands()
);
dumpSection("Region Commands", manager);
manager = createManager();
this.registration.register(
manager,
GenerationCommandsRegistration.builder(),
new GenerationCommands(worldEdit)
);
dumpSection("Generation Commands", manager);
manager = createManager();
registerSubCommands(
manager,
"schematic",
ImmutableList.of("schem", "/schematic", "/schem"),
"Schematic commands for saving/loading areas",
SchematicCommandsRegistration.builder(),
new SchematicCommands(worldEdit)
);
this.registration.register(
manager,
ClipboardCommandsRegistration.builder(),
new ClipboardCommands()
);
dumpSection("Schematic and Clipboard Commands", manager);
manager = createManager();
this.registration.register(
manager,
ToolCommandsRegistration.builder(),
new ToolCommands(worldEdit)
);
this.registration.register(
manager,
ToolUtilCommandsRegistration.builder(),
new ToolUtilCommands(worldEdit)
);
dumpSection("Tool Commands", manager);
manager = createManager();
registerSubCommands(
manager,
"superpickaxe",
ImmutableList.of("pickaxe", "sp"),
"Super-pickaxe commands",
SuperPickaxeCommandsRegistration.builder(),
new SuperPickaxeCommands(worldEdit)
);
dumpSection("Super Pickaxe Commands", manager);
manager = createManager();
registerSubCommands(
manager,
"brush",
ImmutableList.of("br", "/brush", "/br"),
"Brushing commands",
BrushCommandsRegistration.builder(),
new BrushCommands(worldEdit),
mgr -> {
PaintBrushCommands.register(commandManagerService, mgr, registration);
ApplyBrushCommands.register(commandManagerService, mgr, registration);
}
);
dumpSection("Brush Commands", manager);
manager = createManager();
this.registration.register(
manager,
BiomeCommandsRegistration.builder(),
new BiomeCommands()
);
dumpSection("Biome Commands", manager);
manager = createManager();
this.registration.register(
manager,
ChunkCommandsRegistration.builder(),
new ChunkCommands(worldEdit)
);
dumpSection("Chunk Commands", manager);
manager = createManager();
this.registration.register(
manager,
SnapshotUtilCommandsRegistration.builder(),
new SnapshotUtilCommands(worldEdit)
);
registerSubCommands(
manager,
"snapshot",
ImmutableList.of("snap"),
"Snapshot commands for restoring backups",
SnapshotCommandsRegistration.builder(),
new SnapshotCommands(worldEdit)
);
dumpSection("Snapshot Commands", manager);
manager = createManager();
this.registration.register(
manager,
ScriptingCommandsRegistration.builder(),
new ScriptingCommands(worldEdit)
);
dumpSection("Scripting Commands", manager);
manager = createManager();
this.registration.register(
manager,
UtilityCommandsRegistration.builder(),
new UtilityCommands(worldEdit)
);
dumpSection("Utility Commands", manager);
writeFooter();
}
private void writeHeader() {
cmdOutput.append(
"========\n" +
"Commands\n" +
"========\n" +
"\n" +
".. contents::\n" +
" :local:\n" +
"\n" +
".. tip::\n" +
"\n" +
" Arguments enclosed in ``[ ]`` are optional, those enclosed in ``< >`` are required.\n\n");
permsOutput.append("===========\n" +
"Permissions\n" +
"===========\n" +
"\n" +
"By default, no one can use WorldEdit. In order for yourself, moderators, and players to use WorldEdit, you must provide the proper permissions. One way is to provide op to moderators and administrators (unless disabled in the :doc:`configuration <config>`), but providing the permission nodes on this page (through a permissions plugin) is the more flexible.\n" +
"\n" +
"You can give the ``worldedit.*`` permission to give yourself and other administrators full access to WorldEdit.\n" +
"\n" +
"Commands\n" +
"=========\n" +
"\n" +
"See the :doc:`commands` page for an explanation of some of these commands.\n" +
"\n" +
".. csv-table::\n" +
" :header: Command, Permission\n" +
" :widths: 15, 25\n\n");
}
private void writeFooter() {
permsOutput.append("\nOther Permissions\n" +
"==================\n" +
"\n" +
".. csv-table::\n" +
" :header: Permission, Explanation\n" +
" :widths: 15, 25\n" +
"\n" +
" worldedit.navigation.jumpto.tool,\"Allows usage of the navigation wand's ``/jumpto`` shortcut (left click).\"\n" +
" worldedit.navigation.thru.tool,\"Allows usage of the navigation wand's ``/thru`` shortcut (right click).\"\n" +
" worldedit.anyblock,\"Allows usage of blocks in the :doc:`disallowed-blocks <config>` config option.\"\n" +
" worldedit.limit.unrestricted,\"Allows setting the limit via the ``//limit`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`, as well as other limit bypasses.\"\n" +
" worldedit.timeout.unrestricted,\"Allows setting the calculation timeout via the ``//timeout`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`.\"\n" +
" worldedit.inventory.unrestricted,\"Override the ``use-inventory`` option if enabled in the :doc:`configuration <config>`.\"\n" +
" worldedit.override.bedrock,\"Allows breaking of bedrock with the super-pickaxe tool.\"\n" +
" worldedit.override.data-cycler,\"Allows cycling non-whitelisted blocks with the data cycler tool.\"\n" +
" worldedit.setnbt,\"Allows setting `extra data <https://minecraft.gamepedia.com/Block_entity>`_ on blocks (such as signs, chests, etc).\"\n" +
" worldedit.report.pastebin,\"Allows uploading report files to pastebin automatically for the ``/worldedit report`` :doc:`command <commands>`.\"");
}
private CommandManager createManager() {
final CommandManager commandManager = commandManagerService.newCommandManager();
if (mgrCmdField != null && commandManager instanceof CommandManagerImpl) {
try {
mgrCmdField.set(commandManager, new LinkedHashMap<>());
} catch (IllegalAccessException ignored) {
}
}
return commandManager;
}
private void dumpSection(String title, CommandManager manager) {
cmdOutput.append("\n").append(title).append("\n").append(Strings.repeat("~", title.length())).append("\n");
String prefix = TextConfig.getCommandPrefix();
// permsOutput.append("\n------------\n\n");
cmdsToPerms(manager.getAllCommands(), prefix);
boolean first = true;
for (Command command : manager.getAllCommands().collect(Collectors.toList())) {
if (!first) cmdOutput.append("\n------------\n\n");
first = false;
writeCommandBlock(command, prefix, Stream.empty());
command.getParts().stream().filter(p -> p instanceof SubCommandPart)
.flatMap(p -> ((SubCommandPart) p).getCommands().stream())
.forEach(sc -> {
cmdOutput.append("\n------------\n\n");
writeCommandBlock(sc, prefix + command.getName() + " ", Stream.of(command));
});
}
}
private void cmdsToPerms(Stream<Command> cmds, String prefix) {
cmds.forEach(c -> {
permsOutput.append(" ").append(cmdToPerm(prefix, c)).append("\n");
c.getParts().stream().filter(p -> p instanceof SubCommandPart).map(p -> (SubCommandPart) p)
.forEach(scp -> cmdsToPerms(scp.getCommands().stream(), prefix + c.getName() + " "));
});
}
private String cmdToPerm(String prefix, Command c) {
return prefix + c.getName() + ",\"" + (c.getCondition() instanceof PermissionCondition
? String.join(", ", ((PermissionCondition) c.getCondition()).getPermissions()) : "") + "\"";
}
private void writeCommandBlock(Command command, String prefix, Stream<Command> parents) {
String name = prefix + command.getName();
String desc = serializer.serialize(command.getDescription());
cmdOutput.append(".. csv-table::\n :widths: 8, 15\n\n");
cmdOutput.append(" ").append(name).append(",");
if (!command.getAliases().isEmpty()) {
cmdOutput.append("\"(or ").append(String.join(", ",
command.getAliases().stream().map(a -> prefix + a).collect(Collectors.toSet())))
.append(")\"");
}
cmdOutput.append("\n");
cmdOutput.append(" Description,\"").append(desc).append("\"\n");
if (command.getCondition() instanceof PermissionCondition) {
cmdOutput.append(" Permissions,\"").append(String.join(", ", ((PermissionCondition) command.getCondition()).getPermissions())).append("\"\n");
}
cmdOutput.append(" Usage,\"").append(serializer.serialize(
HelpGenerator.create(Stream.concat(parents, Stream.of(command)).collect(Collectors.toList())).getUsage())).append("\"\n");
command.getParts().stream().filter(part -> !(part instanceof SubCommandPart)).forEach(part ->
cmdOutput.append(" \u2001\u2001").append(serializer.serialize(part.getTextRepresentation())).append(",\"")
.append(serializer.serialize(part.getDescription())).append("\"\n"));
if (command.getFooter().isPresent()) {
cmdOutput.append(" ,\"").append(serializer.serialize(command.getFooter().get()).replace("\n", " ")).append("\"\n");
}
}
}