Add the ability to query for config values from specific sources.

This commit is contained in:
2026-04-13 12:51:11 -05:00
parent fccaf54dc5
commit 58a6c94885
2 changed files with 44 additions and 13 deletions

View File

@@ -1,6 +1,6 @@
# Package # Package
version = "0.12.0" version = "0.12.1"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Helper functions for writing command line interfaces." description = "Helper functions for writing command line interfaces."
license = "MIT" license = "MIT"

View File

@@ -1,4 +1,4 @@
import std/[json, os, sequtils, strtabs, strutils] import std/[json, options, os, sequtils, strtabs, strutils]
import docopt, identcasing, regex import docopt, identcasing, regex
type type
@@ -100,6 +100,17 @@ proc findConfigFile*(name: string, otherLocations: seq[string] = @[]): string =
raise newException(ValueError, "could not find configuration file") raise newException(ValueError, "could not find configuration file")
proc jsonConfigNodeToString(node: JsonNode): string =
case node.kind
of JString: node.getStr
of JInt: $node.getInt
of JFloat: $node.getFloat
of JBool: $node.getBool
of JNull: ""
of JObject: $node
of JArray: $node
proc getValueAndProvenance*( proc getValueAndProvenance*(
cfg: CombinedConfig, cfg: CombinedConfig,
key: string): tuple[value: string, provenance: ValueProvenance] key: string): tuple[value: string, provenance: ValueProvenance]
@@ -111,17 +122,7 @@ proc getValueAndProvenance*(
elif existsEnv(envKey): elif existsEnv(envKey):
return (getEnv(envKey), ValueProvenance.environment) return (getEnv(envKey), ValueProvenance.environment)
elif cfg.json.hasKey(jsonKey): elif cfg.json.hasKey(jsonKey):
let node = cfg.json[jsonKey] return (jsonConfigNodeToString(cfg.json[jsonKey]), ValueProvenance.json)
let value =
case node.kind
of JString: node.getStr
of JInt: $node.getInt
of JFloat: $node.getFloat
of JBool: $node.getBool
of JNull: ""
of JObject: $node
of JArray: $node
return (value, ValueProvenance.json)
else: raise newException(ValueError, "cannot find a configuration value for \"" & key & "\"") else: raise newException(ValueError, "cannot find a configuration value for \"" & key & "\"")
@@ -146,6 +147,21 @@ proc getVal*(cfg: CombinedConfig, key, default: string): string {.raises: [].} =
proc `[]`*(cfg: CombinedConfig, key: string): string = getVal(cfg, key) proc `[]`*(cfg: CombinedConfig, key: string): string = getVal(cfg, key)
proc getValueFromSource*(
cfg: CombinedConfig,
source: ValueProvenance,
key: string): Option[string] =
result = none[string]()
let (argKey, envKey, jsonKey) = keyNames(key)
if source == ValueProvenance.arguments and cfg.docopt.contains(argKey):
result = some($cfg.docopt[argKey])
elif source == ValueProvenance.environment and existsEnv(envKey):
result = some(getEnv(envKey))
elif source == ValueProvenance.json and cfg.json.hasKey(jsonKey):
result = some(jsonConfigNodeToString(cfg.json[jsonKey]))
proc getJsonValueAndProvenance*( proc getJsonValueAndProvenance*(
cfg: CombinedConfig, cfg: CombinedConfig,
key: string): tuple[value: JsonNode, provenance: ValueProvenance] key: string): tuple[value: JsonNode, provenance: ValueProvenance]
@@ -191,6 +207,21 @@ proc getJson*(
except CatchableError: return default except CatchableError: return default
proc getJsonFromSource*(
cfg: CombinedConfig,
source: ValueProvenance,
key: string): Option[JsonNode] =
result = none[JsonNode]()
let (argKey, envKey, jsonKey) = keyNames(key)
if source == ValueProvenance.arguments and cfg.docopt.contains(argKey):
result = some(parseJson($cfg.docopt[argKey]))
elif source == ValueProvenance.environment and existsEnv(envKey):
result = some(parseJson(getEnv(envKey)))
elif source == ValueProvenance.json and cfg.json.hasKey(jsonKey):
result = some(cfg.json[jsonKey])
proc hasKey*(cfg: CombinedConfig, key: string): bool = proc hasKey*(cfg: CombinedConfig, key: string): bool =
let (argKey, envKey, jsonKey) = keyNames(key) let (argKey, envKey, jsonKey) = keyNames(key)