# 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. ![](yns/yns.svg) ### 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 `` - if `replace me` is a member of list, replace itself to `` The scheme program using `libyaml` can be: ```lisp (import libyaml) (call-with-input-file "/tmp/tmp.yaml" (lambda (yaml) (let* ( (yaml ((yaml->ss yaml))) ; don't forget to index document from procedure ) (define (replace-replace-me Y) (cond ((ymap? Y) (let ((alist (car Y))) (list ; Don't forget to wrap alist to match yaml-mapping format here (map (lambda (pair) (if (equal? (car pair) "replace me") (cons (car pair) "") (cons (replace-replace-me (car pair)) (replace-replace-me (cdr pair))) )) alist ) ) )) ((yseq? Y) (let ((slist (vector->list Y))) (list->vector ; Don't forget to convert back to vector to match yaml-list format here (map (lambda (list-unit) (if (equal? list-unit "replace me") "" (replace-replace-me list-unit) )) slist ) ) )) (else Y) )) (ss->yaml (replace-replace-me yaml)) ) )) ``` Save the yaml content to `/tmp/tmp.yaml`, save the scheme program to `/tmp/tmp.ss`, `csi -s tmp.ss` will generate: ```yaml --- - replace me: - a internal mapping: replace me: - - - - ignored - '3.32' - 3.32 ... ``` ---

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)))) ```
--- Besides, [yns/](yns/) provide some example to convert [yns/yns.yaml](yns/yns.yaml) to different formats. And actually chart in *yaml and scheme* section was from programs in [yns/](yns/). It was recommended to begin with [yns/yns.yaml2html.ss](yns/yns.yaml2html.ss) because it is much simpler than others. ## License MIT