diff --git a/doc/doctrees/environment.pickle b/doc/doctrees/environment.pickle
index 9ea0e9f..e329ca1 100644
Binary files a/doc/doctrees/environment.pickle and b/doc/doctrees/environment.pickle differ
diff --git a/doc/doctrees/tutorials/custom_types.doctree b/doc/doctrees/tutorials/custom_types.doctree
index 4d8a875..5f0a456 100644
Binary files a/doc/doctrees/tutorials/custom_types.doctree and b/doc/doctrees/tutorials/custom_types.doctree differ
diff --git a/doc/doctrees/tutorials/getting_started.doctree b/doc/doctrees/tutorials/getting_started.doctree
index e213365..18d2b4c 100644
Binary files a/doc/doctrees/tutorials/getting_started.doctree and b/doc/doctrees/tutorials/getting_started.doctree differ
diff --git a/doc/html/_sources/tutorials/custom_types.txt b/doc/html/_sources/tutorials/custom_types.txt
index 1a22ebe..7137f07 100644
--- a/doc/html/_sources/tutorials/custom_types.txt
+++ b/doc/html/_sources/tutorials/custom_types.txt
@@ -17,11 +17,16 @@ It is also possible to implicitly resolve custom tags, as we will show later.
Constructor
-----------
-D:YAML uses the *Constructor* class to process each node to hold data type
-corresponding to its tag. *Constructor* stores a function for each supported
-tag to process it. These functions are supplied by the user using the
-*addConstructor()* method. *Constructor* is then passed to *Loader*, which
-parses YAML input.
+D:YAML uses the `Constructor <../api/dyaml.constructor.html>`_ class to process
+each node to hold data type corresponding to its tag. *Constructor* stores a
+function for each supported tag to process it. These functions are supplied by
+the user using the *addConstructor()* method. *Constructor* is then passed to
+*Loader*, which parses YAML input.
+
+Struct types have no specific requirements for YAML support. Class types should
+define the *opEquals()* operator, as this is used in equality comparisons of
+nodes. Default class *opEquals()* compares references, which means two identical
+objects might be considered unequal.
We will implement support for an RGB color type. It is implemented as the
following struct:
@@ -111,8 +116,8 @@ RRGGBB, or from a mapping, where we use the following format:
return Color(cast(ubyte)r, cast(ubyte)g, cast(ubyte)b);
}
-Next, we need some YAML data using our new tag. Create a file called input.yaml
-with the following contents:
+Next, we need some YAML data using our new tag. Create a file called
+``input.yaml`` with the following contents:
.. code-block:: yaml
@@ -167,7 +172,7 @@ Finally, the code to put it all together:
}
First, we create a *Constructor* and pass functions to handle the ``!color``
-and ``!color-mapping`` tag. We construct a *Loader*m and pass the *Constructor*
+and ``!color-mapping`` tag. We construct a *Loader* and pass the *Constructor*
to it. We then load the YAML document, and finally, read the colors using
*get()* method to test if they were loaded as expected.
@@ -181,12 +186,13 @@ Resolver
Specifying tag for every color value can be tedious. D:YAML can implicitly
resolve scalar tags using regular expressions. This is how default types such as
-int are resolved. We will use the *Resolver* class to add implicit tag
-resolution for the Color data type (in its scalar form).
+int are resolved. We will use the `Resolver <../api/dyaml.resolver.html>`_ class
+to add implicit tag resolution for the Color data type (in its scalar form).
-We use the *addImplicitResolver* method of *Resolver*, passing the tag, regular
-expression the value must match to resolve to this tag, and a string of possible
-starting characters of the value. Then we pass the *Resolver* to *Loader*.
+We use the *addImplicitResolver()* method of *Resolver*, passing the tag,
+regular expression the scalar must match to resolve to this tag, and a string of
+possible starting characters of the scalar. Then we pass the *Resolver* to
+*Loader*.
Note that resolvers added first override ones added later. If no resolver
matches a scalar, YAML string tag is used. Therefore our custom values must not
@@ -199,8 +205,8 @@ Add this to your code to add implicit resolution of ``!color``.
//code from the previous example...
auto resolver = new Resolver;
- resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}",
- "0123456789abcdefABCDEF"));
+ resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
+ "0123456789abcdefABCDEF");
auto loader = Loader("input.yaml");
@@ -209,7 +215,7 @@ Add this to your code to add implicit resolution of ``!color``.
//code from the previous example...
-Now, change contents of input.yaml to this:
+Now, change contents of ``input.yaml`` to this:
.. code-block:: yaml
@@ -227,3 +233,107 @@ the example. If everything went as expected, it should report success.
You can find the complete code in the ``examples/resolver`` directory in the
D:YAML package.
+
+
+-----------
+Representer
+-----------
+
+Now that you know how to load custom data types, it might also be useful to know
+how to dump them. D:YAML uses the `Representer <../api/dyaml.representer.html>`_
+class for this purpose.
+
+*Representer* processes YAML nodes into plain mapping, sequence or scalar nodes
+ready for output. Just like with *Constructor*, this is done by user specified
+functions. These functions take references to a node to process and to the
+*Representer*, and return the processed node.
+
+Representer functions can be added with the *addRepresenter()* method. The
+*Representer* is then passed to *Dumper*, which dumps YAML documents. Only one
+representer can be added for a type. This is asserted in *addRepresenter()*
+preconditions. By default, the default YAML types already have representer
+functions, but you can disable them by constructing *Representer* with the
+*useDefaultRepresenters* parameter set to false.
+
+By default, tags are explicitly specified for all non-default types. If you
+want the tags to be implicit, you can pass a *Resolver* that will resolve them
+implicitly. Of course, you will then need to use an identical *Resolver* when
+loading the output.
+
+With the following code, we will add support for dumping the our Color type.
+
+.. code-block:: d
+
+ Node representColor(ref Node node, Representer representer)
+ {
+ //The node is guaranteed to be Color as we add representer for Color.
+ Color color = node.get!Color;
+
+ static immutable hex = "0123456789ABCDEF";
+
+ //Using the color format from the Constructor example.
+ string scalar;
+ foreach(channel; [color.red, color.green, color.blue])
+ {
+ scalar ~= hex[channel / 16];
+ scalar ~= hex[channel % 16];
+ }
+
+ //Representing as a scalar, with custom tag to specify this data type.
+ return representer.representScalar("!color", scalar);
+ }
+
+First we get the *Color* from the node. Then we convert it to a string with the
+HTML-like format we've used before. Finally, we use the *representScalar()*
+method of *Representer* to get a scalar node ready for output.
+There are corresponding *representMapping()* and *representSequence()* methods
+as well, with examples in the
+`Resolver API documentation <../api/dyaml.resolver.html>`_.
+
+Since a type can only have one representer function, we don't dump *Color* both
+in the scalar and mapping formats we've used before. However, you can decide to
+dump the node with different formats/tags in the representer function itself.
+E.g. you could dump the Color as a mapping based on some arbitrary condition,
+such as the color being white.
+
+.. code-block:: d
+
+ void main()
+ {
+ try
+ {
+ auto representer = new Representer;
+ representer.addRepresenter!Color(&representColor);
+
+ auto resolver = new Resolver;
+ resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
+ "0123456789abcdefABCDEF");
+
+ auto dumper = Dumper("output.yaml");
+ dumper.representer = representer;
+ dumper.resolver = resolver;
+
+ auto document = Node([Color(255, 0, 0),
+ Color(0, 255, 0),
+ Color(0, 0, 255)]);
+
+ dumper.dump(document);
+ }
+ catch(YAMLException e)
+ {
+ writeln(e.msg);
+ }
+ }
+
+We construct a new *Representer*, and specify a representer function for the
+*Color* (the template argument) type. We also construct a *Resolver*, same as in
+the previous section, so the ``!color`` tag will be implicit. Of course,
+identical *Resolver* would then have to be used when loading the file.
+You don't need to do this if you want the tag to be explicit.
+
+We construct a *Dumper* to file ``output.yaml`` and pass the *Representer* and
+*Resolver* to it. Then, we create a simple node containing a sequence of colors
+and finally, we dump it.
+
+Source code for this section can be found in the ``examples/representer``
+directory of the D:YAML package.
diff --git a/doc/html/_sources/tutorials/getting_started.txt b/doc/html/_sources/tutorials/getting_started.txt
index 73bd3b0..8e4c7cd 100644
--- a/doc/html/_sources/tutorials/getting_started.txt
+++ b/doc/html/_sources/tutorials/getting_started.txt
@@ -72,7 +72,7 @@ Create a directory for your project and in that directory, create a file called
This will serve as input for our example.
-Now we need to parse it. Create a file called "main.d". Paste following code
+Now we need to parse it. Create a file called ``main.d``. Paste following code
into the file:
.. code-block:: d
@@ -82,12 +82,18 @@ into the file:
void main()
{
+ //Read the input.
Node root = Loader("input.yaml").load();
+
+ //Display the data read.
foreach(string word; root["Hello World"])
{
writeln(word);
}
writeln("The answer is ", root["Answer"].get!int);
+
+ //Dump the loaded document to output.yaml.
+ Dumper("output.yaml").dump(root);
}
@@ -98,8 +104,8 @@ Explanation of the code
First, we import the *yaml* module. This is the only module you need to import
to use D:YAML - it automatically imports all needed modules.
-Next we load the file using the *Loader.load()* method. *Loader* is the struct
-used for parsing YAML documents, and *load()* is a method that loads the file as
+Next we load the file using the *Loader.load()* method. *Loader* is a struct
+used for parsing YAML documents. The *load()* method loads the file as
**one** YAML document, or throws *YAMLException*, D:YAML exception type, if the
file could not be parsed or does not contain exactly one document. Note that we
don't do any error checking here in order to keep the example as simple as
@@ -126,6 +132,15 @@ The *Node.get()* method is used to get value of a scalar node, allowing to
specify type. D:YAML will try to return the scalar as this type, converting if
needed, throwing *YAMLException* if not possible.
+Finally we dump the document we just read to ``output.yaml`` with the
+*Dumper.dump()* method. *Dumper* is a struct used to dump YAML documents.
+The *dump()* method writes one or more documents to a file, throwing
+*YAMLException* if the file could not be written to.
+
+D:YAML doesn't preserve style information in documents, so even though
+``output.yaml`` will contain the same data as ``input.yaml``, it might be
+formatted differently. Comments are not preserved, either.
+
^^^^^^^^^
Compiling
diff --git a/doc/html/api/dyaml.representer.html b/doc/html/api/dyaml.representer.html
index 593dcd0..ec00226 100644
--- a/doc/html/api/dyaml.representer.html
+++ b/doc/html/api/dyaml.representer.html
@@ -39,7 +39,8 @@
dyaml.representer
-
YAML node representer.
+
YAML node representer. Prepares YAML nodes for output. A tutorial can be
+ found here.
Code based on PyYAML.
diff --git a/doc/html/articles/spec_differences.html b/doc/html/articles/spec_differences.html
index d8947b6..cff7ce6 100644
--- a/doc/html/articles/spec_differences.html
+++ b/doc/html/articles/spec_differences.html
@@ -138,7 +138,7 @@ struct appears in Phobos.