about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-20 15:18:23 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-20 15:18:23 +0200
commit29802269045c5eeb137a85d067120c5c6c7a6ed2 (patch)
tree2b85d357ab395292177f3f5e131b0f23803816ab
parent38ada8121ea2a76720bb7188940d1d9d4b0a1c1d (diff)
downloadchawan-29802269045c5eeb137a85d067120c5c6c7a6ed2.tar.gz
Accept bare strings in -o, fix -o with missing newline
* Bare strings are now allowed when specifying config options
  through -o.
* Fix a bug where options specified with -o would be disregarded
  unless a newline was included.
* (Also, add a TOML stringifier routine for debugging.)
-rw-r--r--src/config/config.nim24
-rw-r--r--src/config/toml.nim70
-rw-r--r--src/main.nim2
3 files changed, 81 insertions, 15 deletions
diff --git a/src/config/config.nim b/src/config/config.nim
index 35490638..21a38811 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -366,8 +366,10 @@ proc getMimeTypes*(config: Config): MimeTypes =
     return DefaultGuess
   return mimeTypes
 
-proc parseConfig(config: Config, dir: string, stream: Stream, name = "<input>")
-proc parseConfig*(config: Config, dir: string, s: string, name = "<input>")
+proc parseConfig(config: Config, dir: string, stream: Stream, name = "<input>",
+  laxnames = false)
+proc parseConfig*(config: Config, dir: string, s: string, name = "<input>",
+  laxnames = false)
 
 proc loadConfig*(config: Config, s: string) {.jsfunc.} =
   let s = if s.len > 0 and s[0] == '/':
@@ -572,17 +574,23 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
   config.configdir = dir
   #TODO: for omnirule/siteconf, check if substitution rules are specified?
 
-proc parseConfig(config: Config, dir: string, stream: Stream, name = "<input>") =
-  let toml = parseToml(stream, dir / name)
+proc parseConfig(config: Config, dir: string, stream: Stream, name = "<input>",
+    laxnames = false) =
+  let toml = parseToml(stream, dir / name, laxnames)
   if toml.isOk:
     config.parseConfig(dir, toml.get)
   else:
-    eprint("Fatal error: Failed to parse config\n")
-    eprint(toml.error & "\n")
+    when nimvm:
+      echo "Fatal error: Failed to parse config"
+      echo toml.error
+    else:
+      stderr.write("Fatal error: Failed to parse config")
+      stderr.write(toml.error & '\n')
     quit(1)
 
-proc parseConfig*(config: Config, dir: string, s: string, name = "<input>") =
-  config.parseConfig(dir, newStringStream(s), name)
+proc parseConfig*(config: Config, dir: string, s: string, name = "<input>",
+    laxnames = false) =
+  config.parseConfig(dir, newStringStream(s), name, laxnames)
 
 proc staticReadConfig(): ConfigObj =
   var config = new(Config)
diff --git a/src/config/toml.nim b/src/config/toml.nim
index 8e514438..703d7ae5 100644
--- a/src/config/toml.nim
+++ b/src/config/toml.nim
@@ -30,6 +30,7 @@ type
     node: TomlNode
     currkey: seq[string]
     tarray: bool
+    laxnames: bool
 
   TomlValue* = ref object
     case vt*: ValueType
@@ -61,6 +62,57 @@ type
     nodes: seq[TomlNode]
     map: Table[string, TomlValue]
 
+func `$`*(val: TomlValue): string
+
+func `$`(tab: TomlTable): string
+
+func `$`(kvpair: TomlKVPair): string =
+  if kvpair.key.len > 0:
+    #TODO escape
+    result = kvpair.key[0]
+    for i in 1 ..< kvpair.key.len:
+      result &= '.'
+      result &= kvpair.key[i]
+  else:
+    result = "\"\""
+  result &= " = "
+  result &= $kvpair.value
+  result &= '\n'
+
+func `$`(tab: TomlTable): string =
+  if tab.comment != "":
+    result &= "#" & tab.comment & '\n'
+  for key, val in tab.map:
+    result &= key & " = " & $val & '\n'
+  result &= '\n'
+
+func `$`*(val: TomlValue): string =
+  case val.vt
+  of VALUE_STRING:
+    result = "\""
+    for c in val.s:
+      if c == '"':
+        result &= '\\'
+      result &= c
+    result &= '"'
+  of VALUE_INTEGER:
+    result = $val.i
+  of VALUE_FLOAT:
+    result = $val.f
+  of VALUE_BOOLEAN:
+    result = $val.b
+  of VALUE_TABLE:
+    result = $val.t
+  of VALUE_DATE_TIME:
+    result = $val.dt
+  of VALUE_ARRAY:
+    #TODO if ad table array probably
+    result = "["
+    for it in val.a:
+      result &= $it
+      result &= ','
+    result &= ']'
+
 func `[]`*(val: TomlValue, key: string): TomlValue =
   return val.t.map[key]
 
@@ -526,18 +578,23 @@ proc consumeValue(state: var TomlParser): TomlResult =
         return ok(TomlValue(vt: VALUE_BOOLEAN, b: true))
       elif s == "false":
         return ok(TomlValue(vt: VALUE_BOOLEAN, b: false))
+      elif state.laxnames:
+        return ok(TomlValue(vt: VALUE_STRING, s: s))
       else:
         return state.err("invalid token: " & s)
     else:
       return state.err("invalid character in value: " & c)
   return state.err("unexpected end of file")
 
-proc parseToml*(inputStream: Stream, filename = "<input>"): TomlResult =
-  var state: TomlParser
-  state.buf = inputStream.readAll()
-  state.line = 1
-  state.root = TomlTable()
-  state.filename = filename
+proc parseToml*(inputStream: Stream, filename = "<input>", laxnames = false):
+    TomlResult =
+  var state = TomlParser(
+    buf: inputStream.readAll(),
+    line: 1,
+    root: TomlTable(),
+    filename: filename,
+    laxnames: laxnames
+  )
   while state.has():
     if ?state.consumeNoState():
       # state.node has been set to a KV pair, so now we parse its value.
@@ -553,5 +610,6 @@ proc parseToml*(inputStream: Stream, filename = "<input>"): TomlResult =
         state.consumeComment()
       of '\t', ' ': discard
       else: return state.err("invalid character after value: " & c)
+  ?state.flushLine()
   inputStream.close()
   return ok(TomlValue(vt: VALUE_TABLE, t: state.root))
diff --git a/src/main.nim b/src/main.nim
index 16a1a73e..ef8bdbbb 100644
--- a/src/main.nim
+++ b/src/main.nim
@@ -109,7 +109,7 @@ while i < params.len:
     conf.css.stylesheet &= getnext()
 
   proc popt() =
-    conf.parseConfig(getCurrentDir(), getnext())
+    conf.parseConfig(getCurrentDir(), getnext(), laxnames = true)
 
   proc phelp() =
     help(0)