From cc8c54990d3aa277fb771e87f732987b0cbc624e Mon Sep 17 00:00:00 2001 From: hinerm Date: Wed, 11 Dec 2024 12:16:19 -0600 Subject: [PATCH] Create overridable config fields JaunchConfig fields prefixed with "cfg." will now explicitly allow override via reading .cfg files. This allows us to set default field values in the .toml but later allow the user to specify these values in a more-easily modified config file. The general pattern is illustrated here with the jvmMaxHeap field: - a cfg.max-heap field is delcared in the toml with a default value - jvm.max-heap is defined in the toml with a value of cfg.max-heap - when jvm.max-heap is interpolated it will resolve to the current cfg.max-heap value, which may have been overridden by a .cfg file Required for https://github.com/fiji/fiji/issues/351 --- src/commonMain/kotlin/config.kt | 14 ++++++++++++++ src/commonMain/kotlin/main.kt | 2 +- src/commonMain/kotlin/vars.kt | 12 +++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/commonMain/kotlin/config.kt b/src/commonMain/kotlin/config.kt index 6508a36..950df20 100644 --- a/src/commonMain/kotlin/config.kt +++ b/src/commonMain/kotlin/config.kt @@ -123,6 +123,9 @@ data class JaunchConfig ( /** Arguments to pass to the main class on the Java side. */ val jvmMainArgs: Array = emptyArray(), + + /** The list of options overridable by .cfg files understood by Jaunch. */ + val cfgVars: Map = emptyMap(), ) { /** Return true iff the given argument is on the specified list of recognized args. */ fun recognizes(arg: String, recognizedArgs: Array): Boolean { @@ -153,6 +156,7 @@ data class JaunchConfig ( programName = config.programName ?: programName, includes = config.includes + includes, supportedOptions = config.supportedOptions + supportedOptions, + cfgVars = config.cfgVars + cfgVars, osAliases = config.osAliases + osAliases, archAliases = config.archAliases + archAliases, modes = config.modes + modes, @@ -240,6 +244,8 @@ fun readConfig( var jvmMainClass: List? = null var jvmMainArgs: List? = null + val cfgVars = mutableMapOf() + // Parse TOML file lines into tokens. val tokens = mutableListOf() tomlFile.lines().forEach { appendTokens(it, tokens) } @@ -294,6 +300,13 @@ fun readConfig( "jvm.runtime-args" -> jvmRuntimeArgs = asList(value) "jvm.main-class" -> jvmMainClass = asList(value) "jvm.main-args" -> jvmMainArgs = asList(value) + else -> { + // Parse cfg.* variable assignments into a cfgVars map + if (name.startsWith("cfg.") && value != null) { + cfgVars[name] = value + } + else warn("[TOML] Unsupported key: '$name'") + } } } else -> warn("[TOML] Ignoring extraneous token: '$token' [${token::class.simpleName}]") @@ -311,6 +324,7 @@ fun readConfig( programName = programName, includes = asArray(includes), supportedOptions = asArray(supportedOptions), + cfgVars = cfgVars, osAliases = asArray(osAliases), archAliases = asArray(archAliases), modes = asArray(modes), diff --git a/src/commonMain/kotlin/main.kt b/src/commonMain/kotlin/main.kt index 69a4a60..7dd9a8b 100644 --- a/src/commonMain/kotlin/main.kt +++ b/src/commonMain/kotlin/main.kt @@ -67,7 +67,7 @@ fun main(args: Array) { // Declare a set to store option parameter values. // It will be populated at argument parsing time. - val vars = Vars(appDir, configDir, exeFile) + val vars = Vars(appDir, configDir, exeFile, config.cfgVars) // Sort out the arguments, keeping the user-specified runtime and main arguments in a struct. At this point, // it may yet be ambiguous whether certain user args belong with the runtime, the main program, or neither. diff --git a/src/commonMain/kotlin/vars.kt b/src/commonMain/kotlin/vars.kt index 773634a..9f3b95e 100644 --- a/src/commonMain/kotlin/vars.kt +++ b/src/commonMain/kotlin/vars.kt @@ -1,6 +1,11 @@ // Vars class and related functions for working with variables. -class Vars(appDir: File, configDir: File, exeFile: File?) { +class Vars( + appDir: File, + configDir: File, + exeFile: File?, + cfgVars: Map +) { private val vars = mutableMapOf() init { @@ -8,6 +13,11 @@ class Vars(appDir: File, configDir: File, exeFile: File?) { vars["config-dir"] = configDir.path if (exeFile?.exists == true) vars["executable"] = exeFile.path + // Parse any Vars that were previously defined in toml. + if (cfgVars is Map) { + vars.putAll(cfgVars) + } + // Build the list of config files val cfgFiles = mutableListOf() var cfgName = exeFile?.base?.name