# parsecfg

- Manual
- Standard library
- Index

Search:
Group by:

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.

Example of how a configuration file may look like:

    # This is a comment.
    ; this too.

    [Common]
    cc=gcc     # '=' and ':' are the same
    --foo="bar"   # '--cc' and 'cc' are the same, 'bar' and '"bar"' 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"

Here is an example of 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: 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))

# Examples

## Configuration file example

    charset = "utf-8"
    [Package]
    name = "hello"
    --threads:on
    [Author]
    name = "lihf8515"
    qq = "10214028"
    email = "lihaifeng@wxm.com"

## Creating a configuration file

    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","lihaifeng@wxm.com")
    dict.writeConfig("config.ini")

## Reading a configuration file

    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

## Modifying a configuration file

    import parsecfg
    var dict = loadConfig("config.ini")
    dict.setSectionKey("Author","name","lhf")
    dict.writeConfig("config.ini")

## Deleting a section key in a configuration file

    import parsecfg
    var dict = loadConfig("config.ini")
    dict.delSectionKey("Author","email")
    dict.writeConfig("config.ini")

# Imports

strutils, lexbase, streams, tables

# Types

    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

  enumeration of all events that may occur when parsing Source Edit

    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.

  describes a parsing event Source Edit

    CfgParser = object of BaseLexer
      tok: Token
      filename: string

  the parser object. Source Edit

    Config = OrderedTableRef[string, OrderedTableRef[string, string]]

  Source Edit

# Procs

    proc open(c: var CfgParser; input: Stream; filename: string; lineOffset = 0) {...}{.gcsafe,
        extern: "npc$1", raises: [Defect, IOError, OSError, Exception],
        tags: [ReadIOEffect, RootEffect].}

  initializes the parser with an input stream. `Filename` is only used for nice error messages. `lineOffset` can be used to influence the line number information in the generated error messages. Source Edit

    proc close(c: var CfgParser) {...}{.gcsafe, extern: "npc$1",
                               raises: [Exception, IOError, OSError],
                               tags: [WriteIOEffect].}

  closes the parser `c` and its associated input stream. Source Edit

    proc getColumn(c: CfgParser): int {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}

  get the current column the parser has arrived at. Source Edit

    proc getLine(c: CfgParser): int {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}

  get the current line the parser has arrived at. Source Edit

    proc getFilename(c: CfgParser): string {...}{.gcsafe, extern: "npc$1", raises: [], tags: [].}

  get the filename of the file that the parser processes. Source Edit

    proc errorStr(c: CfgParser; msg: string): string {...}{.gcsafe, extern: "npc$1",
        raises: [ValueError], tags: [].}

  returns a properly formatted error message containing current line and column information. Source Edit

    proc warningStr(c: CfgParser; msg: string): string {...}{.gcsafe, extern: "npc$1",
        raises: [ValueError], tags: [].}

  returns a properly formatted warning message containing current line and column information. Source Edit

    proc ignoreMsg(c: CfgParser; e: CfgEvent): string {...}{.gcsafe, extern: "npc$1",
        raises: [ValueError], tags: [].}

  returns a properly formatted warning message containing that an entry is ignored. Source Edit

    proc next(c: var CfgParser): CfgEvent {...}{.gcsafe, extern: "npc$1", raises: [Defect, IOError,
        OSError, ValueError], tags: [ReadIOEffect].}

  retrieves the first/next event. This controls the parser. Source Edit

    proc newConfig(): Config {...}{.raises: [], tags: [].}

  Create a new configuration table. Useful when wanting to create a configuration file. Source Edit

    proc loadConfig(stream: Stream; filename: string = "[stream]"): Config {...}{.
        raises: [Defect, IOError, OSError, Exception, ValueError, KeyError],
        tags: [ReadIOEffect, RootEffect, WriteIOEffect].}

  Load the specified configuration from stream into a new Config instance. `filename` parameter is only used for nicer error messages. Source Edit

    proc loadConfig(filename: string): Config {...}{.raises: [IOError, Exception, OSError,
        Defect, ValueError, KeyError], tags: [WriteIOEffect, ReadIOEffect, RootEffect].}

  Load the specified configuration file into a new Config instance. Source Edit

    proc writeConfig(dict: Config; stream: Stream) {...}{.raises: [Defect, IOError, OSError],
        tags: [WriteIOEffect].}

  Writes the contents of the table to the specified stream

  Note: Comment statement will be ignored.

  Source Edit

    proc `$`(dict: Config): string {...}{.raises: [Exception, IOError, OSError, Defect],
                                 tags: [WriteIOEffect].}

  Writes the contents of the table to string. Note: Comment statement will be ignored. Source Edit

    proc writeConfig(dict: Config; filename: string) {...}{.
        raises: [IOError, Defect, OSError], tags: [WriteIOEffect].}

  Writes the contents of the table to the specified configuration file. Note: Comment statement will be ignored. Source Edit

    proc getSectionValue(dict: Config; section, key: string): string {...}{.raises: [KeyError],
        tags: [].}

  Gets the Key value of the specified Section, returns an empty string if the key does not exist. Source Edit

    proc setSectionKey(dict: var Config; section, key, value: string) {...}{.raises: [KeyError],
        tags: [].}

  Sets the Key value of the specified Section. Source Edit

    proc delSection(dict: var Config; section: string) {...}{.raises: [], tags: [].}

  Deletes the specified section and all of its sub keys. Source Edit

    proc delSectionKey(dict: var Config; section, key: string) {...}{.raises: [KeyError], tags: [].}

  Delete the key of the specified section. Source Edit