# libyaml.ss This is a chicken scheme egg, section structure will follow - [http://wiki.call-cc.org/eggs%20tutorial#sections](http://wiki.call-cc.org/eggs%20tutorial#sections) ## Authors - [riku-ri@outlook.com](riku-ri@outlook.com) ## Repository [https://codeberg.org/rikuri/libyaml.ss/](https://codeberg.org/rikuri/libyaml.ss/) ## Requirements - varg - https://codeberg.org/rikuri/varg.ss ## API ``` (import libyaml) ``` ### Exception Exceptions is supposed to be compliant with the module `(chicken condition)` and SRFI-12 - http://wiki.call-cc.org/man/5/Module%20(chicken%20condition) Find details about exception in the specific procedure below #### non-continuable The non-continuable conditions expand system conditions from: - http://wiki.call-cc.org/man/5/Module%20(chicken%20condition)#system-conditions More specifically, they would be: - be with composite kind `(exn libfyaml)` - for a condition from a specific procedure `
`, the composite kind would be `(exn libfyaml
)`
- in the `exn` field, it will contain properties listed below:
- `'message`
> Note that it is lib**f**yaml but not libyaml.
> [dev.md](dev.md) explain it.
### Values in `libfyaml.h` `libfyaml-core.h`
`(import libyaml)` will
export enum members and functions in
[`../git/libfyaml/include/libfyaml.h`]() and
[`../git/libfyaml/include/libfyaml/libfyaml-core.h`]()
**Prevent** using dynamic argument list function(`printf` like),
because chicken-scheme does not support.
Functions and enum members can be used in scheme code as
scheme variable or procedure.
> Note that you may install libfyaml development package in your system,
> but sources in submodule will be used instead of development package in system
### yaml and scheme
The chart below define mapping between yaml structure and scheme structure.

### Read yaml
```lisp
(yaml->ss |Parameters|)
```
#### Return value
`yaml->ss` will return a procedure that generate yaml-documents:
- the **procedure** take 1 or no parameter
- if 1 parameter, it must be a non-negative integer or `-1`
- for `-1`, return a scheme-list of all yaml-document
- for positive integer ***n***, return the ***n-1***th document.
Index from `0` but not `1`
- if no parameter, return the 1st document.
Equal to parameter is `0`
For example:
| code | return value |
|-|-|
| `(yaml->ss "--- 1\n--- 2\n...")` | a procedure |
| `((yaml->ss "--- 1\n--- 2\n..."))` | `1` |
| `((yaml->ss "--- 1\n--- 2\n...") 0)` | `1` |
| `((yaml->ss "--- 1\n--- 2\n...") 1)` | `2` |
| `((yaml->ss "--- 1\n--- 2\n...") -1)` | `'(1 2)` |
| `((yaml->ss "--- 1\n--- 2\n...") 2)` | *abort* |
#### Parameters
- Where to read yaml
> For example `(yaml->ss "[1,[2],3]")`,
> `(call-will-input-file "/tmp/tmp.yaml" (lambda (file) (yaml->ss file)))`
- Must be a string or input port
- If not set, like `(yaml->ss)`, will read from `(current-input-port)`
- NOTE that the port will not be closed insied `yaml->ss`,
even if it abort a condition
#### Examples
```lisp
((yaml->ss "--- 1\n--- 2\n...") 1)
```
```lisp
(yaml->ss
(open-input-file "/dev/null")
)
```
```lisp
(call-with-input-file "/dev/null"
(lambda (file) (display ((yaml->ss file) -1)))
)
```
### Dump yaml
```
(ss->yaml |Parameters|)
```
#### Return value
Usually the return value of `ss->yaml` is useless.
But if you wan to known it,
`ss->yaml` will call the C function `fy_emitter_destroy()`
to free resource, so it is `void`.
#### Parameters
- The data to output, defined in *yaml and scheme* section
> For example `(ss->yaml 2)`, `2` is the data to output here
- `(cons #:output ...)` where to output yaml
> For example
> `(call-with-output-file "2yaml.yaml" (lambda (file) (ss->yaml (cons #:output file) 3)))`
> will output `3` to file `2yaml.yaml`
- Where `...` should be a output port.
- If not set, will output to `(current-output-port)`
- NOTE that the port will not be closed insied `ss->yaml`,
even if it abort a condition
- `(list #:flags ...)` flags to the libfyaml emitter.
> For example `(ss->yaml 2 (list #:flags FYECF_INDENT_4 FYECF_WIDTH_INF))`
- Where `...` should be members of `enum fy_emitter_cfg_flags`,
- Flags are defined in `libfyaml-core.h`.
Read the header source file for more details. Here is some common flags:
- `FYECF_INDENT_1` to `FYECF_INDENT_9` and `FYECF_INDENT_DEFAULT`
to set the indent
- `FYECF_WIDTH_80` `FYECF_WIDTH_132` to set max width to 80 or 132
- `FYECF_MODE_BLOCK` `FYECF_MODE_FLOW` to set the output style, block or flow
- `FYECF_DOC_START_MARK_ON` `FYECF_DOC_START_MARK_OFF`,
to set if omit the document start/end marker `---`
- If not set, use these flags by default:
- `FYECF_INDENT_2`
- `FYECF_VERSION_DIR_OFF`
- `FYECF_MODE_BLOCK`
- `FYECF_WIDTH_INF`
- `#:strict-input` check the input is strict format as `yaml->ss` return value
> For example `(ss->yaml #:strict-input (yaml->ss "[1]"))`
- If not set, dangling scalar values, vector(as yaml list), etc
could be output too.
#### Tips
##### Indent
libfyaml set indent by flags to emitter,
refer to the parameter of *Dump yaml* section
#### Examples
```lisp
(ss->yaml #:strict-input (yaml->ss "[1]"))
```
```lisp
(ss->yaml ((yaml->ss "[1]")))
```
```lisp
(ss->yaml #("1st" ()))
```
```lisp
(ss->yaml `(#:output . ,(current-output-port))
`(#:flags ,FYECF_INDENT_5 ,FYECF_WIDTH_80)
(string-append (make-string 70 #\X) "\n" (make-string 20 #\X)))
```
### Check the structure
All check are supposed to be based on definition in *yaml and scheme* section.
---
```lisp
(yaml? ?)
(ydoc? ?)
```
Check if `?` is a scheme structure that match a yaml-documents
`ydoc?` just check if the procedure valid when take `-1` as parameter.
`yaml?` will check if `?` totally match
the format of `yaml->ss` return value
---
```lisp
(ymap? ?)
(ymap?? ?)
```
Check if `?` is a scheme structure that match a yaml-mapping
`ymap?` only check the top level, a list that only contain 1 alist
`ymap??` will recursively check if each part of `?` is a legal structure
---
```lisp
(ylist? ?)
(ylist?? ?)
(yseq? ?)
(yseq?? ?)
```
Similar to `ymap?` and `ymap??` but check yaml-list not yaml-mapping
---
```lisp
(yscalar? ?)
```
Check if `?` is a scheme object that match to a yaml-scalar
---
## Examples
In the API section, in each API subsection,
there are examples for single call at the tail of subsection.
And here is a complete example including read/write/modify.
For a yaml content:
```yaml
- replace me: This will be changed
- a internal mapping:
replace me: This will be changed
- replace me
- - replace me
- ignored
- "3.32" # string , also ignored
- 3.32 # number, also ignored
```
Assuming it was saved in file `/tmp/tmp.yaml`,
we don't know the content of it,
but we need to modify its content:
- if `replace me` is a key of mapping, replace the value to `Here are some small examples showing in egg page:
```lisp
(yaml->ss "--- 1\n--- 2\n...") ;will return a procedure
((yaml->ss "--- 1\n--- 2\n...")) ;will return 1
((yaml->ss "--- 1\n--- 2\n...") 0) ;will return 1
((yaml->ss "--- 1\n--- 2\n...") 1) ;will return 2
((yaml->ss "--- 1\n--- 2\n...") -1) ;will return '(1 2)
((yaml->ss "--- 1\n--- 2\n...") 2) ;will abort by exception
(yaml->ss) ;will try to read yaml from (current-input-port) and return a procedure
(call-with-input-file "you-need-to-create-this.yaml"
(lambda (input-port) (yaml->ss input-port))
)
; will try to read yaml from the file `you-need-to-create-this.yaml`
; and return a procedure
```
```lisp
(ss->yaml #:strict-input (yaml->ss "[1]"))
(ss->yaml ((yaml<- "[1]")))
(ss->yaml #("1st" ()))
(call-with-output-file "create-by-example.yaml"
(lambda (port)
(ss->yaml `(#:output . ,port)
((yaml->ss "---\n---\n---\n[1,2,3]") 2))))
```