From e3d6211da1095a1be8459d0963b538f78d9aa862 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Thu, 7 Sep 2023 23:53:25 +0200 Subject: [PATCH 1/5] Allow `CliktCommand.test` to take a `vararg` (#451) --- .../ajalt/clikt/testing/CliktTesting.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/testing/CliktTesting.kt b/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/testing/CliktTesting.kt index a2cabac9..836fafb5 100644 --- a/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/testing/CliktTesting.kt +++ b/clikt/src/commonMain/kotlin/com/github/ajalt/clikt/testing/CliktTesting.kt @@ -8,6 +8,7 @@ import com.github.ajalt.clikt.parsers.shlex import com.github.ajalt.mordant.rendering.AnsiLevel import com.github.ajalt.mordant.terminal.Terminal import com.github.ajalt.mordant.terminal.TerminalRecorder +import kotlin.jvm.JvmName data class CliktCommandTestResult( /** Standard output captured from the command */ @@ -52,6 +53,33 @@ fun CliktCommand.test( return test(argvArray, stdin, envvars, includeSystemEnvvars, ansiLevel, width, height) } +/** + * Test this command, returning a result that captures the output and result status code. + * + * Note that only output printed with [echo][CliktCommand.echo] will be captured. Anything printed with [print] or + * [println] is not. + * + * @param argv The command line to send to the command + * @param stdin Content of stdin that will be read by prompt options. Multiple inputs should be separated by `\n`. + * @param envvars A map of environment variable name to value for envvars that can be read by the command + * @param includeSystemEnvvars Set to true to include the environment variables from the system in addition to those + * defined in [envvars] + * @param ansiLevel Defaults to no colored output; set to [AnsiLevel.TRUECOLOR] to include ANSI codes in the output. + * @param width The width of the terminal, used to wrap text + * @param height The height of the terminal + */ +@JvmName("varargTest") +fun CliktCommand.test( + vararg argv: String, + stdin: String = "", + envvars: Map = emptyMap(), + includeSystemEnvvars: Boolean = false, + ansiLevel: AnsiLevel = AnsiLevel.NONE, + width: Int = 79, + height: Int = 24, +): CliktCommandTestResult { + return test(argv.asList(), stdin, envvars, includeSystemEnvvars, ansiLevel, width, height) +} /** * Test this command, returning a result that captures the output and result status code. From c01bad21bf410639ea7f3a73b18dd23344a26a2a Mon Sep 17 00:00:00 2001 From: AJ Alt Date: Thu, 14 Sep 2023 18:05:21 +0000 Subject: [PATCH 2/5] Fix string quoting in json sample (#456) --- samples/json/README.md | 3 +- .../clikt/samples/json/JsonValueSource.kt | 28 ++++++++++++------- .../github/ajalt/clikt/samples/json/main.kt | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/samples/json/README.md b/samples/json/README.md index d5e1fe76..270d5668 100644 --- a/samples/json/README.md +++ b/samples/json/README.md @@ -1,6 +1,7 @@ # JSON Configuration files -This example shows how to read option values from JSON files using the kotlinx.serialization library. +This example shows how to read option values from JSON files using the `kotlinx.serialization` +library. It reads config files from the `config.json` file located in this directory. ``` ./runsample json subcommand diff --git a/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/JsonValueSource.kt b/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/JsonValueSource.kt index 824e2a8b..412be16c 100644 --- a/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/JsonValueSource.kt +++ b/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/JsonValueSource.kt @@ -5,10 +5,7 @@ import com.github.ajalt.clikt.core.InvalidFileFormat import com.github.ajalt.clikt.parameters.options.Option import com.github.ajalt.clikt.sources.ValueSource import kotlinx.serialization.SerializationException -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.* import java.io.File /** @@ -27,10 +24,17 @@ class JsonValueSource( } if (cursor == null) return emptyList() - // This implementation interprets a list as multiple invocations, but you could also - // implement it as a single invocation with multiple values. - if (cursor is JsonArray) return cursor.map { ValueSource.Invocation.value(it) } - return ValueSource.Invocation.just(cursor) + try { + // This implementation interprets a list as multiple invocations, but you could also + // implement it as a single invocation with multiple values. + if (cursor is JsonArray) return cursor.map { + ValueSource.Invocation.value(it.jsonPrimitive.content) + } + return ValueSource.Invocation.just(cursor.jsonPrimitive.content) + } catch (e: IllegalArgumentException) { + // This implementation skips invalid values, but you could handle them differently. + return emptyList() + } } companion object { @@ -41,12 +45,16 @@ class JsonValueSource( Json.parseToJsonElement(file.readText()) as? JsonObject ?: throw InvalidFileFormat(file.path, "object expected", 1) } catch (e: SerializationException) { - if (requireValid) throw InvalidFileFormat(file.name, e.message ?: "could not read file") + if (requireValid) { + throw InvalidFileFormat(file.name, e.message ?: "could not read file") + } JsonObject(emptyMap()) } return JsonValueSource(json) } - fun from(file: String, requireValid: Boolean = false): JsonValueSource = from(File(file), requireValid) + fun from(file: String, requireValid: Boolean = false): JsonValueSource { + return from(File(file), requireValid) + } } } diff --git a/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/main.kt b/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/main.kt index 9f7a45b8..1f928c81 100644 --- a/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/main.kt +++ b/samples/json/src/main/kotlin/com/github/ajalt/clikt/samples/json/main.kt @@ -20,7 +20,7 @@ class Cli : CliktCommand(help = "An example using json files for configuration v init { context { valueSources( - JsonValueSource.from(System.getProperty("user.dir") + "config.json"), + JsonValueSource.from(System.getProperty("user.dir") + "/config.json"), JsonValueSource.from(System.getProperty("user.dir") + "/samples/json/config.json") ) } From ba90c85865b023f326d2b2ac7fc5529687e42f25 Mon Sep 17 00:00:00 2001 From: AJ Alt Date: Fri, 22 Sep 2023 16:45:57 +0000 Subject: [PATCH 3/5] Update quickstart example (#460) --- docs/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index b46883ef..8498c4d5 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -143,7 +143,7 @@ main function directly from within gradle. You can pass command line arguments t with the `--args` flag: ```shell -$ ./gradlew run --args="hello --count=3 --name=Clikt" +$ ./gradlew run --args="--count=3 Clikt" ``` A drawback to using the `run` gradle task is that it redirects stdout, so Clikt will not print From 31a16b85d3112e8702511615b232a8cf71651ff9 Mon Sep 17 00:00:00 2001 From: Paul Woitaschek Date: Sat, 23 Sep 2023 18:22:16 +0200 Subject: [PATCH 4/5] Fix the test example (#461) The triple quote lead to a wrong syntax --- docs/testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/testing.md b/docs/testing.md index 56913ae5..f1f4e1ed 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -42,7 +42,7 @@ You can set environment variables for your command by passing in a map of `envva @Test fun testHello() { val command = Hello() - val result = command.test(""", envvars=mapOf("HELLO_NAME" to "Foo")) + val result = command.test("", envvars=mapOf("HELLO_NAME" to "Foo")) assertEqual(result.stdout, "Hello, Foo!") } ``` From d661506aaacffd49a93a55d1661b77c8495bb164 Mon Sep 17 00:00:00 2001 From: AJ Date: Tue, 26 Sep 2023 10:33:46 -0700 Subject: [PATCH 5/5] Simplify PropertyValueSource.from overload implementation --- .../ajalt/clikt/sources/PropertiesValueSource.kt | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/clikt/src/jvmMain/kotlin/com/github/ajalt/clikt/sources/PropertiesValueSource.kt b/clikt/src/jvmMain/kotlin/com/github/ajalt/clikt/sources/PropertiesValueSource.kt index e599b1db..94240366 100644 --- a/clikt/src/jvmMain/kotlin/com/github/ajalt/clikt/sources/PropertiesValueSource.kt +++ b/clikt/src/jvmMain/kotlin/com/github/ajalt/clikt/sources/PropertiesValueSource.kt @@ -57,19 +57,7 @@ object PropertiesValueSource { requireValid: Boolean = false, getKey: (Context, Option) -> String = ValueSource.getKey(joinSubcommands = "."), ): ValueSource { - val properties = Properties() - if (file.isFile) { - try { - file.bufferedReader().use { properties.load(it) } - } catch (e: Throwable) { - if (requireValid) throw InvalidFileFormat( - file.name, - e.message ?: "could not read file" - ) - } - } - - return from(properties, getKey) + return from(file.toPath(), requireValid, getKey) } /**