about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2025-05-11 16:58:26 +0200
committerbptato <nincsnevem662@gmail.com>2025-05-11 16:58:26 +0200
commit74d5d94c81bac328bb2aad6ee3514f56a059a90e (patch)
tree0cf90f8bce91b0be10a5fa13aab4b3d60d6f4221 /src
parent7c5323086f2b332a2f0afe44d69a4fb773dfd333 (diff)
downloadchawan-74d5d94c81bac328bb2aad6ee3514f56a059a90e.tar.gz
config: warn on unused values
Diffstat (limited to 'src')
-rw-r--r--src/config/config.nim55
-rw-r--r--src/config/toml.nim11
2 files changed, 31 insertions, 35 deletions
diff --git a/src/config/config.nim b/src/config/config.nim
index 5627cdd0..ef138ca5 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -399,20 +399,25 @@ proc typeCheck(v: TomlValue; t: set[TomlValueType]; k: string): Err[string] =
     return err(k & ": invalid type (got " & $v.t & ", expected " & $t & ")")
   ok()
 
+proc warnValuesLeft(ctx: var ConfigParser; v: TomlValue; k: string) =
+  for fk in v.keys:
+    let kk = if k != "": k & '.' & fk else: fk
+    ctx.warnings.add("unrecognized option " & kk)
+
 proc parseConfigValue(ctx: var ConfigParser; x: var object; v: TomlValue;
     k: string): Err[string] =
   ?typeCheck(v, tvtTable, k)
   if v.tab.clear:
     x = default(typeof(x))
+  when x isnot typeof(Config()[]):
+    let k = k & '.'
   for fk, fv in x.fieldPairs:
     when fk notin ["jsvfns", "arraySeen", "dir"]:
-      let kebabk = camelToKebabCase(fk)
-      if kebabk in v:
-        let kkk = if k != "":
-          k & "." & fk
-        else:
-          fk
-        ?ctx.parseConfigValue(fv, v[kebabk], kkk)
+      const kebabk = camelToKebabCase(fk)
+      var x: TomlValue
+      if v.pop(kebabk, x):
+        ?ctx.parseConfigValue(fv, x, k & kebabk)
+  ctx.warnValuesLeft(v, k)
   ok()
 
 proc parseConfigValue(ctx: var ConfigParser; x: var ref object; v: TomlValue;
@@ -444,13 +449,9 @@ proc parseConfigValue[U, V](ctx: var ConfigParser; x: var OrderedTable[U, V];
 
 proc parseConfigValue[U, V](ctx: var ConfigParser; x: var TableRef[U, V];
     v: TomlValue; k: string): Err[string] =
-  ?typeCheck(v, tvtTable, k)
-  if v.tab.clear or x == nil:
+  if x == nil:
     x = TableRef[U, V]()
-  for kk, vv in v:
-    let kkk = k & "[" & kk & "]"
-    ?ctx.parseConfigValue(x.mgetOrPut(kk, default(V)), vv, kkk)
-  ok()
+  ctx.parseConfigValue(x[], v, k)
 
 proc parseConfigValue(ctx: var ConfigParser; x: var bool; v: TomlValue;
     k: string): Err[string] =
@@ -608,24 +609,18 @@ proc parseConfigValue(ctx: var ConfigParser; x: var CSSConfig; v: TomlValue;
     k: string): Err[string] =
   ?typeCheck(v, tvtTable, k)
   ctx.warnings.add("[css] is deprecated; use buffer.user-style instead")
-  for kk, vv in v:
-    let kkk = if k != "":
-      k & "." & kk
-    else:
-      kk
-    case kk
-    of "include":
-      ?typeCheck(vv, {tvtString, tvtArray}, kkk)
-      case vv.t
-      of tvtString:
+  var vv: TomlValue
+  if v.pop("include", vv):
+    ?typeCheck(vv, {tvtString, tvtArray}, k & ".include")
+    if vv.t == tvtString:
+      ?x.stylesheet.readUserStylesheet(ctx.dir, vv.s)
+    else: # array
+      for child in vv.a:
         ?x.stylesheet.readUserStylesheet(ctx.dir, vv.s)
-      of tvtArray:
-        for child in vv.a:
-          ?x.stylesheet.readUserStylesheet(ctx.dir, vv.s)
-      else: discard
-    of "inline":
-      ?typeCheck(vv, tvtString, kkk)
-      x.stylesheet &= vv.s
+  if v.pop("inline", vv):
+    ?typeCheck(vv, tvtString, k & ".inline")
+    x.stylesheet &= vv.s
+  ctx.warnValuesLeft(v, k)
   ok()
 
 proc parseConfigValue(ctx: var ConfigParser; x: var Regex; v: TomlValue;
diff --git a/src/config/toml.nim b/src/config/toml.nim
index 1866a036..66a59120 100644
--- a/src/config/toml.nim
+++ b/src/config/toml.nim
@@ -121,16 +121,17 @@ func `$`*(val: TomlValue): string =
       result &= $it
     result &= ']'
 
-func `[]`*(val: TomlValue; key: string): TomlValue =
-  return val.tab.map[key]
+template pop*(val: TomlValue; key: string; x: typed): bool =
+  val.tab.map.pop(key, x)
+
+iterator keys*(val: TomlValue): string {.inline.} =
+  for k in val.tab.map.keys:
+    yield k
 
 iterator pairs*(val: TomlValue): (string, TomlValue) {.inline.} =
   for k, v in val.tab.map:
     yield (k, v)
 
-func contains*(val: TomlValue; key: string): bool =
-  return key in val.tab.map
-
 const ValidBare = AsciiAlphaNumeric + {'-', '_'}
 
 func peek(state: TomlParser; buf: openArray[char]; i: int): char =