* better docs and tests
* a bit better only clean trailing whitespace
This commit is contained in:
flywind 2020-12-06 16:50:46 +08:00 • committed by GitHub
commit 48d7c40553
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 141 additions and 18 deletions

View file

@ -107,6 +107,70 @@
## var dict = loadConfig("config.ini") ## var dict = loadConfig("config.ini")
## dict.delSectionKey("Author","email") ## dict.delSectionKey("Author","email")
## dict.writeConfig("config.ini") ## dict.writeConfig("config.ini")
##
## Supported INI File structure
## ----------------------------
## The examples below are supported:
##
# taken from https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
runnableExamples:
import streams
var dict = loadConfig(newStringStream("""[Simple Values]
key=value
spaces in keys=allowed
spaces in values=allowed as well
spaces around the delimiter = obviously
you can also use : to delimit keys from values
[All Values Are Strings]
values like this: 19990429
or this: 3.14159265359
are they treated as numbers : no
integers floats and booleans are held as: strings
can use the API to get converted values directly: true
[No Values]
key_without_value
# empty string value is not allowed =
[ Seletion A ]
space around section name will be ignored
[You can use comments]
# like this
; or this
# By default only in an empty line.
# Inline comments can be harmful because they prevent users
# from using the delimiting characters as parts of values.
# That being said, this can be customized.
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
# Did I mention we can indent comments, too?
""")
)
let section1 = "Simple Values"
doAssert dict.getSectionValue(section1, "key") == "value"
doAssert dict.getSectionValue(section1, "spaces in keys") == "allowed"
doAssert dict.getSectionValue(section1, "spaces in values") == "allowed as well"
doAssert dict.getSectionValue(section1, "spaces around the delimiter") == "obviously"
doAssert dict.getSectionValue(section1, "you can also use") == "to delimit keys from values"
let section2 = "All Values Are Strings"
doAssert dict.getSectionValue(section2, "values like this") == "19990429"
doAssert dict.getSectionValue(section2, "or this") == "3.14159265359"
doAssert dict.getSectionValue(section2, "are they treated as numbers") == "no"
doAssert dict.getSectionValue(section2, "integers floats and booleans are held as") == "strings"
doAssert dict.getSectionValue(section2, "can use the API to get converted values directly") == "true"
let section3 = "Seletion A"
doAssert dict.getSectionValue(section3,
"space around section name will be ignored", "not an empty value") == ""
let section4 = "Sections Can Be Indented"
doAssert dict.getSectionValue(section4, "can_values_be_as_well") == "True"
doAssert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False"
doAssert dict.getSectionValue(section4, "purpose") == "formatting for readability"
import import
strutils, lexbase, streams, tables strutils, lexbase, streams, tables
@ -151,7 +215,7 @@ type
# implementation # implementation
const const
SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', '/', '\\', '-'} SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', ' ', '\x80'..'\xFF', '.', '/', '\\', '-'}
proc rawGetTok(c: var CfgParser, tok: var Token) {.gcsafe.} proc rawGetTok(c: var CfgParser, tok: var Token) {.gcsafe.}
@ -306,6 +370,10 @@ proc getSymbol(c: var CfgParser, tok: var Token) =
add(tok.literal, c.buf[pos]) add(tok.literal, c.buf[pos])
inc(pos) inc(pos)
if not (c.buf[pos] in SymChars): break if not (c.buf[pos] in SymChars): break
while tok.literal.len > 0 and tok.literal[^1] == ' ':
tok.literal.setLen(tok.literal.len - 1)
c.bufpos = pos c.bufpos = pos
tok.kind = tkSymbol tok.kind = tkSymbol

View file

@ -5,14 +5,14 @@ discard """
import parsecfg, streams import parsecfg, streams
when not defined(js): when not defined(js):
from stdtest/specialpaths import buildDir
import os
# bug #6046 # bug #6046
block:
var config = newConfig() var config = newConfig()
config.setSectionKey("foo", "bar", "-1") config.setSectionKey("foo", "bar", "-1")
config.setSectionKey("foo", "foo", "abc") config.setSectionKey("foo", "foo", "abc")
from stdtest/specialpaths import buildDir
import os
const file = buildDir / "tparsecfg.ini" const file = buildDir / "tparsecfg.ini"
config.writeConfig(file) config.writeConfig(file)
@ -27,7 +27,6 @@ when not defined(js):
assert(bar == "-1") assert(bar == "-1")
assert(foo == "abc") assert(foo == "abc")
## Creating a configuration file. ## Creating a configuration file.
var dict1 = newConfig() var dict1 = newConfig()
dict1.setSectionKey("", "charset", "utf-8") dict1.setSectionKey("", "charset", "utf-8")
@ -78,3 +77,59 @@ name=hello
name=lihf8515 name=lihf8515
qq=10214028 qq=10214028
""" """
block:
var dict = loadConfig(newStringStream("""[Simple Values]
key=value
spaces in keys=allowed
spaces in values=allowed as well
spaces around the delimiter = obviously
you can also use : to delimit keys from values
[All Values Are Strings]
values like this: 19990429
or this: 3.14159265359
are they treated as numbers : no
integers floats and booleans are held as: strings
can use the API to get converted values directly: true
[No Values]
key_without_value
# empty string value is not allowed =
[ Seletion A ]
space around section name will be ignored
[You can use comments]
# like this
; or this
# By default only in an empty line.
# Inline comments can be harmful because they prevent users
# from using the delimiting characters as parts of values.
# That being said, this can be customized.
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
# Did I mention we can indent comments, too?
""")
)
let section1 = "Simple Values"
doAssert dict.getSectionValue(section1, "key") == "value"
doAssert dict.getSectionValue(section1, "spaces in keys") == "allowed"
doAssert dict.getSectionValue(section1, "spaces in values") == "allowed as well"
doAssert dict.getSectionValue(section1, "spaces around the delimiter") == "obviously"
doAssert dict.getSectionValue(section1, "you can also use") == "to delimit keys from values"
let section2 = "All Values Are Strings"
doAssert dict.getSectionValue(section2, "values like this") == "19990429"
doAssert dict.getSectionValue(section2, "or this") == "3.14159265359"
doAssert dict.getSectionValue(section2, "are they treated as numbers") == "no"
doAssert dict.getSectionValue(section2, "integers floats and booleans are held as") == "strings"
doAssert dict.getSectionValue(section2, "can use the API to get converted values directly") == "true"
let section3 = "Seletion A"
doAssert dict.getSectionValue(section3,
"space around section name will be ignored", "not an empty value") == ""
let section4 = "Sections Can Be Indented"
doAssert dict.getSectionValue(section4, "can_values_be_as_well") == "True"
doAssert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False"
doAssert dict.getSectionValue(section4, "purpose") == "formatting for readability"