---
title: "Introduction to yaml"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to yaml}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(yaml)
```

## What is YAML?

YAML is a human-readable data serialization language. With it, you can create
easily readable documents that can be consumed by a variety of programming
languages.

For example, here's a map of baseball teams per league:

```yaml
american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves
```

And a data dictionary specification:

```yaml
- field: ID
  description: primary identifier
  type: integer
  primary key: yes
- field: DOB
  description: date of birth
  type: date
  format: yyyy-mm-dd
- field: State
  description: state of residence
  type: string
```

## Parsing YAML

`yaml.load()` parses a YAML document from a string:

```{r}
yaml.load("
- 1
- 2
- 3
")
```

`yaml.load_file()` and `read_yaml()` read YAML from a file or connection.

### Scalars

A YAML scalar is the basic building block of YAML documents. The parser
automatically determines the type:

```{r}
yaml.load("1.2345")
yaml.load("true")
yaml.load("hello")
```

### Sequences

A YAML sequence is a list of elements. If all elements are uniform,
`yaml.load()` returns a vector of that type. Otherwise, it returns a list:

```{r}
# Uniform sequence -> vector
yaml.load("
- 1
- 2
- 3
")

# Mixed sequence -> list
yaml.load("
- 1
- hello
- true
")
```

### Maps

A YAML map is a list of paired keys and values. By default, `yaml.load()`
returns a named list:

```{r}
yaml.load("
one: 1
two: 2
three: 3
")
```

Since YAML map keys can be almost anything (not just strings), you can preserve
the data type of keys with `as.named.list = FALSE`. This creates a `keys`
attribute instead of coercing keys to strings:

```{r}
yaml.load("
1: one
2: two
", as.named.list = FALSE)
```

### Custom handlers

You can customize parsing with handler functions. Handlers are passed to
`yaml.load()` as a named list, where each name is the YAML type to handle:

```{r}
# Add 100 to all integers
yaml.load("123", handlers = list(int = function(x) as.integer(x) + 100))
```

#### Sequence handlers

Sequence handlers receive a list and can transform it:

```{r}
yaml.load("
- 1
- 2
- 3
", handlers = list(seq = function(x) sum(as.numeric(x))))
```

#### Map handlers

Map handlers receive a named list (or a list with a `keys` attribute):

```{r}
yaml.load("
a:
- 1
- 2
b:
- 3
- 4
", handlers = list(map = function(x) as.data.frame(x)))
```

## Emitting YAML

`as.yaml()` converts R objects to YAML strings:

```{r}
cat(as.yaml(1:5))
```

`write_yaml()` writes the result directly to a file or connection.

### Formatting options

#### indent

Control indentation depth (default is 2):

```{r}
cat(as.yaml(list(foo = list(bar = "baz")), indent = 4))
```

#### indent.mapping.sequence

By default, sequences within a mapping are not indented:

```{r}
cat(as.yaml(list(foo = 1:3)))
```

Set `indent.mapping.sequence = TRUE` to indent them:

```{r}
cat(as.yaml(list(foo = 1:3), indent.mapping.sequence = TRUE))
```

#### column.major

Controls how data frames are converted. When `TRUE` (default), data frames
are emitted column-wise:

```{r}
x <- data.frame(a = 1:2, b = 3:4)
cat(as.yaml(x, column.major = TRUE))
```

When `FALSE`, data frames are emitted row-wise:

```{r}
cat(as.yaml(x, column.major = FALSE))
```

### Custom handlers

Specify custom handler functions for R object classes:

```{r}
cat(as.yaml(
  Sys.Date(),
  handlers = list(Date = function(x) format(x, "%Y/%m/%d"))
))
```

### YAML 1.2 logical handling

For YAML 1.2-like logical output, use `verbatim_logical`:

```{r}
cat(as.yaml(c(TRUE, FALSE), handlers = list(logical = verbatim_logical)))
```

### Verbatim text

Character vectors with class `"verbatim"` are not quoted except when required
by the YAML specification:

```{r}
result <- c("true", "false")
class(result) <- "verbatim"
cat(as.yaml(result))
```

### Quoted strings

Force quoting with the `"quoted"` attribute:

```{r}
port <- "80:80"
attr(port, "quoted") <- TRUE
cat(as.yaml(list(ports = list(port))))
```

### Custom tags

Set YAML tags with the `"tag"` attribute:

```{r}
x <- 1:3
attr(x, "tag") <- "!custom"
cat(as.yaml(x))
```
