diff --git a/manual.md b/manual.md index 3ca11c9..c392f09 100644 --- a/manual.md +++ b/manual.md @@ -6,7 +6,7 @@ Command | Description | Aliases | Usage add |Add a new mod | |add nexus nxm://starfield/mods/4183/files/12955?key=abc&expires=1697023374&user_id=111
add https://www.nexusmods.com/starfield/mods/4183?tab=files
add 4183
add 4183 4182 4181 - Add multiple by id
add * config |Edit Configuration | |config game-path - Sets the path to the folder under steam containing the starfield Data folder and exe
config ini-path - Sets the path to the folder under your documents that contains StarfieldCustom.ini and eventually Plugins.txt. Needed for updating mod load order
config api-key
config verbose - get additional output (for debugging)
config use-my-docs - deploy mod files under Data to my documents instead of the game folder. (Defaults to false)
config categories - download category names from nexus
If your paths have spaces, make sure to quote them enable |Enable Mod | |enable
disable
enable 1 2 4
enable 1-4
disable all -disable |Enable Mod | |enable
disable
enable 1 2 4
enable 1-4
disable all +disable |Disable Mod | |enable
disable
enable 1 2 4
enable 1-4
disable all endorse |Endorse Mod | |endorse - endorse a mod on nexus
abstain
endorse 1 2 4
endorse 1-4 abstain |Abstain from endorsing Mod | |endorse - endorse a mod on nexus
abstain
endorse 1 2 4
endorse 1-4 deploy |Deploy enabled mods | |deploy - Applies all mods to the game folder by creating the appropriate symlinks
deploy dryrun - Per your load order view how files will be deployed diff --git a/src/main/kotlin/TablePrinter.kt b/src/main/kotlin/TablePrinter.kt index 6fbc9a5..0cd6c8a 100644 --- a/src/main/kotlin/TablePrinter.kt +++ b/src/main/kotlin/TablePrinter.kt @@ -1,9 +1,11 @@ +import io.ktor.client.utils.EmptyContent.headers + fun String?.truncate(length: Int = 6): String { return this?.substring(0, kotlin.math.min(this.length, length)) ?: "" } data class Table(val columns: List, val data: List>) { - fun print() { + fun print(highlightHeaders: Boolean = true) { val colFormat = columns.joinToString("") { "%-${it.size}s" } val rowFormat = columns.joinToString("") { val type = if (it.isNumber) "d" else "s" @@ -11,7 +13,8 @@ data class Table(val columns: List, val data: List>) { } val headerValues = columns.map { it.header }.toTypedArray() - System.out.printf(cyan("$colFormat\n"), *headerValues) + val headers = if (highlightHeaders) cyan("$colFormat\n") else "$colFormat\n" + System.out.printf(headers, *headerValues) data.forEach { row -> val dataValues = columns.map { row[it.header] ?: "" }.toTypedArray() System.out.printf("$rowFormat\n", *dataValues) diff --git a/src/main/kotlin/commands/CommandType.kt b/src/main/kotlin/commands/CommandType.kt index c67565d..da2687f 100644 --- a/src/main/kotlin/commands/CommandType.kt +++ b/src/main/kotlin/commands/CommandType.kt @@ -1,43 +1,46 @@ package commands +enum class Category { ADD, DEPLOY, VIEW, EDIT, OPEN, UPDATE, CONFIG } + enum class CommandType( val description: String, + val category: Category, val help: () -> String, val apply: (List) -> Unit, vararg val aliases: String = arrayOf(), ) { - ADD("Add a new mod", ::addModHelp, ::addMod), - CONFIG("Edit Configuration", ::configHelp, ::config), - ENABLE("Enable Mod", ::enableHelp, ::enable), - DISABLE("Enable Mod", ::enableHelp, ::disable), - ENDORSE("Endorse Mod", ::endorseHelp, ::endorse), - ABSTAIN("Abstain from endorsing Mod", ::endorseHelp, ::abstain), - DEPLOY("Deploy enabled mods", ::deployHelp, ::deploy), - HELP("Explain commands", ::helpHelp, ::help), - FETCH("Fetch Mod Data", ::fetchHelp, ::fetchMod), - LIST("List Mods", ::listHelp, ::listMods, "ls"), - DETAIL("View all details of mod", ::detailHelp, ::detailMod), - ORDER("Change Load Order", ::orderHelp, ::order), - OPEN("Open mod on web", ::openHelp, ::open), - LOCAL("Open local mod folder", ::openHelp, ::local), - GAME_PATH("Open game folder", ::openHelp, ::openGamePath, "gamepath"), - INI_PATH("Open ini path folder", ::openHelp, ::openIniPath, "inipath"), - JAR_PATH("Open jar path folder", ::openHelp, ::openJarPath, "jarpath"), - PURGE("Purge all sym links", ::purgeHelp, ::purge), - MOD("Update a mod", ::changeHelp, ::changeMod), - PROFILE("Create and use local mod lists", ::profileHelp, ::profile), - RENAME("Rename a mod", ::changeHelp, ::moveMod, "mv"), - REFRESH("Refresh mods by id", ::refreshHelp, ::refresh), - UPDATE("Check for newer versions", ::updateHelp, ::update), - UPGRADE("Upgrade to newer versions", ::upgradeHelp, ::upgrade), - REMOVE("Delete a mod", ::removeHelp, ::remove, "rm"), - SEARCH("Search Mods", ::searchHelp, ::searchMods, "grep", "awk"), - FILTER("Apply a filter to Mods", ::filterHelp, ::filterMods), - SORT("Sort Mods", ::sortHelp, ::sortMods), - VALIDATE("List issues with mods", ::validateHelp, ::validateMods), - START("Launch Starfield", ::startGameHelp, ::startGame, "game"), + ADD("Add a new mod", Category.ADD, ::addModHelp, ::addMod), + CONFIG("Edit Configuration", Category.CONFIG, ::configHelp, ::config), + ENABLE("Enable Mod", Category.DEPLOY, ::enableHelp, ::enable), + DISABLE("Disable Mod", Category.DEPLOY, ::enableHelp, ::disable), + ENDORSE("Endorse Mod", Category.EDIT, ::endorseHelp, ::endorse), + ABSTAIN("Abstain from endorsing Mod", Category.EDIT, ::endorseHelp, ::abstain), + DEPLOY("Deploy enabled mods", Category.DEPLOY, ::deployHelp, ::deploy), + HELP("Explain commands", Category.CONFIG, ::helpHelp, ::help), + FETCH("Fetch Mod Data", Category.ADD, ::fetchHelp, ::fetchMod), + LIST("List Mods", Category.VIEW, ::listHelp, ::listMods, "ls"), + DETAIL("View all details of mod", Category.VIEW, ::detailHelp, ::detailMod), + ORDER("Change Load Order", Category.DEPLOY, ::orderHelp, ::order), + OPEN("Open mod on web", Category.OPEN, ::openHelp, ::open), + LOCAL("Open local mod folder", Category.OPEN, ::openHelp, ::local), + GAME_PATH("Open game folder", Category.OPEN, ::openHelp, ::openGamePath, "gamepath"), + INI_PATH("Open ini path folder", Category.OPEN, ::openHelp, ::openIniPath, "inipath"), + JAR_PATH("Open jar path folder", Category.OPEN, ::openHelp, ::openJarPath, "jarpath"), + PURGE("Purge all sym links", Category.DEPLOY, ::purgeHelp, ::purge), + MOD("Update a mod", Category.EDIT, ::changeHelp, ::changeMod), + PROFILE("Create and use local mod lists", Category.DEPLOY, ::profileHelp, ::profile), + RENAME("Rename a mod", Category.EDIT, ::changeHelp, ::moveMod, "mv"), + REFRESH("Refresh mods by id", Category.UPDATE, ::refreshHelp, ::refresh), + UPDATE("Check for newer versions", Category.UPDATE, ::updateHelp, ::update), + UPGRADE("Upgrade to newer versions", Category.UPDATE, ::upgradeHelp, ::upgrade), + REMOVE("Delete a mod", Category.ADD, ::removeHelp, ::remove, "rm"), + SEARCH("Search Mods", Category.VIEW, ::searchHelp, ::searchMods, "grep", "awk"), + FILTER("Apply a filter to Mods", Category.VIEW, ::filterHelp, ::filterMods), + SORT("Sort Mods", Category.VIEW, ::sortHelp, ::sortMods), + VALIDATE("List issues with mods", Category.DEPLOY, ::validateHelp, ::validateMods), + START("Launch Starfield", Category.CONFIG, ::startGameHelp, ::startGame, "game"), EXIT( - "Exit Program", + "Exit Program", Category.CONFIG, { "Exit the process" }, { kotlin.system.exitProcess(0) } ), diff --git a/src/main/kotlin/commands/Help.kt b/src/main/kotlin/commands/Help.kt index bc00870..2afde17 100644 --- a/src/main/kotlin/commands/Help.kt +++ b/src/main/kotlin/commands/Help.kt @@ -1,5 +1,9 @@ package commands +import Column +import Table +import cyan + fun helpHelp() = "" fun help(args: List = listOf()) { val helpCommand = args.firstOrNull()?.let { getCommand(it) } @@ -12,9 +16,24 @@ fun help(args: List = listOf()) { } private fun printGeneralHelp() { - println(CommandType.entries.filterNot { it == CommandType.HELP }.joinToString("\n") { - "${it.cleanName}\n\t${it.description}" - }) + CommandType.entries + .filterNot { it == CommandType.HELP } + .groupBy { it.category }.entries + .forEach { (category, commands) -> + println(cyan(category.name.lowercase().capitalize())) + val columns = listOf( + Column("Command", 10), + Column("Summary", 30), + ) + val data = commands.map { + mapOf( + "Command" to it.cleanName, + "Summary" to it.description, + ) + } + Table(columns, data).print(false) + println() + } } private fun printDetailedHelp() {