std/parsecfg
SourceEditМодуль parsecfg реализует высокопроизводительный парсер конфигурационных файлов. Синтаксис конфигурационного файла аналогичен формату Windows .ini, но намного мощнее, поскольку это не построчный парсер. Строковые литералы, необработанные строковые литералы и строковые литералы в тройных кавычках поддерживаются так же, как и в языке программирования Nim.
Пример того, как может выглядеть конфигурационный файл:
# 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 (except for '#') macrosym: "#" # Note that '#' is interpreted as a comment without the quotation --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"
Вот пример использования парсера конфигурационных файлов:
Пример: cmd: -r:off
import std/parsecfg
import std/[strutils, streams]
let configFile = "example.ini"
var f = newFileStream(configFile, fmRead)
assert f != nil, "cannot open " & configFile
var p: CfgParser
open(p, f, configFile)
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) Пример конфигурационного файла
charset = "utf-8" [Package] name = "hello" --threads:on [Author] name = "nim-lang" website = "nim-lang.org"
Создание конфигурационного файла
Пример:
import std/parsecfg
var dict = newConfig()
dict.setSectionKey("","charset", "utf-8")
dict.setSectionKey("Package", "name", "hello")
dict.setSectionKey("Package", "--threads", "on")
dict.setSectionKey("Author", "name", "nim-lang")
dict.setSectionKey("Author", "website", "nim-lang.org")
assert $dict == """
charset=utf-8
[Package]
name=hello
--threads:on
[Author]
name=nim-lang
website=nim-lang.org
""" Чтение конфигурационного файла
Пример: cmd: -r:off
import std/parsecfg
let dict = loadConfig("config.ini")
let charset = dict.getSectionValue("","charset")
let threads = dict.getSectionValue("Package","--threads")
let pname = dict.getSectionValue("Package","name")
let name = dict.getSectionValue("Author","name")
let website = dict.getSectionValue("Author","website")
echo pname & "\n" & name & "\n" & website Изменение конфигурационного файла
Пример: cmd: -r:off
import std/parsecfg
var dict = loadConfig("config.ini")
dict.setSectionKey("Author", "name", "nim-lang")
dict.writeConfig("config.ini") Удаление ключа раздела в конфигурационном файле
Пример: cmd: -r:off
import std/parsecfg
var dict = loadConfig("config.ini")
dict.delSectionKey("Author", "website")
dict.writeConfig("config.ini") Поддерживаемая структура INI-файла
Пример:
import std/parsecfg
import std/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"
assert dict.getSectionValue(section1, "key") == "value"
assert dict.getSectionValue(section1, "spaces in keys") == "allowed"
assert dict.getSectionValue(section1, "spaces in values") == "allowed as well"
assert dict.getSectionValue(section1, "spaces around the delimiter") == "obviously"
assert dict.getSectionValue(section1, "you can also use") == "to delimit keys from values"
let section2 = "All Values Are Strings"
assert dict.getSectionValue(section2, "values like this") == "19990429"
assert dict.getSectionValue(section2, "or this") == "3.14159265359"
assert dict.getSectionValue(section2, "are they treated as numbers") == "no"
assert dict.getSectionValue(section2, "integers floats and booleans are held as") == "strings"
assert dict.getSectionValue(section2, "can use the API to get converted values directly") == "true"
let section3 = "Seletion A"
assert dict.getSectionValue(section3,
"space around section name will be ignored", "not an empty value") == ""
let section4 = "Sections Can Be Indented"
assert dict.getSectionValue(section4, "can_values_be_as_well") == "True"
assert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False"
assert dict.getSectionValue(section4, "purpose") == "formatting for readability" Импорты
- strutils, lexbase, streams, tables, decode_helpers, since
Типы
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.- описывает событие анализа Source Edit
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
- перечисление всех событий, которые могут произойти при разборе Source Edit
Процедуры
proc loadConfig(filename: string): Config {. ...raises: [IOError, OSError, Exception, ValueError, KeyError], tags: [WriteIOEffect, ReadIOEffect, RootEffect], forbids: [].}- Загружает указанный конфигурационный файл в новый экземпляр Config. Source Edit
proc loadConfig(stream: Stream; filename: string = "[stream]"): Config {. ...raises: [IOError, OSError, Exception, ValueError, KeyError], tags: [ReadIOEffect, RootEffect, WriteIOEffect], forbids: [].}- Загружает указанную конфигурацию из потока в новый экземпляр Config. Параметр
filenameиспользуется только для более удобных сообщений об ошибках. Source Edit proc open(c: var CfgParser; input: Stream; filename: string; lineOffset = 0) {. ...gcsafe, extern: "npc$1", raises: [IOError, OSError, Exception], tags: [ReadIOEffect, RootEffect], forbids: [].}- Инициализирует парсер входным потоком.
Filenameиспользуется только для удобных сообщений об ошибках.lineOffsetможно использовать для влияния на информацию о номере строки в генерируемых сообщениях об ошибках. Source Edit
Итераторы
END_OF_DOCUMENT_MARKERiterator sections(dict: Config): lent string {....raises: [], tags: [], forbids: [].}- Перебирает секции в
dict. Исходный код Редактировать
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/parsecfg.html