Add custom args parser to allow spaces in arguments
Fixes #96 where worlds with spaces could not be used with chunkmaster. Signed-off-by: trivernis <trivernis@protonmail.com>pull/109/head
parent
f15dc646f6
commit
aad4143e8a
@ -0,0 +1,77 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Better argument parser for command arguments
|
||||||
|
*/
|
||||||
|
class ArgParser {
|
||||||
|
private var input = ""
|
||||||
|
private var position = 0
|
||||||
|
private var currentChar = ' '
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses arguments from a string and respects quotes
|
||||||
|
*/
|
||||||
|
fun parseArguments(arguments: String): List<String> {
|
||||||
|
if (arguments.isEmpty()) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
input = arguments
|
||||||
|
position = 0
|
||||||
|
currentChar = input[position]
|
||||||
|
val args = ArrayList<String>()
|
||||||
|
var arg = ""
|
||||||
|
|
||||||
|
while (!endReached()) {
|
||||||
|
nextCharacter()
|
||||||
|
|
||||||
|
if (currentChar.isWhitespace()) {
|
||||||
|
if (arg.isNotBlank()) {
|
||||||
|
args.add(arg)
|
||||||
|
}
|
||||||
|
arg = ""
|
||||||
|
} else if (currentChar == '"') {
|
||||||
|
if (arg.isNotBlank()) {
|
||||||
|
args.add(arg)
|
||||||
|
}
|
||||||
|
arg = parseString()
|
||||||
|
if (arg.isNotBlank()) {
|
||||||
|
args.add(arg)
|
||||||
|
}
|
||||||
|
arg = ""
|
||||||
|
} else {
|
||||||
|
arg += currentChar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arg.isNotBlank()) {
|
||||||
|
args.add(arg)
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an enquoted string
|
||||||
|
*/
|
||||||
|
private fun parseString(): String {
|
||||||
|
var output = ""
|
||||||
|
|
||||||
|
while (!endReached()) {
|
||||||
|
nextCharacter()
|
||||||
|
if (currentChar == '"') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
output += currentChar
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun nextCharacter() {
|
||||||
|
if (!endReached()) {
|
||||||
|
currentChar = input[position++]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endReached(): Boolean {
|
||||||
|
return position >= input.length
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib
|
||||||
|
|
||||||
|
import io.kotest.matchers.shouldBe
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ArgParserTest {
|
||||||
|
var argParser = ArgParser()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses arguments`() {
|
||||||
|
argParser.parseArguments("first second third forth").shouldBe(listOf("first", "second", "third", "forth"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses quoted arguments as one argument`() {
|
||||||
|
argParser.parseArguments("first \"second with space\" third").shouldBe(listOf("first", "second with space", "third"))
|
||||||
|
argParser.parseArguments("\"first\" \"second\" \"third\"").shouldBe(listOf("first", "second", "third"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses single arguments`() {
|
||||||
|
argParser.parseArguments("one").shouldBe(listOf("one"))
|
||||||
|
argParser.parseArguments("\"one\"").shouldBe(listOf("one"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses no arguments`() {
|
||||||
|
argParser.parseArguments("").shouldBe(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses just whitespace as no arguments`() {
|
||||||
|
argParser.parseArguments(" ").shouldBe(emptyList())
|
||||||
|
argParser.parseArguments("\t\t").shouldBe(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it parses arguments with weird whitespace`() {
|
||||||
|
argParser.parseArguments(" first second \t third \n forth ").shouldBe(listOf("first", "second", "third", "forth"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `it deals predictable with malformed input`() {
|
||||||
|
argParser.parseArguments("first \"second third fourth").shouldBe(listOf("first", "second third fourth"))
|
||||||
|
argParser.parseArguments("\"first second \"third\" fourth").shouldBe(listOf("first second ", "third", " fourth"))
|
||||||
|
argParser.parseArguments("first second third fourth\"").shouldBe(listOf("first", "second", "third", "fourth"))
|
||||||
|
argParser.parseArguments("\"").shouldBe(emptyList())
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package net.trivernis.chunkmaster
|
package net.trivernis.chunkmaster.lib
|
||||||
import io.kotest.matchers.string.shouldNotBeEmpty
|
import io.kotest.matchers.string.shouldNotBeEmpty
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import net.trivernis.chunkmaster.lib.LanguageManager
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
import org.bukkit.configuration.file.FileConfiguration
|
import org.bukkit.configuration.file.FileConfiguration
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
Loading…
Reference in New Issue