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.mockk.every
|
||||
import io.mockk.mockk
|
||||
import net.trivernis.chunkmaster.lib.LanguageManager
|
||||
import net.trivernis.chunkmaster.Chunkmaster
|
||||
import org.bukkit.configuration.file.FileConfiguration
|
||||
import org.junit.Test
|
||||
|
Loading…
Reference in New Issue