4
0
Fork 0
mirror of https://github.com/Anvilcraft/modpacktools synced 2024-11-17 15:31:10 +01:00

command loader will now use kotlin reflection instead of java reflection whenever possible

modlist will use paragraphs for description instead of just line breaks
modlist will not add image to HTML if the dependency has no image
moved help messages for missing config/modpackjson out of CommandLoader.kt and replaced with exceptions
fix formatting and improve CSS for modlist
This commit is contained in:
LordMZTE 2020-07-28 13:18:56 +02:00
parent b3cd41f215
commit 3fa8924c35
4 changed files with 54 additions and 31 deletions

View file

@ -32,20 +32,31 @@ private val httpClient0 = lazy {
.build()
}
val HTTP_CLIENT by httpClient0
private val helpMessage by lazy {
val sb = StringBuilder().append("Commands:\n\n")
LOADER.commands.entries.stream()
//Sort by name
.sorted(Comparator.comparing {e: MutableMap.MutableEntry<String, ICommand> -> e.key})
.forEach {sb.append("${it.key}: ${it.value.helpMessage}\n")}
sb.toString()
}
fun main(args: Array<out String>) {
if(args.isEmpty()) {
printHelp()
println(helpMessage)
} else {
try {
val ret = LOADER.runCommand(args[0], args)
if(ret.hasRet())
println(ret.ret)
} catch(e: NoSuchElementException) {
println(e.message)
printHelp()
println("Command ${args[0]} not found")
println(helpMessage)
} catch(e: CommandLoader.ConfigMissingException) {
println("Config is needed for this command yet it is not present. Run 'init' to generate")
} catch(e: CommandLoader.ModpackJsonMissingException) {
println("Modpackjson is needed for this command yet it is not present.")
}
}
@ -55,11 +66,3 @@ fun main(args: Array<out String>) {
HTTP_CLIENT.connectionPool.evictAll()
}
}
fun printHelp() {
println("Commands:")
LOADER.commands.entries.stream()
//Sort by name
.sorted(Comparator.comparing {e: MutableMap.MutableEntry<String, ICommand> -> e.key})
.forEach {println("${it.key}: ${it.value.helpMessage}")}
}

View file

@ -2,9 +2,10 @@ package ley.anvil.modpacktools.command
import ley.anvil.modpacktools.CONFIG
import ley.anvil.modpacktools.MPJH
import ley.anvil.modpacktools.command.CommandReturn.Companion.fail
import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import kotlin.reflect.KClass
import kotlin.reflect.full.createInstance
/**
* The command loader will scan the given package for {@link ICommand} classes and add them to the command list
@ -12,15 +13,28 @@ import org.reflections.scanners.SubTypesScanner
* @param pkg The package to scan for commands
*/
class CommandLoader(private val pkg: String) {
class ConfigMissingException : IllegalStateException()
class ModpackJsonMissingException : IllegalStateException()
val commands = HashMap<String, ICommand>()
companion object {
/**
* Runs a command statically.
*
* @param args the args to pass to the command
* @throws ConfigMissingException if the command requires a config and it is not found
* @throws ModpackJsonMissingException if the command requires a modpackjson file and it is not found
*/
@JvmStatic
@Throws(ConfigMissingException::class, ModpackJsonMissingException::class)
fun ICommand.runStatic(args: Array<out String>): CommandReturn {
if(this.needsConfig && !CONFIG.configExists())
return fail("Config is needed for this command yet it is not present. Run 'init' to generate")
throw ConfigMissingException()
if(this.needsModpackjson && MPJH.asWrapper == null)
return fail("Modpackjson is needed for this command yet it is not present.")
throw ModpackJsonMissingException()
return this.execute(args)
}
}
@ -35,11 +49,14 @@ class CommandLoader(private val pkg: String) {
val refs = Reflections(pkg, SubTypesScanner(false))
refs.getSubTypesOf(ICommand::class.java).stream()
.map {it.kotlin}
//Only annotated classes
.filter {it.isAnnotationPresent(LoadCommand::class.java)}
//Cannot use it.hasAnnotation because it is experimental and requires everything to be annotated so this makes more sense
.filter {it.annotations.any {ann -> ann.annotationClass == LoadCommand::class}}
//can be object
.map {it.kotlin.objectInstance ?: it}
.forEach {if(it is ICommand) addCommand(it) else addClass(it as Class<out ICommand>)}
.map {it.objectInstance ?: it}
//create new instance if it is a class, otherwise just add the current instance
.forEach {if(it is ICommand) addCommand(it) else addClass(it as KClass<out ICommand>)}
}
/**
@ -48,7 +65,7 @@ class CommandLoader(private val pkg: String) {
* @param clazz the class to add
* @return if it was successful
*/
fun addClass(clazz: Class<out ICommand>) = addCommand(clazz.newInstance())
fun addClass(clazz: KClass<out ICommand>) = addCommand(clazz.createInstance())
/**
* Adds a command to the command list with the name that getName() returns

View file

@ -77,10 +77,10 @@ object CreateModlist : ICommand {
),
each(getMods()) {
tr(
td(a(
td(if(it.icon != null) a(
img().withSrc(it.icon)
.withClass("img")
).withHref(it.website)
).withHref(it.website) else null
),
td(a(it.name)
.withHref(it.website)
@ -92,7 +92,9 @@ object CreateModlist : ICommand {
li(contr.key)
}
)),
td(it.description?.joinToString("<br />") ?: "")
td(each(it.description?.asList() ?: listOf()) {d: String ->
p(d)
})
.withClass("description")
)
}

View file

@ -1,20 +1,21 @@
a:link {
color: #ff5555;
color: #ff5555;
}
a:visited {
color: #cc55cc;
color: #cc55cc;
}
body {
background-color: #333333;
color: #ffffff
background-color: #333333;
color: #ffffff;
font-family: sans-serif;
}
.img {
width:100px;
width: 100px;
}
td {
border: #999999 3px;
border-style: solid;
border: #999999 3px;
border-style: solid;
}
.description {
width: 100%
}
width: 100%;
}