---
title: "Usage of configr"
author: "Jianfeng Li"
date: "`r Sys.Date()`"
output:
  prettydoc::html_pretty:
      toc: true
      theme: cayman
      highlight: github
  pdf_document:
      toc: true
vignette: >
  %\VignetteIndexEntry{Usage of configr}
  %\VignetteEngine{knitr::rmarkdown}
  \usepackage[utf8]{inputenc}
  %\VignetteEncoding{UTF-8}
---

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

configr is an integrated parser package that json, ini, yaml and toml format files can now be processed. The vignette will walk you through the basics of using configr to extend existing parser in R.

## Built-in examples of configuration file

Example of json, ini, yaml, toml can be used follow the instructions below.

```{r}
library(configr)
config.json <- system.file('extdata', 'config.json', package='configr')
config.ini <- system.file('extdata', 'config.ini', package='configr')
config.yaml <- system.file('extdata', 'config.yaml', package='configr')
config.toml <- system.file('extdata', 'config.toml', package='configr')
config.glob <- system.file('extdata', 'config.global.toml', package='configr')
```

## Check the configuration file type

`is.json.file`, `is.ini.file`, `is.yaml.file` and `is.toml.file` can be used to check the configuration file type. If input file were coincident with required, it will return TRUE. `get.config.type` will using above functions and get the file type name: json, ini, yaml, toml or FALSE.

```{r, echo = TRUE}
is.json.file(config.json)
is.toml.file(config.toml)
is.ini.file(config.ini)
is.yaml.file(config.yaml)
get.config.type(config.json)
get.config.type(config.yaml)
get.config.type(config.ini)
get.config.type(config.toml)
```

## Get the configuration section names

Section names of configuration file can be get using `eval.config.sections`. Python package [ConfigParser](https://pypi.python.org/pypi/configparser) `sections` inspired us to add this function.

```{r, echo = TRUE}
eval.config.sections(config.ini)
eval.config.sections(config.toml)
```

## Read the configuration file

`read.config` can read a configuration file in R and as a list object that can pass parameter to inner read function (fromJSON/read.ini/yaml.load_file/parseToml) accordingly.

```{r, echo = TRUE}
# Read in R as a list (JSON/INI/YAML/TOML be suported)
# fromJSON/read.ini/readLines/yaml.load  parameters can be automatch by parameter name (encoding .etc.)
read.config(file = config.toml)
```

`eval.config` return a value or a list object containing the file path, config group, filetype as the attribute.

```{r, echo = TRUE}
# Get the same obj with config package, only get the 
# 'default or R_CONFIG_ACTIVE config sets' in config.cfg or R_CONFIGFILE_ACTIVE
eval.config(file = config.yaml)

# Read designated section
eval.config(file = config.json, config = "comments")

# Read designated section with its one value
eval.config(file = config.ini, config = "comments", value = "version")
```

`eval.config.merge` will merge multiple sections (equal to `config` in `eval.config` function) and reduce the layer of configuration file.

```{r, echo = TRUE}
eval.config.merge(file = config.json, sections = c('default', 'comments'))
eval.config.merge(file = config.toml, sections = c('default', 'comments'))
```

`fetch.config` can parse configuration files from internet and local that merged the files and return a list.

```{r, echo = TRUE}
links <- c("https://raw.githubusercontent.com/JhuangLab/BioInstaller/master/inst/extdata/config/db/db_annovar.toml", 
           "https://raw.githubusercontent.com/JhuangLab/BioInstaller/master/inst/extdata/config/db/db_main.toml", 
           system.file('extdata', 'config.toml', package = "configr"))
x <- fetch.config(links)
x[c(1:5, length(x))]
```

## Converting and writing configuration file

`convert.config` will read a configuration file and write a configuration file with appointed file type (json. ini, yaml). Moreover, `write.config` is similar to `convert.config` but using the list object rather than a file.

```{r, echo = TRUE}
# Convert YAML configuration file to JSON format
out.json <- tempfile(fileext = ".json")
convert.config(file = config.yaml, out.file = out.json, convert.to = "JSON")
get.config.type(out.json)

# Generate a JSON format configuration file
list.test <- list(a=c(123,456))
out.fn <- sprintf("%s/test.json", tempdir())
write.config(config.dat = list.test, file.path = out.fn, write.type = "json")
get.config.type(out.fn)

# Generate a YAML format configuration file with defined indent
write.config(config.dat = list.test, file.path = out.fn, write.type = "yaml", indent = 4)
get.config.type(out.fn)

# Generate a YAML format configuration file with defined indent and pointed sections
#write.config(config.dat = list.test, file.path = out.fn, write.type = "yaml", sections = "a", indent = 4)
#get.config.type(out.fn)
```

## Configr specific extra parse

configr own several userful extra parse function, you can use the `parse.extra` to finish these work for any list object. Of course, `read.config`, `eval.config` and `eval.config.merge` can directly using `parse.extra` by passing parameters to `parse.extra`.

- `extra.list` can be used to parse the value of `{{debug}}` to `self` if you setted `extra.list = list(debug = 'self')`
- `other.config` can be used to parse the value of `{{key:yes_flag}}` to `yes` if you setted `other.config = system.file('extdata', 'config.other.yaml', package='configr')` which content can be founded below.
- `rcmd.parse` can be used to parse the value of `@>@str_replace('config','g$','gr')@<@` to `configr` if you setted `rcmd.parse = TRUE`.
- `bash.parse` can be used to parse the value of `#>#echo bash#<#` to `bash` if you setted `bash.parse = TRUE`.
- `glue.parse` can be used to paste the value of `!!glue {1:5}` to `["1", "2", "3", "4", "5"]`; `!!glue_numeric {1:5}` to [1, 2, 3, 4, 5] 
- `global.vars.field` can be used to parse the internal values using the given top level fields default use `global_vars` (new feature in v0.3.4)

**Note:** `glue.parse` using the `glue` package `glue` function to do that. Just like glue('{1:5}') and be processed by unname(unlist(x)). 
The `!!glue` can be changed if you setted `glue.flag`. It is a remarkable fact that only contain the `glue.flag` character be parsed and the order of item will be changed if the `glue` result were multiple values. e.g. `['{a}', '!!glue {1:5}', '{{a}}']` will be parsed to `['{a}', '1', '2', '3', '4', '5', '{{a}}']`

```{r, echo = TRUE}
other.config <- system.file('extdata', 'config.other.yaml', package='configr')

read.config(file = other.config)

config.1 <- read.config(file = config.json)
config.1$default
read.config(file = config.json, extra.list = list(debug = "self", debug2 = "self2"))$default

sections <- c('default', 'other_config_parse')
config.1[sections]
read.config(file = config.json, extra.list = list(debug = "self", debug2 = "self2"), 
  other.config = other.config)[sections]

sections <- c('default', 'other_config_parse', 'rcmd_parse')
# The followed two line command will return the same value
config.1[sections]
read.config(file = config.json, extra.list = list(debug = "self", debug2 = "self2"), 
  other.config = other.config, rcmd.parse = T)[sections]
parse.extra(config.1, extra.list = list(debug = "self", debug2 = "self2"), 
  other.config = other.config, rcmd.parse = T)[sections]


sections <- c('default', 'other_config_parse', 'rcmd_parse', 'mulitple_parse')
config.1[sections]
parse.extra(config.1, extra.list = list(debug = "self", debug2 = "self2", yes = "1", no = "0"), 
  other.config = other.config, rcmd.parse = T, bash.parse = T)[sections]

# glue parse
raw <- c("a", "!!glue{1:5}", "c")
list.raw <- list(glue = raw, nochange = 1:10)
list.raw
expect.parsed.1 <- c("a", "1", "2", "3", "4", "5", "c")
expect.parsed.2 <- list(glue = expect.parsed.1, nochange = 1:10)
parse.extra(list.raw, glue.parse = TRUE, glue.flag = "!!glue")


read.config(config.glob, global.vars.field = NULL)

read.config(config.glob)

```

## External urls about configuration format and others

configr provides a function `config.help` to access external resource about various configuration format and other related materies.

```r
Show all external urls stored in configr
config.help()
# Open item in browser
# config.help('toml_stackoverflow_search')
# Or use the row number to access
# config.help(23)
```

## Others usage

`config.section.del` can be used to delete a section of config, just do `config$section <- NULL`.

``` {r, echo = TRUE}
config <- read.config(file = config.json, extra.list = list(debug = "self", debug2 = "self2"), 
  other.config = other.config)[sections]
names(config)
config <- config.sections.del(config, 'default')
names(config)
```

`str2config` can be used to parse a string object to a configuration list

```{r, echo = TRUE}
json_string <- '{"city" : "Crich"}\n'
yaml_string <- 'foo: 123\n'
json_config <- str2config(json_string)
yaml_config <- str2config(yaml_string)
print(json_config)
print(yaml_config)
```

## Session info

Here is the output of `sessionInfo()` on the system on which this document was compiled:

```{r echo=FALSE}
sessionInfo()
```
