updated docs

This commit is contained in:
Felix Krause 2020-06-26 22:36:52 +02:00
parent bce3981849
commit e4b3e8347a
4 changed files with 46 additions and 53 deletions

View File

@ -17,11 +17,11 @@
## available as source files for automatic testing. This way, we can make sure ## available as source files for automatic testing. This way, we can make sure
## that the code in the docs actually works. ## that the code in the docs actually works.
import parseopt2, streams, tables, strutils, os import parseopt2, streams, tables, strutils, os, options
var var
infile = "" infile = ""
path: string = nil path = none(string)
for kind, key, val in getopt(): for kind, key, val in getopt():
case kind case kind
of cmdArgument: of cmdArgument:
@ -36,7 +36,7 @@ for kind, key, val in getopt():
of cmdLongOption, cmdShortOption: of cmdLongOption, cmdShortOption:
case key case key
of "out", "o": of "out", "o":
if isNil(path): path = val if path.isNone: path = some(val)
else: else:
echo "Duplicate output path!" echo "Duplicate output path!"
quit 1 quit 1
@ -49,15 +49,15 @@ if infile == "":
echo "Missing input file!" echo "Missing input file!"
quit 1 quit 1
if isNil(path): if path.isNone:
for i in countdown(infile.len - 1, 0): for i in countdown(infile.len - 1, 0):
if infile[i] == '.': if infile[i] == '.':
if infile[i..^1] == ".rst": path = infile & ".rst" if infile[i..^1] == ".rst": path = some(infile & ".rst")
else: path = infile[0..i] & "rst" else: path = some(infile[0..i] & "rst")
break break
if isNil(path): path = infile & ".rst" if path.isNone: path = some(infile & ".rst")
var tmpOut = newFileStream(path, fmWrite) var tmpOut = newFileStream(path.get(), fmWrite)
proc append(s: string) = proc append(s: string) =
tmpOut.writeLine(s) tmpOut.writeLine(s)
@ -118,17 +118,17 @@ var lineNum = 0
for line in infile.lines(): for line in infile.lines():
if line.len > 0 and line[0] == '%': if line.len > 0 and line[0] == '%':
var var
srcPath: string = nil srcPath = none(string)
level = 0 level = 0
for i in 1..<line.len: for i in 1..<line.len:
if line[i] == '%': if line[i] == '%':
srcPath = line[1 .. i - 1] srcPath = some(line[1 .. i - 1])
level = parseInt(line[i + 1 .. ^1]) level = parseInt(line[i + 1 .. ^1])
break break
if isNil(srcPath): if srcPath.isNone:
echo "Second % missing in line " & $lineNum & "! content:\n" echo "Second % missing in line " & $lineNum & "! content:\n"
echo line echo line
quit 1 quit 1
outputExamples("snippets" / srcPath, level) outputExamples("snippets" / srcPath.get(), level)
else: else:
append(line) append(line)

View File

@ -72,28 +72,26 @@ supported.
To support new scalar types, you must implement the ``constructObject()`` and To support new scalar types, you must implement the ``constructObject()`` and
``representObject()`` procs on that type (see below). ``representObject()`` procs on that type (see below).
Collection Types Container Types
---------------- ---------------
NimYAML supports Nim's ``array``, ``set``, ``seq``, ``Table`` and NimYAML supports Nim's ``array``, ``set``, ``seq``, ``Table``, ``OrderedTable``
``OrderedTable`` types out of the box. Unlike the native YAML types ``!!seq`` and ``Option`` types out of the box. While YAML's standard types ``!!seq`` and
and ``!!map``, Nim's collection types define the type of all their contained ``!!map`` allow arbitrarily typed content, in Nim the contained type must be
items (or keys and values). So YAML objects with heterogeneous types in them known at compile time. Therefore, Nim cannot load ``!!seq`` and ``!!map``.
cannot be loaded to Nim collection types. For example, this sequence:
However, it doesn't need to. For example, if you have a YAML file like this:
.. code-block:: yaml .. code-block:: yaml
%YAML 1.2 %YAML 1.2
--- !!seq ---
- !!int 1 - 1
- !!string foo - 2
Cannot be loaded to a Nim ``seq``. For this reason, you cannot load YAML's You can simply load it into a `seq[int]`. If your YAML file contains differently
native ``!!map`` and ``!!seq`` types directly into Nim types. However, you can typed values in the same collection, you can use an implicit variant object, see
use variant object types to process heterogeneous value lists, see below. below.
Nim ``seq`` types may be ``nil``. This is handled by serializing them to an
empty scalar with the tag ``!nim:nil:seq``.
Reference Types Reference Types
--------------- ---------------
@ -182,7 +180,7 @@ list in order to load it:
type type
ContainerKind = enum ContainerKind = enum
ckInt, ckString, ckNone ckInt, ckString, ckNone
Container = object Container {.implicit.} = object
case kind: ContainerKind case kind: ContainerKind
of ckInt: of ckInt:
intVal: int intVal: int
@ -191,14 +189,12 @@ list in order to load it:
of ckNone: of ckNone:
discard discard
markAsImplicit(Container)
var var
list: seq[Container] list: seq[Container]
s = newFileStream("in.yaml") s = newFileStream("in.yaml")
load(s, list) load(s, list)
``markAsImplicit`` tells NimYAML that you want to use the type ``Container`` ``{.implicit.}`` tells NimYAML that you want to use the type ``Container``
implicitly, i.e. its fields are not visible in YAML, and are set dependent on implicitly, i.e. its fields are not visible in YAML, and are set dependent on
the value type that gets loaded into it. The type ``Container`` must fullfil the the value type that gets loaded into it. The type ``Container`` must fullfil the
following requirements: following requirements:
@ -251,11 +247,8 @@ for example use it on a certain ``seq`` type:
Customizing Field Handling Customizing Field Handling
========================== ==========================
NimYAML allows the user to specify special handling of certain object fields. NimYAML allows the user to specify special handling of certain object fields via
This configuration will be applied at compile time when NimYAML generates the annotation pragmas.
(de)serialization code for an object type. It is important that the
configuration happens before any YAML operations (e.g. ``load`` or ``dump``) are
executed on a variable of the object type.
Transient Fields Transient Fields
---------------- ----------------
@ -271,27 +264,23 @@ Example:
type MyObject: object type MyObject: object
storable: string storable: string
temporary: string temporary {.transient.}: string
markAsTransient(MyObject, temporary)
Default Values Default Values
-------------- --------------
When you load YAML that has been written by a human, you might want to allow the When you load YAML, you might want to allow for the omission certain fields,
user to omit certain fields, which should then be filled with a default value. which should then be filled with a default value. You can do that like this:
You can do that like this:
.. code-block:: nim .. code-block:: nim
type MyObject: object type MyObject: object
required: string required: string
optional: string optional {.defaultVal: "default value".}: string
setDefaultValue(MyObject, optional, "default value") Whenever a value of type ``MyObject`` now is loaded and the input stream does
not contain the field ``optional``, that field will be set to the value
Whenever ``MyObject`` now is loaded and the input stream does not contain the ``"default value"``.
field ``optional``, that field will be set to the value ``"default value"``.
Customize Serialization Customize Serialization
======================= =======================

View File

@ -126,6 +126,7 @@ doc.file = """
<li><a href="yaml.parser.html">yaml.parser</a></li> <li><a href="yaml.parser.html">yaml.parser</a></li>
<li><a href="yaml.presenter.html">yaml.presenter</a></li> <li><a href="yaml.presenter.html">yaml.presenter</a></li>
<li><a href="yaml.serialization.html">yaml.serialization</a></li> <li><a href="yaml.serialization.html">yaml.serialization</a></li>
<li><a href="yaml.annotations.html">yaml.annotations</a></li>
<li><a href="yaml.stream.html">yaml.stream</a></li> <li><a href="yaml.stream.html">yaml.stream</a></li>
<li><a href="yaml.taglib.html">yaml.taglib</a></li> <li><a href="yaml.taglib.html">yaml.taglib</a></li>
<li><a href="yaml.tojson.html">yaml.tojson</a></li> <li><a href="yaml.tojson.html">yaml.tojson</a></li>

View File

@ -13,7 +13,7 @@
template defaultVal*(value : typed) {.pragma.} template defaultVal*(value : typed) {.pragma.}
## This annotation can be assigned to an object field. During deserialization, ## This annotation can be assigned to an object field. During deserialization,
## if no value for this field is given, the `value` parameter of this ## if no value for this field is given, the ``value`` parameter of this
## annotation is used as value. ## annotation is used as value.
## ##
## Example usage: ## Example usage:
@ -24,7 +24,7 @@ template defaultVal*(value : typed) {.pragma.}
## c {.defaultVal: (1,2).}: tuple[x, y: int] ## c {.defaultVal: (1,2).}: tuple[x, y: int]
template transient*() {.pragma.} template transient*() {.pragma.}
## This annotation can be assigned to an object field. Any object field ## This annotation can be put on an object field. Any object field
## carrying this annotation will not be serialized to YAML and cannot be given ## carrying this annotation will not be serialized to YAML and cannot be given
## a value when deserializing. Giving a value for this field during ## a value when deserializing. Giving a value for this field during
## deserialization is an error. ## deserialization is an error.
@ -39,14 +39,17 @@ template transient*() {.pragma.}
## markAsTransient(MyObject, c) ## markAsTransient(MyObject, c)
template ignore*(keys : openarray[string]) {.pragma.} template ignore*(keys : openarray[string]) {.pragma.}
## This annotation can be assigned to an object type. All keys with the given ## This annotation can be put on an object type. All keys with the given
## names in the input YAML mapping will be ignored when deserializing a value ## names in the input YAML mapping will be ignored when deserializing a value
## of this type. This can be used to ignore parts of the YAML structure. ## of this type. This can be used to ignore parts of the YAML structure.
## ##
## You may use it with an empty list (``{.ignore: [].}``) to ignore *all*
## unknown keys.
##
## Example usage: ## Example usage:
## ##
## .. code-block:: ## .. code-block::
## type MyObject {.ignore("c").} = object ## type MyObject {.ignore: ["c"].} = object
## a, b: string ## a, b: string
template implicit*() {.pragma.} template implicit*() {.pragma.}