commit a5068c3974d3fb39936ed783fddfa8e881277fe3
parent 5f2313d68e65e6c6d39347c0ed83d32c8e166e40
Author: Antoine A <>
Date: Tue, 12 Dec 2023 17:31:22 +0000
Improve CLI help message format
Diffstat:
6 files changed, 144 insertions(+), 155 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
@@ -1,8 +1,8 @@
package tech.libeufin.nexus
import com.github.ajalt.clikt.core.CliktCommand
-import com.github.ajalt.clikt.parameters.options.flag
-import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.groups.*
import tech.libeufin.util.*
import kotlin.system.exitProcess
@@ -12,17 +12,14 @@ import kotlin.system.exitProcess
* the data first.
*/
class DbInit : CliktCommand("Initialize the libeufin-nexus database", name = "dbinit") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
+ private val common by CommonOption()
private val requestReset by option(
"--reset", "-r",
- help = "reset database (DANGEROUS: All existing data is lost)"
+ help = "Reset database (DANGEROUS: All existing data is lost)"
).flag()
override fun run() {
- val cfg = loadConfigOrFail(configFile).extractDbConfigOrFail()
+ val cfg = loadConfigOrFail(common.config).extractDbConfigOrFail()
doOrFail {
pgDataSource(cfg.dbConnStr).pgConnection().use { conn ->
if (requestReset) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -1,8 +1,8 @@
package tech.libeufin.nexus
import com.github.ajalt.clikt.core.CliktCommand
-import com.github.ajalt.clikt.parameters.options.flag
-import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.groups.*
import io.ktor.client.*
import kotlinx.coroutines.runBlocking
import net.taler.wallet.crypto.Base32Crockford
@@ -524,10 +524,7 @@ private suspend fun fetchDocuments(
}
class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 notifications") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
+ private val common by CommonOption()
private val transient by option(
"--transient",
help = "This flag fetches only once from the bank and returns, " +
@@ -553,7 +550,7 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti
).flag(default = false)
private val pinnedStart by option(
- help = "constant YYYY-MM-DD date for the earliest document" +
+ help = "Constant YYYY-MM-DD date for the earliest document" +
" to download (only consumed in --transient mode). The" +
" latest document is always until the current time."
)
@@ -580,7 +577,7 @@ class EbicsFetch: CliktCommand("Fetches bank records. Defaults to camt.054 noti
*/
override fun run() {
val cfg: EbicsSetupConfig = doOrFail {
- extractEbicsConfig(configFile)
+ extractEbicsConfig(common.config)
}
val dbCfg = cfg.config.extractDbConfigOrFail()
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
@@ -20,8 +20,8 @@
package tech.libeufin.nexus
import com.github.ajalt.clikt.core.CliktCommand
-import com.github.ajalt.clikt.parameters.options.flag
-import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.groups.*
import io.ktor.client.*
import kotlinx.coroutines.runBlocking
import tech.libeufin.util.ebics_h004.EbicsTypes
@@ -330,27 +330,24 @@ private fun makePdf(privs: ClientPrivateKeysFile, cfg: EbicsSetupConfig) {
* CLI class implementing the "ebics-setup" subcommand.
*/
class EbicsSetup: CliktCommand("Set up the EBICS subscriber") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
+ private val common by CommonOption()
private val checkFullConfig by option(
- help = "checks config values of ALL the subcommands"
+ help = "Checks config values of ALL the subcommands"
).flag(default = false)
private val forceKeysResubmission by option(
- help = "resubmits all the keys to the bank"
+ help = "Resubmits all the keys to the bank"
).flag(default = false)
private val autoAcceptKeys by option(
- help = "accepts the bank keys without the user confirmation"
+ help = "Accepts the bank keys without the user confirmation"
).flag(default = false)
private val generateRegistrationPdf by option(
- help = "generates the PDF with the client public keys to send to the bank"
+ help = "Generates the PDF with the client public keys to send to the bank"
).flag(default = false)
/**
* This function collects the main steps of setting up an EBICS access.
*/
override fun run() {
- val cfg = doOrFail { extractEbicsConfig(this.configFile) }
+ val cfg = doOrFail { extractEbicsConfig(common.config) }
if (checkFullConfig) {
doOrFail {
cfg.config.requireString("nexus-submit", "frequency").apply {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -20,16 +20,15 @@
package tech.libeufin.nexus
import com.github.ajalt.clikt.core.CliktCommand
-import com.github.ajalt.clikt.parameters.options.flag
-import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.groups.*
import io.ktor.client.*
import kotlinx.coroutines.runBlocking
import tech.libeufin.nexus.ebics.EbicsSideError
import tech.libeufin.nexus.ebics.EbicsSideException
import tech.libeufin.nexus.ebics.EbicsUploadException
import tech.libeufin.nexus.ebics.submitPain001
-import tech.libeufin.util.parsePayto
-import tech.libeufin.util.toDbMicros
+import tech.libeufin.util.*
import java.io.File
import java.nio.file.Path
import java.time.Instant
@@ -251,10 +250,7 @@ private fun submitBatch(
}
class EbicsSubmit : CliktCommand("Submits any initiated payment found in the database") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
+ private val common by CommonOption()
private val transient by option(
"--transient",
help = "This flag submits what is found in the database and returns, " +
@@ -276,7 +272,7 @@ class EbicsSubmit : CliktCommand("Submits any initiated payment found in the dat
*/
override fun run() {
val cfg: EbicsSetupConfig = doOrFail {
- extractEbicsConfig(configFile)
+ extractEbicsConfig(common.config)
}
// Fail now if keying is incomplete.
if (!isKeyingComplete(cfg)) exitProcess(1)
diff --git a/util/src/main/kotlin/Cli.kt b/util/src/main/kotlin/Cli.kt
@@ -0,0 +1,121 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2023 Taler Systems S.A.
+
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
+ * Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.util
+
+import ConfigSource
+import TalerConfig
+import TalerConfigError
+import com.github.ajalt.clikt.core.CliktCommand
+import com.github.ajalt.clikt.core.subcommands
+import com.github.ajalt.clikt.parameters.types.*
+import com.github.ajalt.clikt.parameters.arguments.*
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.groups.*
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import kotlin.system.exitProcess
+
+private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.util.ConfigCli")
+
+fun cliCmd(logger: Logger, lambda: () -> Unit) {
+ try {
+ lambda()
+ } catch (e: Exception) {
+ logger.error(e.message)
+ exitProcess(1)
+ }
+}
+
+private fun talerConfig(configSource: ConfigSource, configPath: String?): TalerConfig {
+ val config = TalerConfig(configSource)
+ config.load(configPath)
+ return config
+}
+
+class CommonOption: OptionGroup() {
+ val config by option(
+ "--config", "-c",
+ help = "Specifies the configuration file"
+ ).path(
+ mustExist = true,
+ canBeDir = false,
+ mustBeReadable = true,
+ ).convert { it.toString() } // TODO take path to load config
+}
+
+class CliConfigCmd(configSource: ConfigSource) : CliktCommand("Inspect or change the configuration", name = "config") {
+ init {
+ subcommands(CliConfigDump(configSource), CliConfigPathsub(configSource), CliConfigGet(configSource))
+ }
+
+ override fun run() = Unit
+}
+
+private class CliConfigGet(private val configSource: ConfigSource) : CliktCommand("Lookup config value", name = "get") {
+ private val common by CommonOption()
+ private val isPath by option(
+ "--filename", "-f",
+ help = "Interpret value as path with dollar-expansion"
+ ).flag()
+ private val sectionName by argument()
+ private val optionName by argument()
+
+
+ override fun run() = cliCmd(logger) {
+ val config = talerConfig(configSource, common.config)
+ if (isPath) {
+ val res = config.lookupPath(sectionName, optionName)
+ if (res == null) {
+ logger.error("value not found in config")
+ exitProcess(2)
+ }
+ println(res)
+ } else {
+ val res = config.lookupString(sectionName, optionName)
+ if (res == null) {
+ logger.error("value not found in config")
+ exitProcess(2)
+ }
+ println(res)
+ }
+ }
+}
+
+
+
+private class CliConfigPathsub(private val configSource: ConfigSource) : CliktCommand("Substitute variables in a path", name = "pathsub") {
+ private val common by CommonOption()
+ private val pathExpr by argument()
+
+ override fun run() = cliCmd(logger) {
+ val config = talerConfig(configSource, common.config)
+ println(config.pathsub(pathExpr))
+ }
+}
+
+private class CliConfigDump(private val configSource: ConfigSource) : CliktCommand("Dump the configuration", name = "dump") {
+ private val common by CommonOption()
+
+ override fun run() = cliCmd(logger) {
+ val config = talerConfig(configSource, common.config)
+ println("# install path: ${config.getInstallPath()}")
+ println(config.stringify())
+ }
+}
diff --git a/util/src/main/kotlin/ConfigCli.kt b/util/src/main/kotlin/ConfigCli.kt
@@ -1,119 +0,0 @@
-/*
- * This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
-
- * LibEuFin is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation; either version 3, or
- * (at your option) any later version.
-
- * LibEuFin is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
- * Public License for more details.
-
- * You should have received a copy of the GNU Affero General Public
- * License along with LibEuFin; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>
- */
-
-package tech.libeufin.util
-
-import ConfigSource
-import TalerConfig
-import TalerConfigError
-import com.github.ajalt.clikt.core.CliktCommand
-import com.github.ajalt.clikt.core.subcommands
-import com.github.ajalt.clikt.parameters.arguments.argument
-import com.github.ajalt.clikt.parameters.options.flag
-import com.github.ajalt.clikt.parameters.options.option
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import kotlin.system.exitProcess
-
-private val logger: Logger = LoggerFactory.getLogger("tech.libeufin.util.ConfigCli")
-
-fun cliCmd(logger: Logger, lambda: () -> Unit) {
- try {
- lambda()
- } catch (e: Exception) {
- logger.error(e.message)
- exitProcess(1)
- }
-}
-
-private fun talerConfig(configSource: ConfigSource, configPath: String?): TalerConfig {
- val config = TalerConfig(configSource)
- config.load(configPath)
- return config
-}
-
-class CliConfigCmd(configSource: ConfigSource) : CliktCommand("Inspect or change the configuration", name = "config") {
- init {
- subcommands(CliConfigDump(configSource), CliConfigPathsub(configSource), CliConfigGet(configSource))
- }
-
- override fun run() = Unit
-}
-
-private class CliConfigGet(private val configSource: ConfigSource) : CliktCommand("Lookup config value", name = "get") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
- private val isPath by option(
- "--filename", "-f",
- help = "interpret value as path with dollar-expansion"
- ).flag()
- private val sectionName by argument()
- private val optionName by argument()
-
-
- override fun run() = cliCmd(logger) {
- val config = talerConfig(configSource, configFile)
- if (isPath) {
- val res = config.lookupPath(sectionName, optionName)
- if (res == null) {
- logger.error("value not found in config")
- exitProcess(2)
- }
- println(res)
- } else {
- val res = config.lookupString(sectionName, optionName)
- if (res == null) {
- logger.error("value not found in config")
- exitProcess(2)
- }
- println(res)
- }
- }
-}
-
-
-
-private class CliConfigPathsub(private val configSource: ConfigSource) : CliktCommand("Substitute variables in a path", name = "pathsub") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
- private val pathExpr by argument()
-
- override fun run() = cliCmd(logger) {
- val config = talerConfig(configSource, configFile)
- println(config.pathsub(pathExpr))
- }
-}
-
-private class CliConfigDump(private val configSource: ConfigSource) : CliktCommand("Dump the configuration", name = "dump") {
- private val configFile by option(
- "--config", "-c",
- help = "set the configuration file"
- )
-
- override fun run() = cliCmd(logger) {
- val config = talerConfig(configSource, configFile)
- println("# install path: ${config.getInstallPath()}")
- config.load(this.configFile)
- println(config.stringify())
- }
-}