mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2024-11-22 23:22:05 +01:00
Add support for rendering help info for input and output
This commit is contained in:
parent
ddf4ba19f9
commit
a607013cfb
4 changed files with 120 additions and 6 deletions
|
@ -81,8 +81,8 @@ class SopCLI {
|
||||||
// Re-set bundle with updated locale
|
// Re-set bundle with updated locale
|
||||||
cliMsg = ResourceBundle.getBundle("msg_sop")
|
cliMsg = ResourceBundle.getBundle("msg_sop")
|
||||||
|
|
||||||
return CommandLine(SopCLI::class.java)
|
val cmd =
|
||||||
.apply {
|
CommandLine(SopCLI::class.java).apply {
|
||||||
// explicitly set help command resource bundle
|
// explicitly set help command resource bundle
|
||||||
subcommands["help"]?.setResourceBundle(ResourceBundle.getBundle("msg_help"))
|
subcommands["help"]?.setResourceBundle(ResourceBundle.getBundle("msg_help"))
|
||||||
// Hide generate-completion command
|
// Hide generate-completion command
|
||||||
|
@ -94,7 +94,15 @@ class SopCLI {
|
||||||
exitCodeExceptionMapper = SOPExceptionExitCodeMapper()
|
exitCodeExceptionMapper = SOPExceptionExitCodeMapper()
|
||||||
isCaseInsensitiveEnumValuesAllowed = true
|
isCaseInsensitiveEnumValuesAllowed = true
|
||||||
}
|
}
|
||||||
.execute(*args)
|
|
||||||
|
// render Input/Output sections in help command
|
||||||
|
cmd.subcommands.values
|
||||||
|
.filter {
|
||||||
|
(it.getCommand() as Any) is AbstractSopCmd
|
||||||
|
} // Only for AbstractSopCmd objects
|
||||||
|
.forEach { (it.getCommand() as AbstractSopCmd).installIORenderer(it) }
|
||||||
|
|
||||||
|
return cmd.execute(*args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,11 @@ package sop.cli.picocli.commands
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.text.ParseException
|
import java.text.ParseException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import picocli.CommandLine
|
||||||
|
import picocli.CommandLine.Help
|
||||||
|
import picocli.CommandLine.Help.Column
|
||||||
|
import picocli.CommandLine.Help.TextTable
|
||||||
|
import picocli.CommandLine.IHelpSectionRenderer
|
||||||
import sop.cli.picocli.commands.AbstractSopCmd.EnvironmentVariableResolver
|
import sop.cli.picocli.commands.AbstractSopCmd.EnvironmentVariableResolver
|
||||||
import sop.exception.SOPGPException.*
|
import sop.exception.SOPGPException.*
|
||||||
import sop.util.UTCUtil.Companion.parseUTCDate
|
import sop.util.UTCUtil.Companion.parseUTCDate
|
||||||
|
@ -215,11 +220,106 @@ abstract class AbstractSopCmd(locale: Locale = Locale.getDefault()) : Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See
|
||||||
|
* [Example](https://github.com/remkop/picocli/blob/main/picocli-examples/src/main/java/picocli/examples/customhelp/EnvironmentVariablesSection.java)
|
||||||
|
*/
|
||||||
|
class InputOutputHelpSectionRenderer(private val argument: Pair<String?, String?>) :
|
||||||
|
IHelpSectionRenderer {
|
||||||
|
|
||||||
|
override fun render(help: Help): String {
|
||||||
|
return argument.let {
|
||||||
|
val calcLen =
|
||||||
|
help.calcLongOptionColumnWidth(
|
||||||
|
help.commandSpec().options(),
|
||||||
|
help.commandSpec().positionalParameters(),
|
||||||
|
help.colorScheme())
|
||||||
|
val keyLength =
|
||||||
|
help
|
||||||
|
.commandSpec()
|
||||||
|
.usageMessage()
|
||||||
|
.longOptionsMaxWidth()
|
||||||
|
.coerceAtMost(calcLen - 1)
|
||||||
|
val table =
|
||||||
|
TextTable.forColumns(
|
||||||
|
help.colorScheme(),
|
||||||
|
Column(keyLength + 7, 6, Column.Overflow.SPAN),
|
||||||
|
Column(width(help) - (keyLength + 7), 0, Column.Overflow.WRAP))
|
||||||
|
table.setAdjustLineBreaksForWideCJKCharacters(adjustCJK(help))
|
||||||
|
table.addRowValues("@|yellow ${argument.first}|@", argument.second ?: "")
|
||||||
|
table.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun adjustCJK(help: Help) =
|
||||||
|
help.commandSpec().usageMessage().adjustLineBreaksForWideCJKCharacters()
|
||||||
|
|
||||||
|
private fun width(help: Help) = help.commandSpec().usageMessage().width()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun installIORenderer(cmd: CommandLine) {
|
||||||
|
val inputName = getResString(cmd, "standardInput")
|
||||||
|
if (inputName != null) {
|
||||||
|
cmd.helpSectionMap[SECTION_KEY_STANDARD_INPUT_HEADING] = IHelpSectionRenderer {
|
||||||
|
getResString(cmd, "standardInputHeading")
|
||||||
|
}
|
||||||
|
cmd.helpSectionMap[SECTION_KEY_STANDARD_INPUT_DETAILS] =
|
||||||
|
InputOutputHelpSectionRenderer(
|
||||||
|
inputName to getResString(cmd, "standardInputDescription"))
|
||||||
|
cmd.helpSectionKeys =
|
||||||
|
insertKey(
|
||||||
|
cmd.helpSectionKeys,
|
||||||
|
SECTION_KEY_STANDARD_INPUT_HEADING,
|
||||||
|
SECTION_KEY_STANDARD_INPUT_DETAILS)
|
||||||
|
}
|
||||||
|
|
||||||
|
val outputName = getResString(cmd, "standardOutput")
|
||||||
|
if (outputName != null) {
|
||||||
|
cmd.helpSectionMap[SECTION_KEY_STANDARD_OUTPUT_HEADING] = IHelpSectionRenderer {
|
||||||
|
getResString(cmd, "standardOutputHeading")
|
||||||
|
}
|
||||||
|
cmd.helpSectionMap[SECTION_KEY_STANDARD_OUTPUT_DETAILS] =
|
||||||
|
InputOutputHelpSectionRenderer(
|
||||||
|
outputName to getResString(cmd, "standardOutputDescription"))
|
||||||
|
cmd.helpSectionKeys =
|
||||||
|
insertKey(
|
||||||
|
cmd.helpSectionKeys,
|
||||||
|
SECTION_KEY_STANDARD_OUTPUT_HEADING,
|
||||||
|
SECTION_KEY_STANDARD_OUTPUT_DETAILS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertKey(keys: List<String>, header: String, details: String): List<String> {
|
||||||
|
val index =
|
||||||
|
keys.indexOf(CommandLine.Model.UsageMessageSpec.SECTION_KEY_EXIT_CODE_LIST_HEADING)
|
||||||
|
val result = keys.toMutableList()
|
||||||
|
result.add(index, header)
|
||||||
|
result.add(index + 1, details)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getResString(cmd: CommandLine, key: String): String? =
|
||||||
|
try {
|
||||||
|
cmd.resourceBundle.getString(key)
|
||||||
|
} catch (m: MissingResourceException) {
|
||||||
|
try {
|
||||||
|
cmd.parent.resourceBundle.getString(key)
|
||||||
|
} catch (m: MissingResourceException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?.let { String.format(it) }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PRFX_ENV = "@ENV:"
|
const val PRFX_ENV = "@ENV:"
|
||||||
|
|
||||||
const val PRFX_FD = "@FD:"
|
const val PRFX_FD = "@FD:"
|
||||||
|
|
||||||
|
const val SECTION_KEY_STANDARD_INPUT_HEADING = "standardInputHeading"
|
||||||
|
const val SECTION_KEY_STANDARD_INPUT_DETAILS = "standardInput"
|
||||||
|
const val SECTION_KEY_STANDARD_OUTPUT_HEADING = "standardOutputHeading"
|
||||||
|
const val SECTION_KEY_STANDARD_OUTPUT_DETAILS = "standardOutput"
|
||||||
|
|
||||||
@JvmField val DAWN_OF_TIME = Date(0)
|
@JvmField val DAWN_OF_TIME = Date(0)
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|
|
@ -9,10 +9,13 @@ locale=Locale for description texts
|
||||||
|
|
||||||
# Generic
|
# Generic
|
||||||
usage.synopsisHeading=Usage:\u0020
|
usage.synopsisHeading=Usage:\u0020
|
||||||
usage.commandListHeading = %nCommands:%n
|
usage.commandListHeading=%nCommands:%n
|
||||||
usage.optionListHeading = %nOptions:%n
|
usage.optionListHeading=%nOptions:%n
|
||||||
usage.footerHeading=Powered by picocli%n
|
usage.footerHeading=Powered by picocli%n
|
||||||
|
|
||||||
|
standardInputHeading=%nInput:%n
|
||||||
|
standardOutputHeading=%nOutput:%n
|
||||||
|
|
||||||
# Exit Codes
|
# Exit Codes
|
||||||
usage.exitCodeListHeading=%nExit Codes:%n
|
usage.exitCodeListHeading=%nExit Codes:%n
|
||||||
usage.exitCodeList.0=\u00200:Successful program execution
|
usage.exitCodeList.0=\u00200:Successful program execution
|
||||||
|
|
|
@ -10,9 +10,12 @@ locale=Gebietsschema f
|
||||||
# Generic
|
# Generic
|
||||||
usage.synopsisHeading=Aufruf:\u0020
|
usage.synopsisHeading=Aufruf:\u0020
|
||||||
usage.commandListHeading=%nBefehle:%n
|
usage.commandListHeading=%nBefehle:%n
|
||||||
usage.optionListHeading = %nOptionen:%n
|
usage.optionListHeading=%nOptionen:%n
|
||||||
usage.footerHeading=Powered by Picocli%n
|
usage.footerHeading=Powered by Picocli%n
|
||||||
|
|
||||||
|
standardInputHeading=%nEingabe:%n
|
||||||
|
standardOutputHeading=%nAusgabe:%n
|
||||||
|
|
||||||
# Exit Codes
|
# Exit Codes
|
||||||
usage.exitCodeListHeading=%nExit Codes:%n
|
usage.exitCodeListHeading=%nExit Codes:%n
|
||||||
usage.exitCodeList.0=\u00200:Erfolgreiche Programmausführung
|
usage.exitCodeList.0=\u00200:Erfolgreiche Programmausführung
|
||||||
|
|
Loading…
Reference in a new issue