mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -04:00
cli: enum parser
This commit is contained in:
parent
3ec82ad51f
commit
6e8fdb78fe
@ -15,7 +15,9 @@ package de.bixilon.minosoft.commands.nodes
|
||||
|
||||
import de.bixilon.minosoft.commands.parser.ArgumentParser
|
||||
import de.bixilon.minosoft.commands.stack.CommandExecutor
|
||||
import de.bixilon.minosoft.commands.stack.CommandStack
|
||||
import de.bixilon.minosoft.commands.suggestion.types.SuggestionType
|
||||
import de.bixilon.minosoft.commands.util.CommandReader
|
||||
|
||||
class ArgumentNode : ExecutableNode {
|
||||
private val parser: ArgumentParser<*>
|
||||
@ -40,4 +42,11 @@ class ArgumentNode : ExecutableNode {
|
||||
super.addChild(node)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun execute(reader: CommandReader, stack: CommandStack) {
|
||||
reader.skipWhitespaces()
|
||||
val parsed = parser.parse(reader)
|
||||
stack.push(name, parsed)
|
||||
super.execute(reader, stack)
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ abstract class ExecutableNode(
|
||||
redirect: CommandNode? = null,
|
||||
) : CommandNode(executable, redirect) {
|
||||
|
||||
private fun execute(stack: CommandStack) {
|
||||
protected fun execute(stack: CommandStack) {
|
||||
try {
|
||||
executor?.invoke(stack)
|
||||
} catch (exception: Throwable) {
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.commands.parser.minosoft.enums
|
||||
|
||||
import de.bixilon.minosoft.commands.errors.parser.ParserError
|
||||
import de.bixilon.minosoft.commands.util.CommandReader
|
||||
import de.bixilon.minosoft.commands.util.ReadResult
|
||||
|
||||
class EnumParseError(
|
||||
reader: CommandReader,
|
||||
result: ReadResult<*>,
|
||||
) : ParserError(reader, result)
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.commands.parser.minosoft.enums
|
||||
|
||||
import de.bixilon.kutil.enums.ValuesEnum
|
||||
import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
|
||||
import de.bixilon.minosoft.commands.parser.ArgumentParser
|
||||
import de.bixilon.minosoft.commands.parser.factory.ArgumentParserFactory
|
||||
import de.bixilon.minosoft.commands.suggestion.ArraySuggestion
|
||||
import de.bixilon.minosoft.commands.util.CommandReader
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
|
||||
class EnumParser<E : Enum<*>>(
|
||||
val values: ValuesEnum<E>,
|
||||
) : ArgumentParser<E> {
|
||||
override val examples: List<E> = values.VALUES.toList()
|
||||
private val suggestion = ArraySuggestion(examples)
|
||||
override val placeholder = ChatComponent.of("<enum>")
|
||||
|
||||
override fun parse(reader: CommandReader): E {
|
||||
reader.readResult { reader.readEnum() }.let { return it.result ?: throw EnumParseError(reader, it) }
|
||||
}
|
||||
|
||||
fun CommandReader.readEnum(): E? {
|
||||
return values.getOrNull(readString()?.lowercase()) // ToDo: Allow ordinals
|
||||
}
|
||||
|
||||
override fun getSuggestions(reader: CommandReader): List<E> {
|
||||
val text = reader.readResult { reader.readString() }
|
||||
if (text.result == null) {
|
||||
return examples
|
||||
}
|
||||
return suggestion.suggest(text.result) ?: throw NoSuggestionError(reader, text)
|
||||
}
|
||||
|
||||
companion object : ArgumentParserFactory<EnumParser<*>> {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minosoft:enum".toResourceLocation()
|
||||
|
||||
override fun build(connection: PlayConnection?) = TODO("Can not construct enum parser yet!")
|
||||
|
||||
override fun read(buffer: PlayInByteBuffer) = TODO("Can not construct enum parser yet!")
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ class CommandStack {
|
||||
stack.removeAll { index++ >= size }
|
||||
}
|
||||
|
||||
fun push(name: String, data: Any) {
|
||||
fun push(name: String, data: Any?) {
|
||||
stack.add(StackEntry(name, data))
|
||||
}
|
||||
|
||||
|
@ -13,19 +13,35 @@
|
||||
|
||||
package de.bixilon.minosoft.terminal.commands
|
||||
|
||||
import de.bixilon.kutil.enums.EnumUtil
|
||||
import de.bixilon.kutil.enums.ValuesEnum
|
||||
import de.bixilon.minosoft.commands.nodes.ArgumentNode
|
||||
import de.bixilon.minosoft.commands.nodes.LiteralNode
|
||||
import de.bixilon.minosoft.commands.parser.minosoft.enums.EnumParser
|
||||
|
||||
object HelpCommand : Command {
|
||||
|
||||
override fun build(): LiteralNode {
|
||||
return LiteralNode("help", setOf("?"), onlyDirectExecution = false, executor = {
|
||||
printHelp(it["general"])
|
||||
})
|
||||
.addChild(LiteralNode("general", executable = true))
|
||||
return LiteralNode("help", setOf("?"), executor = { printHelp() })
|
||||
.addChild(ArgumentNode("subcommand", parser = EnumParser(HelpCommands), executor = { printHelp(it["subcommand"]!!) }))
|
||||
}
|
||||
|
||||
fun printHelp(subcommand: String?) {
|
||||
fun printHelp() {
|
||||
println("-------------- Minosoft help --------------")
|
||||
}
|
||||
|
||||
fun printHelp(subcommand: HelpCommands) {
|
||||
println("-------------- Minosoft help --------------")
|
||||
println("Subcommand: $subcommand")
|
||||
}
|
||||
|
||||
enum class HelpCommands {
|
||||
GENERAL,
|
||||
;
|
||||
|
||||
companion object : ValuesEnum<HelpCommands> {
|
||||
override val VALUES: Array<HelpCommands> = values()
|
||||
override val NAME_MAP: Map<String, HelpCommands> = EnumUtil.getEnumValues(VALUES)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,11 @@ package de.bixilon.minosoft.commands.parser.brigadier.bool
|
||||
|
||||
import de.bixilon.minosoft.commands.errors.suggestion.NoSuggestionError
|
||||
import de.bixilon.minosoft.commands.util.CommandReader
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
internal class BooleanParserTest {
|
||||
|
||||
@ -35,19 +38,19 @@ internal class BooleanParserTest {
|
||||
@Test
|
||||
fun testCaseSensitivity() {
|
||||
val reader = CommandReader("True")
|
||||
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
|
||||
assertThrows<BooleanParseError> { (BooleanParser.parse(reader)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEmpty() {
|
||||
val reader = CommandReader("")
|
||||
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
|
||||
assertThrows<BooleanParseError> { (BooleanParser.parse(reader)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTrash() {
|
||||
val reader = CommandReader("this is trash")
|
||||
assertThrows(BooleanParseError::class.java) { (BooleanParser.parse(reader)) }
|
||||
assertThrows<BooleanParseError> { (BooleanParser.parse(reader)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -83,6 +86,6 @@ internal class BooleanParserTest {
|
||||
@Test
|
||||
fun testNoSuggestion() {
|
||||
val reader = CommandReader("a")
|
||||
assertThrows(NoSuggestionError::class.java) { BooleanParser.getSuggestions(reader).size }
|
||||
assertThrows<NoSuggestionError> { BooleanParser.getSuggestions(reader).size }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2022 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.commands.parser.minosoft.enums
|
||||
|
||||
import de.bixilon.kutil.enums.EnumUtil
|
||||
import de.bixilon.kutil.enums.ValuesEnum
|
||||
import de.bixilon.minosoft.commands.util.CommandReader
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class EnumParserTest {
|
||||
|
||||
|
||||
@Test
|
||||
fun checkFirst() {
|
||||
val reader = CommandReader("FIRST")
|
||||
val parser = EnumParser(Tests)
|
||||
assertEquals(parser.parse(reader), Tests.FIRST)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkSecond() {
|
||||
val reader = CommandReader("SECOND")
|
||||
val parser = EnumParser(Tests)
|
||||
assertEquals(parser.parse(reader), Tests.SECOND)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkCaseInsensitivity() {
|
||||
val reader = CommandReader("sEcOnD")
|
||||
val parser = EnumParser(Tests)
|
||||
assertEquals(parser.parse(reader), Tests.SECOND)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkInvalid() {
|
||||
val reader = CommandReader("invalid")
|
||||
val parser = EnumParser(Tests)
|
||||
assertThrows<EnumParseError> { parser.parse(reader) }
|
||||
}
|
||||
|
||||
enum class Tests {
|
||||
FIRST,
|
||||
SECOND,
|
||||
;
|
||||
|
||||
companion object : ValuesEnum<Tests> {
|
||||
override val VALUES: Array<Tests> = values()
|
||||
override val NAME_MAP: Map<String, Tests> = EnumUtil.getEnumValues(VALUES)
|
||||
}
|
||||
}
|
||||
}
|
@ -15,8 +15,8 @@ package de.bixilon.minosoft.commands.util
|
||||
|
||||
import de.bixilon.minosoft.commands.errors.reader.OutOfBoundsError
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
|
||||
internal class CommandReaderTest {
|
||||
@Test
|
||||
@ -52,7 +52,7 @@ internal class CommandReaderTest {
|
||||
assertEquals(reader.read(), 'e'.code)
|
||||
assertEquals(reader.read(), 's'.code)
|
||||
assertEquals(reader.read(), 't'.code)
|
||||
assertThrows(OutOfBoundsError::class.java) { reader.unsafeRead() }
|
||||
assertThrows<OutOfBoundsError> { reader.unsafeRead() }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user