convert docs to markdown and remove built doc artifacts (#153)
convert docs to markdown and remove built doc artifacts merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
parent
ab0e2c0519
commit
03c9972485
83 changed files with 656 additions and 10839 deletions
64
docs/articles/spec_differences.md
Normal file
64
docs/articles/spec_differences.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Differences between D:YAML and the YAML specification
|
||||
|
||||
There are some differences between D:YAML and the YAML 1.1
|
||||
specification. Some are caused by difficulty of implementation of some
|
||||
features, such as multiple Unicode encodings within single stream, and
|
||||
some by unnecessary restrictions or ambiguities in the specification.
|
||||
|
||||
Still, D:YAML tries to be as close to the specification as possible. It
|
||||
should never load documents with different meaning than according to the
|
||||
specification, and documents that fail to load should be very rare (for
|
||||
instance, very few files use multiple Unicode encodings).
|
||||
|
||||
## List of known differences:
|
||||
|
||||
Differences that can cause valid YAML documents not to load:
|
||||
|
||||
- No support for byte order marks and multiple Unicode encodings in a
|
||||
stream.
|
||||
|
||||
- Plain scalars in flow context cannot contain `,`, `:` and `?`. This
|
||||
might change with `:` in the future. See
|
||||
<http://pyyaml.org/wiki/YAMLColonInFlowContext> for details.
|
||||
|
||||
- The specification does not restrict characters for anchors and
|
||||
aliases. This may lead to problems, for instance, the document:
|
||||
|
||||
[ *alias, value ]
|
||||
|
||||
can be interpteted in two ways, as:
|
||||
|
||||
[ "value" ]
|
||||
|
||||
and:
|
||||
|
||||
[ *alias , "value" ]
|
||||
|
||||
Therefore we restrict aliases and anchors to ASCII alphanumeric
|
||||
characters.
|
||||
|
||||
- The specification is confusing about tabs in plain scalars. We don't
|
||||
use tabs in plain scalars at all.
|
||||
|
||||
- There is no support for recursive data structures in DYAML.
|
||||
|
||||
Other differences:
|
||||
|
||||
- Indentation is ignored in the flow context, which is less
|
||||
restrictive than the specification. This allows code such as:
|
||||
|
||||
key: {
|
||||
}
|
||||
|
||||
- Indentation rules for quoted scalars are loosed: They don't need to
|
||||
adhere indentation as `"` and `'` clearly mark the beginning and the
|
||||
end of them.
|
||||
|
||||
- We allow `_` in tag handles.
|
||||
|
||||
- Right now, two mappings with the same contents but different
|
||||
orderings are considered unequal, even if they are unordered
|
||||
mappings. This is because all mappings are ordered in the D:YAML
|
||||
implementation. This should change in future, once D associative
|
||||
arrays work with variant types or a map class or struct appears in
|
||||
Phobos.
|
11
docs/index.md
Normal file
11
docs/index.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Welcome to D:YAML documentation!
|
||||
|
||||
API Documentation [online](https://dyaml.dpldocs.info/dyaml.html)
|
||||
|
||||
Tutorials:
|
||||
- [Getting Started](tutorials/getting_started.md)
|
||||
- [Custom Types](tutorials/custom_types.md)
|
||||
- [YAML Syntax](tutorials/yaml_syntax.md)
|
||||
|
||||
Articles:
|
||||
- [Spec Differences](articles/spec_differences.md)
|
BIN
docs/logo128.png
Normal file
BIN
docs/logo128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
docs/logo210.png
Normal file
BIN
docs/logo210.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
336
docs/tutorials/custom_types.md
Normal file
336
docs/tutorials/custom_types.md
Normal file
|
@ -0,0 +1,336 @@
|
|||
# Custom YAML data types
|
||||
|
||||
Sometimes you need to serialize complex data types such as classes. To
|
||||
do this you could use plain nodes such as mappings with classes' fields.
|
||||
YAML also supports custom types with identifiers called *tags*. That is
|
||||
the topic of this tutorial.
|
||||
|
||||
Each YAML node has a tag specifying its type. For instance: strings use
|
||||
the tag `tag:yaml.org,2002:str`. Tags of most default types are
|
||||
*implicitly resolved* during parsing - you don't need to specify tag for
|
||||
each float, integer, etc. D:YAML can also implicitly resolve custom
|
||||
tags, as we will show later.
|
||||
|
||||
## Constructor
|
||||
|
||||
D:YAML uses the [Constructor](https://dyaml.dpldocs.info/dyaml.constructor.Constructor.html)
|
||||
class to process each node to hold data type corresponding to its tag.
|
||||
*Constructor* stores functions to process each supported tag. These are
|
||||
supplied by the user using the *addConstructorXXX()* methods, where
|
||||
*XXX* is *Scalar*, *Sequence* or *Mapping*. *Constructor* is then passed
|
||||
to *Loader*, which parses YAML input.
|
||||
|
||||
Structs and classes must implement the *opCmp()* operator for YAML
|
||||
support. This is used for duplicate detection in mappings, sorting and
|
||||
equality comparisons of nodes. The signature of the operator that must
|
||||
be implemented is `const int opCmp(ref const MyStruct s)` for structs
|
||||
where *MyStruct* is the struct type, and `int opCmp(Object o)` for
|
||||
classes. Note that the class *opCmp()* should not alter the compared
|
||||
values - it is not const for compatibility reasons.
|
||||
|
||||
We will implement support for an RGB color type. It is implemented as
|
||||
the following struct:
|
||||
|
||||
```D
|
||||
struct Color
|
||||
{
|
||||
ubyte red;
|
||||
ubyte green;
|
||||
ubyte blue;
|
||||
|
||||
const int opCmp(ref const Color c)
|
||||
{
|
||||
if(red != c.red) {return red - c.red;}
|
||||
if(green != c.green){return green - c.green;}
|
||||
if(blue != c.blue) {return blue - c.blue;}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
First, we need a function to construct our data type. The function will
|
||||
take a reference to *Node* to construct from. The node is guaranteed to
|
||||
contain either a *string*, an array of *Node* or of *Node.Pair*,
|
||||
depending on whether we're constructing our value from a scalar,
|
||||
sequence, or mapping, respectively. If this function throws any
|
||||
exception, D:YAML handles it and adds its message to a *YAMLException*
|
||||
that will be thrown when loading the file.
|
||||
|
||||
In this tutorial, we have functions to construct a color from a scalar,
|
||||
using CSS-like format, RRGGBB, or from a mapping, where we use the
|
||||
following format: {r:RRR, g:GGG, b:BBB} . Code of these functions:
|
||||
|
||||
```D
|
||||
Color constructColorScalar(ref Node node)
|
||||
{
|
||||
string value = node.as!string;
|
||||
|
||||
if(value.length != 6)
|
||||
{
|
||||
throw new Exception("Invalid color: " ~ value);
|
||||
}
|
||||
//We don't need to check for uppercase chars this way.
|
||||
value = value.toLower();
|
||||
|
||||
//Get value of a hex digit.
|
||||
uint hex(char c)
|
||||
{
|
||||
import std.ascii;
|
||||
if(!std.ascii.isHexDigit(c))
|
||||
{
|
||||
throw new Exception("Invalid color: " ~ value);
|
||||
}
|
||||
|
||||
if(std.ascii.isDigit(c))
|
||||
{
|
||||
return c - '0';
|
||||
}
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
|
||||
Color result;
|
||||
result.red = cast(ubyte)(16 * hex(value[0]) + hex(value[1]));
|
||||
result.green = cast(ubyte)(16 * hex(value[2]) + hex(value[3]));
|
||||
result.blue = cast(ubyte)(16 * hex(value[4]) + hex(value[5]));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Color constructColorMapping(ref Node node)
|
||||
{
|
||||
ubyte r,g,b;
|
||||
|
||||
//Might throw if a value is missing is not an integer, or is out of range.
|
||||
//If this happens, D:YAML will handle the exception and use its message
|
||||
//in a YAMLException thrown when loading.
|
||||
r = node["r"].as!ubyte;
|
||||
g = node["g"].as!ubyte;
|
||||
b = node["b"].as!ubyte;
|
||||
|
||||
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:
|
||||
|
||||
```YAML
|
||||
scalar-red: !color FF0000
|
||||
scalar-orange: !color FFFF00
|
||||
mapping-red: !color-mapping {r: 255, g: 0, b: 0}
|
||||
mapping-orange:
|
||||
!color-mapping
|
||||
r: 255
|
||||
g: 255
|
||||
b: 0
|
||||
```
|
||||
|
||||
You can see that we're using tag `!color` for scalar colors, and
|
||||
`!color-mapping` for colors expressed as mappings.
|
||||
|
||||
Finally, the code to put it all together:
|
||||
|
||||
```D
|
||||
void main()
|
||||
{
|
||||
auto red = Color(255, 0, 0);
|
||||
auto orange = Color(255, 255, 0);
|
||||
|
||||
try
|
||||
{
|
||||
auto constructor = new Constructor;
|
||||
//both functions handle the same tag, but one handles scalar, one mapping.
|
||||
constructor.addConstructorScalar("!color", &constructColorScalar);
|
||||
constructor.addConstructorMapping("!color-mapping", &constructColorMapping);
|
||||
|
||||
auto loader = Loader("input.yaml");
|
||||
loader.constructor = constructor;
|
||||
|
||||
auto root = loader.load();
|
||||
|
||||
if(root["scalar-red"].as!Color == red &&
|
||||
root["mapping-red"].as!Color == red &&
|
||||
root["scalar-orange"].as!Color == orange &&
|
||||
root["mapping-orange"].as!Color == orange)
|
||||
{
|
||||
writeln("SUCCESS");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(YAMLException e)
|
||||
{
|
||||
writeln(e.msg);
|
||||
}
|
||||
|
||||
writeln("FAILURE");
|
||||
}
|
||||
```
|
||||
|
||||
First, we create a *Constructor* and pass functions to handle the
|
||||
`!color` 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 to test if they were loaded as expected.
|
||||
|
||||
You can find the source code for what we've done so far in the
|
||||
`examples/constructor` directory in the D:YAML package.
|
||||
|
||||
## Resolver
|
||||
|
||||
Specifying tag for every color can be tedious. D:YAML can implicitly
|
||||
resolve scalar tags using regular expressions. This is how default types
|
||||
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 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 be resolvable as any non-string YAML data type.
|
||||
|
||||
Add this to your code to add implicit resolution of `!color`.
|
||||
|
||||
```D
|
||||
//code from the previous example...
|
||||
|
||||
auto resolver = new Resolver;
|
||||
import std.regex;
|
||||
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
|
||||
"0123456789abcdefABCDEF");
|
||||
|
||||
auto loader = Loader("input.yaml");
|
||||
|
||||
loader.constructor = constructor;
|
||||
loader.resolver = resolver;
|
||||
|
||||
//code from the previous example...
|
||||
```
|
||||
|
||||
Now, change contents of `input.yaml` to this:
|
||||
|
||||
```YAML
|
||||
scalar-red: FF0000
|
||||
scalar-orange: FFFF00
|
||||
mapping-red: !color-mapping {r: 255, g: 0, b: 0}
|
||||
mapping-orange:
|
||||
!color-mapping
|
||||
r: 255
|
||||
g: 255
|
||||
b: 0
|
||||
```
|
||||
|
||||
We no longer need to specify the tag for scalar color values. Compile
|
||||
and test 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 can load custom data types, it might be good to know how to
|
||||
dump them. D:YAML uses the [Representer](https://dyaml.dpldocs.info/dyaml.representer.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 function per type can be specified. This is asserted
|
||||
in *addRepresenter()* preconditions. Default YAML types already have
|
||||
representer functions specified, but you can disable them by
|
||||
constructing *Representer* with the *useDefaultRepresenters* parameter
|
||||
set to false.
|
||||
|
||||
By default, tags are explicitly output for all non-default types. To
|
||||
make dumped tags implicit, you can pass a *Resolver* that will resolve
|
||||
them implicitly. Of course, you will need to use an identical *Resolver*
|
||||
when loading the output.
|
||||
|
||||
With the following code, we will add support for dumping the our Color
|
||||
type.
|
||||
|
||||
```D
|
||||
Node representColor(ref Node node, Representer representer)
|
||||
{
|
||||
//The node is guaranteed to be Color as we add representer for Color.
|
||||
Color color = node.as!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 CSS-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](https://dyaml.dpldocs.info/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.
|
||||
|
||||
```D
|
||||
void main()
|
||||
{
|
||||
try
|
||||
{
|
||||
auto representer = new Representer;
|
||||
representer.addRepresenter!Color(&representColor);
|
||||
|
||||
auto resolver = new Resolver;
|
||||
import std.regex;
|
||||
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.
|
164
docs/tutorials/getting_started.md
Normal file
164
docs/tutorials/getting_started.md
Normal file
|
@ -0,0 +1,164 @@
|
|||
# Getting started
|
||||
|
||||
Welcome to D:YAML\! D:YAML is a
|
||||
[YAML](http://en.wikipedia.org/wiki/YAML) parser library for the [D
|
||||
programming language](http://dlang.org). This tutorial will explain how
|
||||
to set D:YAML up and use it in your projects.
|
||||
|
||||
This is meant to be the **simplest possible** introduction to D:YAML.
|
||||
Some of this information might already be known to you. Only basic usage
|
||||
is covered.
|
||||
|
||||
## Setting up
|
||||
|
||||
### Install the DMD compiler
|
||||
|
||||
Digital Mars D compiler, or DMD, is the most commonly used D compiler.
|
||||
You can find its newest version [here](http://dlang.org/download.html).
|
||||
Download the version of DMD for your operating system and install it.
|
||||
|
||||
Note: Other D compilers exist, such as [GDC](http://gdcproject.org/) and
|
||||
[LDC](https://github.com/ldc-developers/ldc).
|
||||
|
||||
### Install dub
|
||||
|
||||
[dub](http://code.dlang.org/about) is a build system and package manager
|
||||
for D. It is the standard way to manage D projects and their
|
||||
dependencies, compilation and so on.
|
||||
|
||||
DMD may include DUB in future releases, but at this point we need to
|
||||
install it separately. See [installation
|
||||
instructions](https://github.com/D-Programming-Language/dub#installation).
|
||||
|
||||
## Your first D:YAML project
|
||||
|
||||
Create a directory for your project and in that directory, create a new
|
||||
file named `input.yaml` and paste this code into the file:
|
||||
|
||||
```YAML
|
||||
Hello World : [Hello, World]
|
||||
Answer: 42
|
||||
```
|
||||
|
||||
This will serve as input for our example.
|
||||
|
||||
Now we need to parse it. Create a new file with name `main.d`. Paste
|
||||
following code into the file:
|
||||
|
||||
```D
|
||||
import std.stdio;
|
||||
import yaml;
|
||||
|
||||
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"].as!int);
|
||||
|
||||
//Dump the loaded document to output.yaml.
|
||||
Dumper("output.yaml").dump(root);
|
||||
}
|
||||
```
|
||||
|
||||
### Explanation of the code
|
||||
|
||||
First, we import the *dyaml.all* module. This is the only D:YAML module
|
||||
you need to import - it automatically imports all needed modules.
|
||||
|
||||
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 contains more than
|
||||
one document. Note that we don't do any error checking here in order to
|
||||
keep the example as simple as possible.
|
||||
|
||||
*Node* represents a node in a YAML document. It can be a sequence
|
||||
(array), mapping (associative array) or a scalar (value). Here the root
|
||||
node is a mapping, and we use the index operator to get subnodes with
|
||||
keys "Hello World" and "Answer". We iterate over the former, as it is a
|
||||
sequence, and use the *Node.as()* method on the latter to read its value
|
||||
as an integer.
|
||||
|
||||
You can iterate over a mapping or sequence as if it was an associative
|
||||
or normal array, respectively. If you try to iterate over a scalar, it
|
||||
will throw a *YAMLException*.
|
||||
|
||||
You can iterate using *Node* as the iterated type, or specify the type
|
||||
iterated nodes are expected to have. D:YAML will automatically convert
|
||||
to that type if possible. Here we specify the *string* type, so we
|
||||
iterate over the "Hello World" sequence as an array of strings. If it is
|
||||
not possible to convert to iterated type, a *YAMLException* is thrown.
|
||||
For instance, if we specified *int* here, we would get an error, as
|
||||
"Hello" cannot be converted to an integer.
|
||||
|
||||
The *Node.as()* method is used to read value of a scalar node as
|
||||
specified type. If the scalar does not have the specified type, D:YAML
|
||||
will try to convert it, 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 tries to preserve style information in documents so e.g. `[Hello,
|
||||
World]` is not turned into:
|
||||
|
||||
```YAML
|
||||
- Hello
|
||||
- World
|
||||
```
|
||||
|
||||
However, comments are not preserved and neither are any extra formatting
|
||||
whitespace that doesn't affect the meaning of YAML contents.
|
||||
|
||||
### Compiling
|
||||
|
||||
We're going to use dub, which we installed at the beginning, to compile
|
||||
our project.
|
||||
|
||||
Create a file called `dub.json` with the following contents:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"name": "getting-started",
|
||||
"targetType": "executable",
|
||||
"sourceFiles": ["main.d"],
|
||||
"mainSourceFile": "main.d",
|
||||
"dependencies":
|
||||
{
|
||||
"dyaml": { "version" : "~>0.5.0" },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
This file tells dub that we're building an executable called
|
||||
`getting-started` from a D source file `main.d`, and that our project
|
||||
depends on D:YAML 0.5.0 or any newer, bugfix release of D:YAML 0.5 . DUB
|
||||
will automatically find and download the correct version of D:YAML when
|
||||
the project is built.
|
||||
|
||||
Now run the following command in your project's directory:
|
||||
|
||||
dub build
|
||||
|
||||
dub will automatically download D:YAML and compile it, and then then it
|
||||
will compile our program. This will generate an executable called
|
||||
`getting-started` or `getting-started.exe` in your directory. When you
|
||||
run it, it should produce the following output:
|
||||
|
||||
Hello
|
||||
World
|
||||
The answer is 42
|
||||
|
||||
### Conclusion
|
||||
|
||||
You should now have a basic idea about how to use D:YAML. To learn more,
|
||||
look at the [API documentation](https://dyaml.dpldocs.info/dyaml.html) and other tutorials.
|
||||
You can find code for this example in the `example/getting_started`
|
||||
directory in the package.
|
241
docs/tutorials/yaml_syntax.md
Normal file
241
docs/tutorials/yaml_syntax.md
Normal file
|
@ -0,0 +1,241 @@
|
|||
# YAML syntax
|
||||
|
||||
This is an introduction to the most common YAML constructs. For more detailed
|
||||
information, see [PyYAML documentation](http://pyyaml.org/wiki/PyYAMLDocumentation),
|
||||
which this article is based on,
|
||||
[Chapter 2 of the YAML specification](http://yaml.org/spec/1.1/#id857168)
|
||||
or the [Wikipedia page](http://en.wikipedia.org/wiki/YAML).
|
||||
|
||||
YAML is a data serialization format designed for human readability. YAML is a
|
||||
recursive acronym for "YAML Ain't Markup Language".
|
||||
|
||||
YAML is similar to JSON, and in fact, JSON is a subset of YAML 1.2; but YAML has
|
||||
some more advanced features and is easier to read. However, it is also more
|
||||
difficult to parse (and probably somewhat slower). Data is stored in mappings
|
||||
(associative arrays), sequences (lists) and scalars (single values). Data
|
||||
structure hierarchy depends either on indentation (block context, similar to
|
||||
Python code), or nesting of brackets and braces (flow context, similar to JSON).
|
||||
YAML comments begin with `#` and continue until the end of line.
|
||||
|
||||
|
||||
## Documents
|
||||
|
||||
A YAML stream consists of one or more documents starting with `---` and
|
||||
optionally ending with `...` . `---` can be left out for the first document.
|
||||
|
||||
Single document with no explicit start or end:
|
||||
|
||||
```
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
```
|
||||
Same document with explicit start and end:
|
||||
```
|
||||
---
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
...
|
||||
```
|
||||
A stream containing multiple documents:
|
||||
```
|
||||
---
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
---
|
||||
- Linux
|
||||
- BSD
|
||||
---
|
||||
answer : 42
|
||||
```
|
||||
|
||||
## Sequences
|
||||
|
||||
Sequences are arrays of nodes of any type, similar e.g. to Python lists.
|
||||
In block context, each item begins with hyphen+space "- ". In flow context,
|
||||
sequences have syntax similar to D arrays.
|
||||
|
||||
```
|
||||
#Block context
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
```
|
||||
```
|
||||
#Flow context
|
||||
[Red, Green, Blue]
|
||||
```
|
||||
```
|
||||
#Nested
|
||||
-
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
-
|
||||
- Linux
|
||||
- BSD
|
||||
```
|
||||
```
|
||||
#Nested flow
|
||||
[[Red, Green, Blue], [Linux, BSD]]
|
||||
```
|
||||
```
|
||||
#Nested in a mapping
|
||||
Colors:
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
Operating systems:
|
||||
- Linux
|
||||
- BSD
|
||||
```
|
||||
|
||||
## Mappings
|
||||
|
||||
Mappings are associative arrays where each key and value can be of any type,
|
||||
similar e.g. to Python dictionaries. In block context, keys and values are
|
||||
separated by colon+space ": ". In flow context, mappings have syntax similar
|
||||
to D associative arrays, but with braces instead of brackets:
|
||||
|
||||
```
|
||||
#Block context
|
||||
CPU: Athlon
|
||||
GPU: Radeon
|
||||
OS: Linux
|
||||
|
||||
```
|
||||
```
|
||||
#Flow context
|
||||
{CPU: Athlon, GPU: Radeon, OS: Linux}
|
||||
|
||||
```
|
||||
```
|
||||
#Nested
|
||||
PC:
|
||||
CPU: Athlon
|
||||
GPU: Radeon
|
||||
OS: Debian
|
||||
Phone:
|
||||
CPU: Cortex
|
||||
GPU: PowerVR
|
||||
OS: Android
|
||||
|
||||
```
|
||||
```
|
||||
#Nested flow
|
||||
{PC: {CPU: Athlon, GPU: Radeon, OS: Debian},
|
||||
Phone: {CPU: Cortex, GPU: PowerVR, OS: Android}}
|
||||
```
|
||||
```
|
||||
#Nested in a sequence
|
||||
- CPU: Athlon
|
||||
GPU: Radeon
|
||||
OS: Debian
|
||||
- CPU: Cortex
|
||||
GPU: PowerVR
|
||||
OS: Android
|
||||
```
|
||||
|
||||
Complex keys start with question mark+space "? ".
|
||||
|
||||
```
|
||||
#Nested in a sequence
|
||||
? [CPU, GPU]: [Athlon, Radeon]
|
||||
OS: Debian
|
||||
```
|
||||
|
||||
## Scalars
|
||||
|
||||
Scalars are simple values such as integers, strings, timestamps and so on.
|
||||
There are multiple scalar styles.
|
||||
|
||||
Plain scalars use no quotes, start with the first non-space and end with the
|
||||
last non-space character:
|
||||
|
||||
```
|
||||
scalar: Plain scalar
|
||||
```
|
||||
|
||||
Single quoted scalars start and end with single quotes. A single quote is
|
||||
represented by a pair of single quotes ''.
|
||||
|
||||
```
|
||||
scalar: 'Single quoted scalar ending with some spaces '
|
||||
```
|
||||
|
||||
Double quoted scalars support C-style escape sequences.
|
||||
|
||||
```
|
||||
scalar: "Double quoted scalar \n with some \\ escape sequences"
|
||||
```
|
||||
|
||||
Block scalars are convenient for multi-line values. They start either with
|
||||
`|` or with `>`. With `|`, the newlines in the scalar are preserved.
|
||||
With `>`, the newlines between two non-empty lines are removed.
|
||||
|
||||
```
|
||||
scalar: |
|
||||
Newlines are preserved
|
||||
First line
|
||||
Second line
|
||||
```
|
||||
```
|
||||
scalar: >
|
||||
Newlines are folded
|
||||
This is still the first paragraph
|
||||
|
||||
This is the second
|
||||
paragraph
|
||||
```
|
||||
|
||||
## Anchors and aliases
|
||||
|
||||
Anchors and aliases can reduce size of YAML code by allowing you to define a
|
||||
value once, assign an anchor to it and use alias referring to that anchor
|
||||
anywhere else you need that value. It is possible to use this to create
|
||||
recursive data structures and some parsers support this; however, D:YAML does
|
||||
not (this might change in the future, but it is unlikely).
|
||||
|
||||
```
|
||||
Person: &AD
|
||||
gender: male
|
||||
name: Arthur Dent
|
||||
Clone: *AD
|
||||
```
|
||||
|
||||
## Tags
|
||||
|
||||
Tags are identifiers that specify data types of YAML nodes. Most default YAML
|
||||
tags are resolved implicitly, so there is no need to specify them. D:YAML also
|
||||
supports implicit resolution for custom, user specified tags.
|
||||
|
||||
Explicitly specified tags:
|
||||
|
||||
```
|
||||
answer: !!int "42"
|
||||
name: !!str "Arthur Dent"
|
||||
```
|
||||
|
||||
Implicit tags:
|
||||
|
||||
```
|
||||
answer: 42 #int
|
||||
name: Arthur Dent #string
|
||||
```
|
||||
|
||||
This table shows D types stored in *yaml.Node* default YAML tags are converted to.
|
||||
Some of these might change in the future (especially !!map and !!set).
|
||||
|
||||
|YAML tag |D type |
|
||||
|-----------------------|---------------------|
|
||||
|!!null |yaml.YAMLNull |
|
||||
|!!bool |bool |
|
||||
|!!int |long |
|
||||
|!!float |real |
|
||||
|!!binary |ubyte[] |
|
||||
|!!timestamp |std.datetime.SysTime |
|
||||
|!!map, !!omap, !!pairs |yaml.Node.Pair[] |
|
||||
|!!seq, !!set |yaml.Node[] |
|
||||
|!!str |string |
|
Loading…
Add table
Add a link
Reference in a new issue