1
1
mirror of https://github.com/wader/fq.git synced 2024-11-21 23:04:07 +03:00

yaml,toml: Add indent option for to_{toml,yaml}

This commit is contained in:
Mattias Wadman 2024-11-20 11:50:28 +01:00
parent 6ac571300a
commit ed872d4b07
7 changed files with 114 additions and 30 deletions

View File

@ -682,18 +682,20 @@ name: Afghanistan
zip> ^D zip> ^D
``` ```
- `from_xml`/`from_xml($opts)` Parse XML into jq value.<br> - `from_xml`/`from_xml($opts)` Parse XML into jq value. `$opts` are:
`{seq: true}` preserve element ordering if more than one sibling.<br> - `{seq: true}` preserve element ordering if more than one sibling.<br>
`{array: true}` use nested `[name, attributes, children]` arrays to represent elements. Attributes will be `null` if none and children will be `[]` if none, this is to make it easier to work with as the array as 3 values. `to_xml` does not require this.<br> - `{array: true}` use nested `[name, attributes, children]` arrays to represent elements. Attributes will be `null` if none and children will be `[]` if none, this is to make it easier to work with as the array as 3 values. `to_xml` does not require this.<br>
- `from_html`/`from_html($opts)` Parse HTML into jq value.<br> - `from_html`/`from_html($opts)` Parse HTML into jq value.<br>
Similar to `from_xml` but parses html5 in non-script mode. Will always have a `html` root with `head` and `body` elements.<br> Similar to `from_xml` but parses html5 in non-script mode. Will always have a `html` root with `head` and `body` elements.<br>
`{array: true}` use nested arrays to represent elements.<br> `$opts` are:
`{seq: true}` preserve element ordering if more than one sibling.<br> - `{array: true}` use nested arrays to represent elements.<br>
- `{seq: true}` preserve element ordering if more than one sibling.<br>
- `to_xml`/`to_xml($opts})` Serialize jq value into XML.<br> - `to_xml`/`to_xml($opts})` Serialize jq value into XML.<br>
`{indent: number}` indent child elements.<br>
Assumes object representation if input is an object, and nested arrays if input is an array.<br> Assumes object representation if input is an object, and nested arrays if input is an array.<br>
Will automatically add a root `doc` element if jq value has more then one root element.<br> Will automatically add a root `doc` element if jq value has more then one root element.<br>
If a `#seq` is found on at least one element all siblings will be sort by sequence number. Attributes are always sorted.<br> If a `#seq` is found on at least one element all siblings will be sort by sequence number. Attributes are always sorted.<br>
`$opts` are:
- `{indent: number}` indent child elements.<br>
XML elements can be represented as jq value in two ways, as objects (inspired by [mxj](https://github.com/clbanning/mxj) and [xml.com's Converting Between XML and JSON XML elements can be represented as jq value in two ways, as objects (inspired by [mxj](https://github.com/clbanning/mxj) and [xml.com's Converting Between XML and JSON
](https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html)) or nested arrays. Both representations are lossy and might lose ordering of elements, text nodes and comments. In object representation `from_xml`, `from_html` and `to_xml` support `{seq:true}` option to parse/serialize `{"#seq"=<number>}` attributes to preserve element sibling ordering. ](https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html)) or nested arrays. Both representations are lossy and might lose ordering of elements, text nodes and comments. In object representation `from_xml`, `from_html` and `to_xml` support `{seq:true}` option to parse/serialize `{"#seq"=<number>}` attributes to preserve element sibling ordering.
@ -801,12 +803,11 @@ zip> ^D
JSON and jq-flavoured JSON JSON and jq-flavoured JSON
- `fromjson` Parse JSON into jq value. - `fromjson` Parse JSON into jq value.
- `tojson`/`tojson($opt)` Serialize jq value into JSON.<br> - `tojson`/`tojson($opts)` Serialize jq value into JSON. `$opts` are:
`{indent: number}` indent array/object values.<br> - `{indent: number}` Indent depth.
- `from_jq` Parse jq-flavoured JSON into jq value. - `from_jq` Parse jq-flavoured JSON into jq value.
- `to_jq`/`to_jq($opt)` Serialize jq value into jq-flavoured JSON<br> - `to_jq`/`to_jq($opts)` Serialize jq value into jq-flavoured JSON. jq-flavoured JSON has optional key quotes, `#` comments and can have trailing comma in arrays. `$opts` are:
`{indent: number}` indent array/object values.<br> - `{indent: number}` Indent depth.
jq-flavoured JSON has optional key quotes, `#` comments and can have trailing comma in arrays.
- `from_jsonl` Parse JSON lines into jq array. - `from_jsonl` Parse JSON lines into jq array.
- `to_jsonl` Serialize jq array into JSONL. - `to_jsonl` Serialize jq array into JSONL.
@ -814,19 +815,22 @@ Note that `fromjson` and `tojson` use different naming conventions as they origi
YAML YAML
- `from_yaml` Parse YAML into jq value. - `from_yaml` Parse YAML into jq value.
- `to_yaml` Serialize jq value into YAML. - `to_yaml`/`to_yaml($opts)` Serialize jq value into YAML. `$opts` are:
- `{indent: number}` Indent depth.
TOML TOML
- `from_toml` Parse TOML into jq value. - `from_toml` Parse TOML into jq value.
- `to_toml` Serialize jq value into TOML. - `to_toml`/`to_toml($opts)` Serialize jq value into TOML. `$opts` are:
- `{indent: number}` Indent depth.
CSV CSV
- `from_csv`/`from_cvs($opts)` Parse CSV into jq value.<br> - `from_csv`/`from_cvs($opts)` Parse CSV into jq value.<br>
`{comma: string}` field separator, default ",".<br> To work with tab separated values you can use `fromcvs({comma: "\t"})` or `fq -d csv -o 'comma="\t"'`<br>
`{comment: string}` comment line character, default "#".<br> `$opts` are:
To work with tab separated values you can use `fromcvs({comma: "\t"})` or `fq -d csv -o 'comma="\t"'` - `{comma: string}` field separator, default ",".<br>
- `to_csv`/`to_csv($opts)` Serialize jq value into CSV.<br> - `{comment: string}` comment line character, default "#".<br>
`{comma: string}` field separator, default ",".<br> - `to_csv`/`to_csv($opts)` Serialize jq value into CSV. `$opts` are:
- `{comma: string}` field separator, default ",".<br>
XML encoding XML encoding
- `from_xmlentities` Decode XML entities. - `from_xmlentities` Decode XML entities.
@ -862,10 +866,10 @@ URL parts and XML encodings
Binary encodings like hex and base64 Binary encodings like hex and base64
- `from_hex` Decode hex string to binary. - `from_hex` Decode hex string to binary.
- `to_hex` Encode binary into hex string. - `to_hex` Encode binary into hex string.
- `from_base64`/`from_base64($opts)` Decode base64 encodings into binary.<br> - `from_base64`/`from_base64($opts)` Decode base64 encodings into binary. `$opts` are:
`{encoding:string}` encoding variant: `std` (default), `url`, `rawstd` or `rawurl` - `{encoding:string}` encoding variant: `std` (default), `url`, `rawstd` or `rawurl`
- `to_base64`/`to_base64($opts)` Encode binary into base64 encodings.<br> - `to_base64`/`to_base64($opts)` Encode binary into base64 encodings. `$opts` are:
`{encoding:string}` encoding variant: `std` (default), `url`, `rawstd` or `rawurl` - `{encoding:string}` encoding variant: `std` (default), `url`, `rawstd` or `rawurl`
Hash functions Hash functions
- `to_md4` Hash binary using md4. - `to_md4` Hash binary using md4.

29
format/toml/testdata/indent.fqtest vendored Normal file
View File

@ -0,0 +1,29 @@
$ fq -rn "{a: {b: 123}} | to_toml"
[a]
b = 123
$ fq -rn "{a: {b: 123}} | to_toml({indent: range(8)})"
[a]
b = 123
[a]
b = 123
[a]
b = 123
[a]
b = 123
[a]
b = 123
[a]
b = 123
[a]
b = 123
[a]
b = 123

View File

@ -6,6 +6,7 @@ import (
"embed" "embed"
"fmt" "fmt"
"io" "io"
"strings"
"unicode/utf8" "unicode/utf8"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
@ -31,7 +32,7 @@ func init() {
Functions: []string{"_todisplay"}, Functions: []string{"_todisplay"},
}) })
interp.RegisterFS(tomlFS) interp.RegisterFS(tomlFS)
interp.RegisterFunc0("to_toml", toTOML) interp.RegisterFunc1("_to_toml", toTOML)
} }
func decodeTOMLSeekFirstValidRune(br io.ReadSeeker) error { func decodeTOMLSeekFirstValidRune(br io.ReadSeeker) error {
@ -88,13 +89,19 @@ func decodeTOML(d *decode.D) any {
return nil return nil
} }
func toTOML(_ *interp.Interp, c any) any { type ToTOMLOpts struct {
Indent int `default:"2"` // 2 is default for BurntSushi/toml
}
func toTOML(_ *interp.Interp, c any, opts ToTOMLOpts) any {
if c == nil { if c == nil {
return gojqx.FuncTypeError{Name: "to_toml", V: c} return gojqx.FuncTypeError{Name: "to_toml", V: c}
} }
b := &bytes.Buffer{} b := &bytes.Buffer{}
if err := toml.NewEncoder(b).Encode(gojqx.Normalize(c)); err != nil { e := toml.NewEncoder(b)
e.Indent = strings.Repeat(" ", opts.Indent)
if err := e.Encode(gojqx.Normalize(c)); err != nil {
return err return err
} }
return b.String() return b.String()

View File

@ -1 +1,3 @@
def _toml__todisplay: tovalue; def _toml__todisplay: tovalue;
def to_toml($opts): _to_toml($opts);
def to_toml: _to_toml(null);

29
format/yaml/testdata/indent.fqtest vendored Normal file
View File

@ -0,0 +1,29 @@
$ fq -rn "{a: {b: 123}} | to_yaml"
a:
b: 123
$ fq -rn "{a: {b: 123}} | to_yaml({indent: range(8)})"
a:
b: 123
a:
b: 123
a:
b: 123
a:
b: 123
a:
b: 123
a:
b: 123
a:
b: 123
a:
b: 123

View File

@ -3,6 +3,7 @@ package yaml
// TODO: yaml type eval? walk eval? // TODO: yaml type eval? walk eval?
import ( import (
"bytes"
"embed" "embed"
"errors" "errors"
"io" "io"
@ -30,7 +31,7 @@ func init() {
Functions: []string{"_todisplay"}, Functions: []string{"_todisplay"},
}) })
interp.RegisterFS(yamlFS) interp.RegisterFS(yamlFS)
interp.RegisterFunc0("to_yaml", toYAML) interp.RegisterFunc1("_to_yaml", toYAML)
} }
func decodeYAML(d *decode.D) any { func decodeYAML(d *decode.D) any {
@ -61,10 +62,20 @@ func decodeYAML(d *decode.D) any {
return nil return nil
} }
func toYAML(_ *interp.Interp, c any) any { type ToYAMLOpts struct {
b, err := yaml.Marshal(gojqx.Normalize(c)) Indent int `default:"4"` // 4 is default for gopkg.in/yaml.v3
if err != nil { }
func toYAML(_ *interp.Interp, c any, opts ToYAMLOpts) any {
b := &bytes.Buffer{}
e := yaml.NewEncoder(b)
// yaml.SetIndent panics if < 0
if opts.Indent >= 0 {
e.SetIndent(opts.Indent)
}
if err := e.Encode(gojqx.Normalize(c)); err != nil {
return err return err
} }
return string(b)
return b.String()
} }

View File

@ -1 +1,3 @@
def _yaml__todisplay: tovalue; def _yaml__todisplay: tovalue;
def to_yaml($opts): _to_yaml($opts);
def to_yaml: _to_yaml(null);