nimでYaml操作

# 概要
NimのYAML処理をコツコツと
NimYAMLの低レベルメソッドを試します。
NimYAMLの現行バージョン0.10.3だと、nim-0.19.0では~~コンパイルエラー~~となります。

追記(2019/07/08) 

* NimYamlのバージョン0.11.0では0.19.0対応しているそうです。
* 残念ながら0.20.0には未対応でいくつかコンパイルエラーが発生します。

0.19.0で動かす場合は、NimYAMLをForkした[ブランチ](https://github.com/6in/NimYAML/tree/for-0.19.0)をクローンして、```nimble install```を実行してください

```
# for nim-0.19.0
git clone -b "for-0.19.0" https://github.com/6in/NimYAML.git
cd NimYAML
nimble install
```

以下は、yaml.domを利用して一からYamlを組み立てるサンプルとなります。

## 以下メモ

### 低レベルなYaml構築

```nim
import yaml,yaml/presenter,yaml/serialization
import json,strutils,os,streams

block:
  # ヘルパー関数群
  proc y(val:string) : YamlNode = newYamlNode(val)
  proc y(val:int) : YamlNode = newYamlNode($val,"int")
  proc y(key,val:string) : YamlNode = newYamlNode( [ (y(key),y(val)) ] )
  # key,valueのペアからYamlNodeを生成
  proc y( keyValues: openArray[(string,string)] ) : YamlNode = 
    var kvs: seq[(YamlNode,YamlNode)] = @[]
    for kv in keyValues:
      kvs.add ( y(kv[0]), y(kv[1]) )
    result = newYamlNode(kvs)    
  # YamlNodeの配列を構築
  proc y( values: openArray[YamlNode] ) : YamlNode = 
    var vals: seq[YamlNode] = @[]
    for val in values:
      vals.add val
    result = newYamlNode(vals)
  # ファイルを表示
  proc cat(file:string) =
    let f = open(file,FileMode.fmRead)
    defer: f.close
    echo f.readAll
  # Yamlをダンプ
  proc dump(yamlDoc:YamlDocument ,file:string, style:PresentationStyle) =
    var s = newFileStream(file, fmWrite)
    yamlDoc.dumpDom(s, options= defineOptions(style = style) )
    s.close()
    cat(file)
  #
  # YamlDocを作成
  let yamlDoc = initYamlDoc( y([("string","val1")]) )
  #
  # 属性追加
  yamlDoc.root[y"number"] = y(2)
  # オブジェクトを追加
  yamlDoc.root[y"object"] = y("child1","3")
  # 配列を追加
  yamlDoc.root[y"array"] = y( [ y"child2", y"child3", y"child4", y"child5" ] )
  # 配列[オブジェクト]を追加
  yamlDoc.root[y"arrayObject"] = y( [ y("key1","val1"),y("key2","val2"),y("key3","val3") ] )
  #
  # Yamlをダンプ
  # psMinimal, psCanonical, psDefault, psJson, psBlockOnly
  echo "============================="
  echo "Yamlを表示(psMinimal)"
  yamlDoc.dump( "psMinimal.yaml", psMinimal)
  echo "============================="
  echo "Yamlを表示(psCanonical)"
  yamlDoc.dump( "psCanonical.yaml", psCanonical)
  echo "============================="
  echo "Yamlを表示(psDefault)"
  yamlDoc.dump( "psDefault.yaml", psDefault)
  echo "============================="
  echo "Yamlを表示(psJson)"
  yamlDoc.dump( "psJson.yaml", psJson)
  echo "============================="
  echo "Yamlを表示(psBlockOnly)"
  yamlDoc.dump( "psBlockOnly.yaml", psBlockOnly)
```

```shell-session
(stdout)
=============================
Yamlを表示(psMinimal)
%YAML 1.2
--- 
{string: val1, number: !<int> 2, object: {child1: 3}, array: [child2, child3, child4, child5], arrayObject: [{key1: val1}, {key2: val2}, {key3: val3}]}
=============================
Yamlを表示(psCanonical)
%YAML 1.2
--- 
{
  ? "string"
  : "val1",
  ? "number"
  : !<int> "2",
  ? "object"
  : {
    ? "child1"
    : "3"
  },
  ? "array"
  : [
    "child2",
    "child3",
    "child4",
    "child5"
  ],
  ? "arrayObject"
  : [
    {
      ? "key1"
      : "val1"
    },
    {
      ? "key2"
      : "val2"
    },
    {
      ? "key3"
      : "val3"
    }
  ]
}
=============================
Yamlを表示(psDefault)
%YAML 1.2
--- 
string: val1
number: !<int> 2
object: 
  child1: 3
array: [child2, child3, child4, child5]
arrayObject: 
  - 
    key1: val1
  - 
    key2: val2
  - 
    key3: val3
=============================
Yamlを表示(psJson)

{
  "string": "val1",
  "number": "2",
  "object": {
    "child1": 3
  },
  "array": [
    "child2",
    "child3",
    "child4",
    "child5"
  ],
  "arrayObject": [
    {
      "key1": "val1"
    },
    {
      "key2": "val2"
    },
    {
      "key3": "val3"
    }
  ]
}
=============================
Yamlを表示(psBlockOnly)
%YAML 1.2
--- 
string: val1
number: !<int> 2
object: 
  child1: 3
array: 
  - child2
  - child3
  - child4
  - child5
arrayObject: 
  - 
    key1: val1
  - 
    key2: val2
  - 
    key3: val3
```

### 文字列から構築

```nim
import yaml,yaml/presenter,yaml/serialization
import json,strutils,os,streams

block:
  # yamlDoc.root.new()
  let yamlDoc2 = loadDom("""
test:
  test1: 1
  """)
  echo $yamlDoc2
```

```shell-session
(stdout)
(root: !<?> {!<?> "test": !<?> {!<?> "test1": !<?> "1"}})
```

### ファイルから構築

```nim
import yaml,yaml/presenter,yaml/serialization
import json,strutils,os,streams

block:
  let fileStream = newFileStream("psBlockOnly.yaml",FileMode.fmRead)
  let yamlDoc = loadDom( fileStream )
  defer:
    fileStream.close
  echo $yamlDoc
```

```shell-session
(stdout)
(root: !<?> {!<?> "string": !<?> "val1", !<?> "number": !<int> "2", !<?> "object": !<?> {!<?> "child1": !<?> "3"}, !<?> "array": !<?> [!<?> "child2", !<?> "child3", !<?> "child4", !<?> "child5"], !<?> "arrayObject": !<?> [!<?> {!<?> "key1": !<?> "val1"}, !<?> {!<?> "key2": !<?> "val2"}, !<?> {!<?> "key3": !<?> "val3"}]})
```