The parsecfg
module implements a high performance configuration file parser. The configuration file's syntax is similar to the Windows .ini
format, but much more powerful, as it is not a line based parser. String literals, raw string literals and triple quoted string literals are supported as in the Nim programming language.This is an example of how a configuration file may look like:
# This is a comment. ; this too. [Common] cc=gcc # '=' and ':' are the same --verbose [Windows] isConsoleApplication=False ; another comment [Posix] isConsoleApplication=True key1: "in this string backslash escapes are interpreted\n" key2: r"in this string not" key3: """triple quotes strings are also supported. They may span multiple lines.""" --"long option with spaces": r"c:\myfiles\test.txt"
The file examples/parsecfgex.nim
demonstrates how to use the configuration file parser:
import os, parsecfg, strutils, streams var f = newFileStream(paramStr(1), fmRead) if f != nil: var p: CfgParser open(p, f, paramStr(1)) while true: var e = next(p) case e.kind of cfgEof: echo("EOF!") break of cfgSectionStart: ## a ``[section]`` has been parsed echo("new section: " & e.section) of cfgKeyValuePair: echo("key-value-pair: " & e.key & ": " & e.value) of cfgOption: echo("command: " & e.key & ": " & e.value) of cfgError: echo(e.msg) close(p) else: echo("cannot open: " & paramStr(1))
This is an example of a configuration file.
charset = "utf-8" [Package] name = "hello" --threads:on [Author] name = "lihf8515" qq = "10214028" email = "[email protected]"
import parsecfg var dict=newConfig() dict.setSectionKey("","charset","utf-8") dict.setSectionKey("Package","name","hello") dict.setSectionKey("Package","--threads","on") dict.setSectionKey("Author","name","lihf8515") dict.setSectionKey("Author","qq","10214028") dict.setSectionKey("Author","email","[email protected]") dict.writeConfig("config.ini")
import parsecfg var dict = loadConfig("config.ini") var charset = dict.getSectionValue("","charset") var threads = dict.getSectionValue("Package","--threads") var pname = dict.getSectionValue("Package","name") var name = dict.getSectionValue("Author","name") var qq = dict.getSectionValue("Author","qq") var email = dict.getSectionValue("Author","email") echo pname & "\n" & name & "\n" & qq & "\n" & email
import parsecfg var dict = loadConfig("config.ini") dict.setSectionKey("Author","name","lhf") dict.writeConfig("config.ini")
import parsecfg var dict = loadConfig("config.ini") dict.delSectionKey("Author","email") dict.writeConfig("config.ini")
CfgEventKind = enum cfgEof, ## end of file reached cfgSectionStart, ## a ``[section]`` has been parsed cfgKeyValuePair, ## a ``key=value`` pair has been detected cfgOption, ## a ``--key=value`` command line option cfgError ## an error occurred during parsing
CfgEvent = object of RootObj case kind*: CfgEventKind ## the kind of the event of cfgEof: nil of cfgSectionStart: section*: string ## `section` contains the name of the ## parsed section start (syntax: ``[section]``) of cfgKeyValuePair, cfgOption: key*, value*: string ## contains the (key, value) pair if an option ## of the form ``--key: value`` or an ordinary ## ``key= value`` pair has been parsed. ## ``value==""`` if it was not specified in the ## configuration file. of cfgError: ## the parser encountered an error: `msg` msg*: string ## contains the error message. No exceptions ## are thrown if a parse error occurs.
CfgParser = object of BaseLexer tok: Token filename: string
Config = OrderedTableRef[string, OrderedTableRef[string, string]]
proc open(c: var CfgParser; input: Stream; filename: string; lineOffset = 0) {.gcsafe, extern: "npc$1", raises: [Exception], tags: [ReadIOEffect, RootEffect].}
proc close(c: var CfgParser) {.gcsafe, extern: "npc$1", raises: [Exception], tags: [].}
proc getColumn(c: CfgParser): int {.gcsafe, extern: "npc$1", raises: [], tags: [].}
proc getLine(c: CfgParser): int {.gcsafe, extern: "npc$1", raises: [], tags: [].}
proc getFilename(c: CfgParser): string {.gcsafe, extern: "npc$1", raises: [], tags: [].}
proc errorStr(c: CfgParser; msg: string): string {.gcsafe, extern: "npc$1", raises: [ValueError], tags: [].}
proc warningStr(c: CfgParser; msg: string): string {.gcsafe, extern: "npc$1", raises: [ValueError], tags: [].}
proc ignoreMsg(c: CfgParser; e: CfgEvent): string {.gcsafe, extern: "npc$1", raises: [ValueError], tags: [].}
proc next(c: var CfgParser): CfgEvent {.gcsafe, extern: "npc$1", raises: [Exception, ValueError], tags: [ReadIOEffect].}
proc newConfig(): Config {.raises: [], tags: [].}
proc loadConfig(stream: Stream; filename: string = "[stream]"): Config {. raises: [Exception, ValueError, KeyError], tags: [ReadIOEffect, RootEffect].}
proc loadConfig(filename: string): Config {.raises: [Exception, IOError, Exception, ValueError, KeyError], tags: [ReadIOEffect, RootEffect].}
proc writeConfig(dict: Config; stream: Stream) {.raises: [Exception], tags: [WriteIOEffect].}
Writes the contents of the table to the specified stream
Note: Comment statement will be ignored.
proc `$`(dict: Config): string {.raises: [Exception], tags: [WriteIOEffect].}
proc writeConfig(dict: Config; filename: string) {. raises: [Exception, IOError, Exception], tags: [WriteIOEffect].}
proc getSectionValue(dict: Config; section, key: string): string {.raises: [KeyError], tags: [].}
proc setSectionKey(dict: var Config; section, key, value: string) {.raises: [KeyError], tags: [].}
proc delSection(dict: var Config; section: string) {.raises: [], tags: [].}
proc delSectionKey(dict: var Config; section, key: string) {.raises: [KeyError], tags: [].}
© 2006–2017 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/parsecfg.html