mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-06 13:25:42 +00:00
wip
This commit is contained in:
parent
2b2c285415
commit
fc5595d0e9
@ -1,4 +1,4 @@
|
|||||||
package yqlib
|
package properties
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -8,16 +8,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type propertiesDecoder struct {
|
type propertiesDecoder struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
finished bool
|
finished bool
|
||||||
d DataTreeNavigator
|
d yqlib.DataTreeNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPropertiesDecoder() Decoder {
|
func NewPropertiesDecoder() yqlib.Decoder {
|
||||||
return &propertiesDecoder{d: NewDataTreeNavigator(), finished: false}
|
return &propertiesDecoder{d: yqlib.NewDataTreeNavigator(), finished: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *propertiesDecoder) Init(reader io.Reader) error {
|
func (dec *propertiesDecoder) Init(reader io.Reader) error {
|
||||||
@ -47,31 +48,31 @@ func (dec *propertiesDecoder) processComment(c string) string {
|
|||||||
return "# " + c
|
return "# " + c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *propertiesDecoder) applyPropertyComments(context Context, path []interface{}, comments []string) error {
|
func (dec *propertiesDecoder) applyPropertyComments(context yqlib.Context, path []interface{}, comments []string) error {
|
||||||
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
assignmentOp := &yqlib.Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
|
||||||
|
|
||||||
rhsCandidateNode := &CandidateNode{
|
rhsCandidateNode := &yqlib.CandidateNode{
|
||||||
Tag: "!!str",
|
Tag: "!!str",
|
||||||
Value: fmt.Sprintf("%v", path[len(path)-1]),
|
Value: fmt.Sprintf("%v", path[len(path)-1]),
|
||||||
HeadComment: dec.processComment(strings.Join(comments, "\n")),
|
HeadComment: dec.processComment(strings.Join(comments, "\n")),
|
||||||
Kind: ScalarNode,
|
Kind: yqlib.ScalarNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
rhsCandidateNode.Tag = rhsCandidateNode.guessTagFromCustomType()
|
rhsCandidateNode.Tag = rhsCandidateNode.GuessTagFromCustomType()
|
||||||
|
|
||||||
rhsOp := &Operation{OperationType: referenceOpType, CandidateNode: rhsCandidateNode}
|
rhsOp := &yqlib.Operation{OperationType: referenceOpType, CandidateNode: rhsCandidateNode}
|
||||||
|
|
||||||
assignmentOpNode := &ExpressionNode{
|
assignmentOpNode := &yqlib.ExpressionNode{
|
||||||
Operation: assignmentOp,
|
Operation: assignmentOp,
|
||||||
LHS: createTraversalTree(path, traversePreferences{}, true),
|
LHS: createTraversalTree(path, traversePreferences{}, true),
|
||||||
RHS: &ExpressionNode{Operation: rhsOp},
|
RHS: &yqlib.ExpressionNode{Operation: rhsOp},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := dec.d.GetMatchingNodes(context, assignmentOpNode)
|
_, err := dec.d.GetMatchingNodes(context, assignmentOpNode)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *propertiesDecoder) applyProperty(context Context, properties *properties.Properties, key string) error {
|
func (dec *propertiesDecoder) applyProperty(context yqlib.Context, properties *properties.Properties, key string) error {
|
||||||
value, _ := properties.Get(key)
|
value, _ := properties.Get(key)
|
||||||
path := parsePropKey(key)
|
path := parsePropKey(key)
|
||||||
|
|
||||||
@ -84,12 +85,12 @@ func (dec *propertiesDecoder) applyProperty(context Context, properties *propert
|
|||||||
}
|
}
|
||||||
|
|
||||||
rhsNode := createStringScalarNode(value)
|
rhsNode := createStringScalarNode(value)
|
||||||
rhsNode.Tag = rhsNode.guessTagFromCustomType()
|
rhsNode.Tag = rhsNode.GuessTagFromCustomType()
|
||||||
|
|
||||||
return dec.d.DeeplyAssign(context, path, rhsNode)
|
return dec.d.DeeplyAssign(context, path, rhsNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
func (dec *propertiesDecoder) Decode() (*yqlib.CandidateNode, error) {
|
||||||
if dec.finished {
|
if dec.finished {
|
||||||
return nil, io.EOF
|
return nil, io.EOF
|
||||||
}
|
}
|
||||||
@ -108,12 +109,12 @@ func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
|
|||||||
}
|
}
|
||||||
properties.DisableExpansion = true
|
properties.DisableExpansion = true
|
||||||
|
|
||||||
rootMap := &CandidateNode{
|
rootMap := &yqlib.CandidateNode{
|
||||||
Kind: MappingNode,
|
Kind: yqlib.MappingNode,
|
||||||
Tag: "!!map",
|
Tag: "!!map",
|
||||||
}
|
}
|
||||||
|
|
||||||
context := Context{}
|
context := yqlib.Context{}
|
||||||
context = context.SingleChildContext(rootMap)
|
context = context.SingleChildContext(rootMap)
|
||||||
|
|
||||||
for _, key := range properties.Keys() {
|
for _, key := range properties.Keys() {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package yqlib
|
package properties
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@ -8,13 +8,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/magiconair/properties"
|
"github.com/magiconair/properties"
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type propertiesEncoder struct {
|
type propertiesEncoder struct {
|
||||||
prefs PropertiesPreferences
|
prefs PropertiesPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPropertiesEncoder(prefs PropertiesPreferences) Encoder {
|
func NewPropertiesEncoder(prefs PropertiesPreferences) yqlib.Encoder {
|
||||||
return &propertiesEncoder{
|
return &propertiesEncoder{
|
||||||
prefs: prefs,
|
prefs: prefs,
|
||||||
}
|
}
|
||||||
@ -61,9 +62,9 @@ func (pe *propertiesEncoder) PrintLeadingContent(writer io.Writer, content strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
func (pe *propertiesEncoder) Encode(writer io.Writer, node *yqlib.CandidateNode) error {
|
||||||
|
|
||||||
if node.Kind == ScalarNode {
|
if node.Kind == yqlib.ScalarNode {
|
||||||
return writeString(writer, node.Value+"\n")
|
return writeString(writer, node.Value+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateNode, path string, keyNode *CandidateNode) error {
|
func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yqlib.CandidateNode, path string, keyNode *CandidateNode) error {
|
||||||
|
|
||||||
comments := ""
|
comments := ""
|
||||||
if keyNode != nil {
|
if keyNode != nil {
|
||||||
@ -91,7 +92,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateN
|
|||||||
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
|
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
|
||||||
|
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case ScalarNode:
|
case yqlib.ScalarNode:
|
||||||
var nodeValue string
|
var nodeValue string
|
||||||
if pe.prefs.UnwrapScalar || !strings.Contains(node.Value, " ") {
|
if pe.prefs.UnwrapScalar || !strings.Contains(node.Value, " ") {
|
||||||
nodeValue = node.Value
|
nodeValue = node.Value
|
||||||
@ -100,11 +101,11 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateN
|
|||||||
}
|
}
|
||||||
_, _, err := p.Set(path, nodeValue)
|
_, _, err := p.Set(path, nodeValue)
|
||||||
return err
|
return err
|
||||||
case SequenceNode:
|
case yqlib.SequenceNode:
|
||||||
return pe.encodeArray(p, node.Content, path)
|
return pe.encodeArray(p, node.Content, path)
|
||||||
case MappingNode:
|
case yqlib.MappingNode:
|
||||||
return pe.encodeMap(p, node.Content, path)
|
return pe.encodeMap(p, node.Content, path)
|
||||||
case AliasNode:
|
case yqlib.AliasNode:
|
||||||
return pe.doEncode(p, node.Alias, path, nil)
|
return pe.doEncode(p, node.Alias, path, nil)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported node %v", node.Tag)
|
return fmt.Errorf("Unsupported node %v", node.Tag)
|
||||||
@ -125,7 +126,7 @@ func (pe *propertiesEncoder) appendPath(path string, key interface{}) string {
|
|||||||
return fmt.Sprintf("%v.%v", path, key)
|
return fmt.Sprintf("%v.%v", path, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*CandidateNode, path string) error {
|
func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yqlib.CandidateNode, path string) error {
|
||||||
for index, child := range kids {
|
for index, child := range kids {
|
||||||
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
|
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -135,7 +136,7 @@ func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*Candi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*CandidateNode, path string) error {
|
func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*yqlib.CandidateNode, path string) error {
|
||||||
for index := 0; index < len(kids); index = index + 2 {
|
for index := 0; index < len(kids); index = index + 2 {
|
||||||
key := kids[index]
|
key := kids[index]
|
||||||
value := kids[index+1]
|
value := kids[index+1]
|
||||||
44
pkg/properties/properties.go
Normal file
44
pkg/properties/properties.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package properties
|
||||||
|
|
||||||
|
import "github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
|
|
||||||
|
type PropertiesPreferences struct {
|
||||||
|
UnwrapScalar bool
|
||||||
|
KeyValueSeparator string
|
||||||
|
UseArrayBrackets bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultPropertiesPreferences() PropertiesPreferences {
|
||||||
|
return PropertiesPreferences{
|
||||||
|
UnwrapScalar: true,
|
||||||
|
KeyValueSeparator: " = ",
|
||||||
|
UseArrayBrackets: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PropertiesPreferences) Copy() PropertiesPreferences {
|
||||||
|
return PropertiesPreferences{
|
||||||
|
UnwrapScalar: p.UnwrapScalar,
|
||||||
|
KeyValueSeparator: p.KeyValueSeparator,
|
||||||
|
UseArrayBrackets: p.UseArrayBrackets,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var PropertiesFormat = &yqlib.Format{"props", []string{"p", "properties"},
|
||||||
|
func() yqlib.Encoder { return NewPropertiesEncoder(ConfiguredPropertiesPreferences) },
|
||||||
|
func() yqlib.Decoder { return NewPropertiesDecoder() },
|
||||||
|
}
|
||||||
|
|
||||||
|
var propertyYqRules = []*yqlib.ParticipleYqRule{
|
||||||
|
{"PropertiesDecode", `from_?props|@propsd`, decodeOp(PropertiesFormat), 0},
|
||||||
|
{"PropsEncode", `to_?props|@props`, encodeWithIndent(PropertiesFormat, 2), 0},
|
||||||
|
{"LoadProperties", `load_?props`, loadOp(NewPropertiesDecoder(), false), 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterPropertiesFormat() {
|
||||||
|
yqlib.RegisterFormat(PropertiesFormat)
|
||||||
|
yqlib.RegisterRules(propertyYqRules)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var ConfiguredPropertiesPreferences = NewDefaultPropertiesPreferences()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//go:build !yq_noxml
|
//go:build !yq_noxml
|
||||||
|
|
||||||
package yqlib
|
package xml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
"golang.org/x/net/html/charset"
|
"golang.org/x/net/html/charset"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ type xmlDecoder struct {
|
|||||||
prefs XmlPreferences
|
prefs XmlPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewXMLDecoder(prefs XmlPreferences) Decoder {
|
func NewXMLDecoder(prefs XmlPreferences) yqlib.Decoder {
|
||||||
return &xmlDecoder{
|
return &xmlDecoder{
|
||||||
finished: false,
|
finished: false,
|
||||||
prefs: prefs,
|
prefs: prefs,
|
||||||
@ -35,8 +36,8 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*CandidateNode, error) {
|
func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yqlib..CandidateNode, error) {
|
||||||
yamlNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
yamlNode := &yqlib..CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
||||||
for _, child := range nodes {
|
for _, child := range nodes {
|
||||||
yamlChild, err := dec.convertToYamlNode(child)
|
yamlChild, err := dec.convertToYamlNode(child)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,9 +64,9 @@ func (dec *xmlDecoder) processComment(c string) string {
|
|||||||
return replacement
|
return replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
|
func (dec *xmlDecoder) createMap(n *xmlNode) (*yqlib..CandidateNode, error) {
|
||||||
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
|
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
|
||||||
yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
|
yamlNode := &yqlib..CandidateNode{Kind: MappingNode, Tag: "!!map"}
|
||||||
|
|
||||||
if len(n.Data) > 0 {
|
if len(n.Data) > 0 {
|
||||||
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
|
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
|
||||||
@ -81,7 +82,7 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
|
|||||||
label := keyValuePair.K
|
label := keyValuePair.K
|
||||||
children := keyValuePair.V
|
children := keyValuePair.V
|
||||||
labelNode := createScalarNode(label, label)
|
labelNode := createScalarNode(label, label)
|
||||||
var valueNode *CandidateNode
|
var valueNode *yqlib..CandidateNode
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
@ -125,18 +126,18 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
|
|||||||
return yamlNode, nil
|
return yamlNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
|
func (dec *xmlDecoder) createValueNodeFromData(values []string) *yqlib..CandidateNode {
|
||||||
switch len(values) {
|
switch len(values) {
|
||||||
case 0:
|
case 0:
|
||||||
return createScalarNode(nil, "")
|
return createScalarNode(nil, "")
|
||||||
case 1:
|
case 1:
|
||||||
return createScalarNode(values[0], values[0])
|
return createScalarNode(values[0], values[0])
|
||||||
default:
|
default:
|
||||||
content := make([]*CandidateNode, 0)
|
content := make([]*yqlib..CandidateNode, 0)
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
content = append(content, createScalarNode(value, value))
|
content = append(content, createScalarNode(value, value))
|
||||||
}
|
}
|
||||||
return &CandidateNode{
|
return &yqlib..CandidateNode{
|
||||||
Kind: SequenceNode,
|
Kind: SequenceNode,
|
||||||
Tag: "!!seq",
|
Tag: "!!seq",
|
||||||
Content: content,
|
Content: content,
|
||||||
@ -144,7 +145,7 @@ func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
|
func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yqlib..CandidateNode, error) {
|
||||||
if len(n.Children) > 0 {
|
if len(n.Children) > 0 {
|
||||||
return dec.createMap(n)
|
return dec.createMap(n)
|
||||||
}
|
}
|
||||||
@ -164,7 +165,7 @@ func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
|
|||||||
return scalar, nil
|
return scalar, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *xmlDecoder) Decode() (*CandidateNode, error) {
|
func (dec *xmlDecoder) Decode() (*yqlib..CandidateNode, error) {
|
||||||
if dec.finished {
|
if dec.finished {
|
||||||
return nil, io.EOF
|
return nil, io.EOF
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//go:build !yq_noxml
|
//go:build !yq_noxml
|
||||||
|
|
||||||
package yqlib
|
package xml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
@ -8,6 +8,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type xmlEncoder struct {
|
type xmlEncoder struct {
|
||||||
@ -17,7 +19,7 @@ type xmlEncoder struct {
|
|||||||
leadingContent string
|
leadingContent string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewXMLEncoder(prefs XmlPreferences) Encoder {
|
func NewXMLEncoder(prefs XmlPreferences) yqlib.Encoder {
|
||||||
var indentString = ""
|
var indentString = ""
|
||||||
|
|
||||||
for index := 0; index < prefs.Indent; index++ {
|
for index := 0; index < prefs.Indent; index++ {
|
||||||
@ -39,7 +41,7 @@ func (e *xmlEncoder) PrintLeadingContent(_ io.Writer, content string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
func (e *xmlEncoder) Encode(writer io.Writer, node *yqlib.CandidateNode) error {
|
||||||
encoder := xml.NewEncoder(writer)
|
encoder := xml.NewEncoder(writer)
|
||||||
// hack so we can manually add newlines to procInst and directives
|
// hack so we can manually add newlines to procInst and directives
|
||||||
e.writer = writer
|
e.writer = writer
|
||||||
@ -79,12 +81,12 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case MappingNode:
|
case yqlib.MappingNode:
|
||||||
err := e.encodeTopLevelMap(encoder, node)
|
err := e.encodeTopLevelMap(encoder, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case ScalarNode:
|
case yqlib.ScalarNode:
|
||||||
var charData xml.CharData = []byte(node.Value)
|
var charData xml.CharData = []byte(node.Value)
|
||||||
err := encoder.EncodeToken(charData)
|
err := encoder.EncodeToken(charData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -99,7 +101,7 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
|
func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yqlib.CandidateNode) error {
|
||||||
err := e.encodeComment(encoder, headAndLineComment(node))
|
err := e.encodeComment(encoder, headAndLineComment(node))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -158,7 +160,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode
|
|||||||
return e.encodeComment(encoder, footComment(node))
|
return e.encodeComment(encoder, footComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
|
||||||
err := encoder.EncodeToken(start)
|
err := encoder.EncodeToken(start)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -166,7 +168,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, star
|
|||||||
return e.encodeComment(encoder, headComment(node))
|
return e.encodeComment(encoder, headComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
|
||||||
err := encoder.EncodeToken(start.End())
|
err := encoder.EncodeToken(start.End())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -174,7 +176,7 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start
|
|||||||
return e.encodeComment(encoder, footComment(node))
|
return e.encodeComment(encoder, footComment(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case MappingNode:
|
case MappingNode:
|
||||||
return e.encodeMap(encoder, node, start)
|
return e.encodeMap(encoder, node, start)
|
||||||
@ -238,7 +240,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
|
||||||
|
|
||||||
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
|
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -260,7 +262,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
|
|||||||
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
|
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
|
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yqlib.CandidateNode, start xml.StartElement) error {
|
||||||
log.Debug("its a map")
|
log.Debug("its a map")
|
||||||
|
|
||||||
//first find all the attributes and put them on the start token
|
//first find all the attributes and put them on the start token
|
||||||
@ -1,4 +1,6 @@
|
|||||||
package yqlib
|
package xml
|
||||||
|
|
||||||
|
import "github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
|
|
||||||
type XmlPreferences struct {
|
type XmlPreferences struct {
|
||||||
Indent int
|
Indent int
|
||||||
@ -44,3 +46,22 @@ func (p *XmlPreferences) Copy() XmlPreferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ConfiguredXMLPreferences = NewDefaultXmlPreferences()
|
var ConfiguredXMLPreferences = NewDefaultXmlPreferences()
|
||||||
|
|
||||||
|
var XMLFormat = &yqlib.Format{"xml", []string{"x"},
|
||||||
|
func() yqlib.Encoder { return NewXMLEncoder(ConfiguredXMLPreferences) },
|
||||||
|
func() yqlib.Decoder { return NewXMLDecoder(ConfiguredXMLPreferences) },
|
||||||
|
}
|
||||||
|
|
||||||
|
var xmlYqRules = []*yqlib.ParticipleYqRule{
|
||||||
|
{"XMLEncodeWithIndent", `to_?xml\([0-9]+\)`, encodeParseIndent(XMLFormat), 0},
|
||||||
|
{"XmlDecode", `from_?xml|@xmld`, decodeOp(XMLFormat), 0},
|
||||||
|
{"XMLEncode", `to_?xml`, encodeWithIndent(XMLFormat, 2), 0},
|
||||||
|
{"XMLEncodeNoIndent", `@xml`, encodeWithIndent(XMLFormat, 0), 0},
|
||||||
|
{"LoadXML", `load_?xml|xml_?load`, loadOp(NewXMLDecoder(ConfiguredXMLPreferences), false), 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterXmlFormat() {
|
||||||
|
yqlib.RegisterFormat(XMLFormat)
|
||||||
|
yqlib.RegisterRules(xmlYqRules)
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,12 +1,13 @@
|
|||||||
//go:build !yq_noxml
|
//go:build !yq_noxml
|
||||||
|
|
||||||
package yqlib
|
package xml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -262,7 +263,7 @@ const expectedXmlWithProcInstAndDirectives = `<?xml version="1.0"?>
|
|||||||
</apple>
|
</apple>
|
||||||
`
|
`
|
||||||
|
|
||||||
var xmlScenarios = []formatScenario{
|
var xmlScenarios = []yqlib.FormatScenario{
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
description: "bad xml",
|
description: "bad xml",
|
||||||
@ -614,10 +615,10 @@ var xmlScenarios = []formatScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testXMLScenario(t *testing.T, s formatScenario) {
|
func testXMLScenario(t *testing.T, s yqlib.FormatScenario) {
|
||||||
switch s.scenarioType {
|
switch s.scenarioType {
|
||||||
case "", "decode":
|
case "", "decode":
|
||||||
yamlPrefs := ConfiguredYamlPreferences.Copy()
|
yamlPrefs := yqlib.ConfiguredYamlPreferences.Copy()
|
||||||
yamlPrefs.Indent = 4
|
yamlPrefs.Indent = 4
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(yamlPrefs)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(yamlPrefs)), s.description)
|
||||||
case "encode":
|
case "encode":
|
||||||
@ -661,7 +662,7 @@ func testXMLScenario(t *testing.T, s formatScenario) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentXMLScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
|
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
@ -685,7 +686,7 @@ func documentXMLScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLDecodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLDecodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -707,7 +708,7 @@ func documentXMLDecodeScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(ConfiguredYamlPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewYamlEncoder(ConfiguredYamlPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLDecodeKeepNsScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLDecodeKeepNsScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -731,7 +732,7 @@ func documentXMLDecodeKeepNsScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(prefsWithout), NewXMLEncoder(prefsWithout))))
|
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(prefsWithout), NewXMLEncoder(prefsWithout))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLDecodeKeepNsRawTokenScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLDecodeKeepNsRawTokenScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -758,7 +759,7 @@ func documentXMLDecodeKeepNsRawTokenScenario(w *bufio.Writer, s formatScenario)
|
|||||||
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(prefsWithout), NewXMLEncoder(prefsWithout))))
|
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(prefsWithout), NewXMLEncoder(prefsWithout))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLEncodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLEncodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -776,7 +777,7 @@ func documentXMLEncodeScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewXMLEncoder(ConfiguredXMLPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewXMLEncoder(ConfiguredXMLPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLRoundTripScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLRoundTripScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -794,7 +795,7 @@ func documentXMLRoundTripScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewXMLEncoder(ConfiguredXMLPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```xml\n%v```\n\n", mustProcessFormatScenario(s, NewXMLDecoder(ConfiguredXMLPreferences), NewXMLEncoder(ConfiguredXMLPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentXMLSkipDirectivesScenario(w *bufio.Writer, s formatScenario) {
|
func documentXMLSkipDirectivesScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -243,7 +243,7 @@ func (n *CandidateNode) AddChildren(children []*CandidateNode) {
|
|||||||
|
|
||||||
func (n *CandidateNode) GetValueRep() (interface{}, error) {
|
func (n *CandidateNode) GetValueRep() (interface{}, error) {
|
||||||
log.Debugf("GetValueRep for %v value: %v", n.GetNicePath(), n.Value)
|
log.Debugf("GetValueRep for %v value: %v", n.GetNicePath(), n.Value)
|
||||||
realTag := n.guessTagFromCustomType()
|
realTag := n.GuessTagFromCustomType()
|
||||||
|
|
||||||
switch realTag {
|
switch realTag {
|
||||||
case "!!int":
|
case "!!int":
|
||||||
@ -261,17 +261,17 @@ func (n *CandidateNode) GetValueRep() (interface{}, error) {
|
|||||||
return n.Value, nil
|
return n.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *CandidateNode) guessTagFromCustomType() string {
|
func (n *CandidateNode) GuessTagFromCustomType() string {
|
||||||
if strings.HasPrefix(n.Tag, "!!") {
|
if strings.HasPrefix(n.Tag, "!!") {
|
||||||
return n.Tag
|
return n.Tag
|
||||||
} else if n.Value == "" {
|
} else if n.Value == "" {
|
||||||
log.Debug("guessTagFromCustomType: node has no value to guess the type with")
|
log.Debug("GuessTagFromCustomType: node has no value to guess the type with")
|
||||||
return n.Tag
|
return n.Tag
|
||||||
}
|
}
|
||||||
dataBucket, errorReading := parseSnippet(n.Value)
|
dataBucket, errorReading := parseSnippet(n.Value)
|
||||||
|
|
||||||
if errorReading != nil {
|
if errorReading != nil {
|
||||||
log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
|
log.Debug("GuessTagFromCustomType: could not guess underlying tag type %v", errorReading)
|
||||||
return n.Tag
|
return n.Tag
|
||||||
}
|
}
|
||||||
guessedTag := dataBucket.Tag
|
guessedTag := dataBucket.Tag
|
||||||
@ -376,7 +376,7 @@ func (n *CandidateNode) UpdateFrom(other *CandidateNode, prefs assignPreferences
|
|||||||
// if this is an empty map or empty array, use the style of other node.
|
// if this is an empty map or empty array, use the style of other node.
|
||||||
if (n.Kind != ScalarNode && len(n.Content) == 0) ||
|
if (n.Kind != ScalarNode && len(n.Content) == 0) ||
|
||||||
// if the tag has changed (e.g. from str to bool)
|
// if the tag has changed (e.g. from str to bool)
|
||||||
(n.guessTagFromCustomType() != other.guessTagFromCustomType()) {
|
(n.GuessTagFromCustomType() != other.GuessTagFromCustomType()) {
|
||||||
n.Style = other.Style
|
n.Style = other.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ const tsvTestExpectedSimpleCsv = `i like csv
|
|||||||
because excel is cool
|
because excel is cool
|
||||||
`
|
`
|
||||||
|
|
||||||
var csvScenarios = []formatScenario{
|
var csvScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "Encode CSV simple",
|
description: "Encode CSV simple",
|
||||||
input: csvTestSimpleYaml,
|
input: csvTestSimpleYaml,
|
||||||
@ -210,7 +210,7 @@ var csvScenarios = []formatScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCSVScenario(t *testing.T, s formatScenario) {
|
func testCSVScenario(t *testing.T, s FormatScenario) {
|
||||||
switch s.scenarioType {
|
switch s.scenarioType {
|
||||||
case "encode-csv":
|
case "encode-csv":
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewCsvEncoder(ConfiguredCsvPreferences)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewCsvEncoder(ConfiguredCsvPreferences)), s.description)
|
||||||
@ -229,7 +229,7 @@ func testCSVScenario(t *testing.T, s formatScenario) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentCSVDecodeObjectScenario(w *bufio.Writer, s formatScenario, formatType string) {
|
func documentCSVDecodeObjectScenario(w *bufio.Writer, s FormatScenario, formatType string) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -254,7 +254,7 @@ func documentCSVDecodeObjectScenario(w *bufio.Writer, s formatScenario, formatTy
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentCSVDecodeObjectNoAutoScenario(w *bufio.Writer, s formatScenario, formatType string) {
|
func documentCSVDecodeObjectNoAutoScenario(w *bufio.Writer, s FormatScenario, formatType string) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -279,7 +279,7 @@ func documentCSVDecodeObjectNoAutoScenario(w *bufio.Writer, s formatScenario, fo
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentCSVEncodeScenario(w *bufio.Writer, s formatScenario, formatType string) {
|
func documentCSVEncodeScenario(w *bufio.Writer, s FormatScenario, formatType string) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -312,7 +312,7 @@ func documentCSVEncodeScenario(w *bufio.Writer, s formatScenario, formatType str
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentCSVRoundTripScenario(w *bufio.Writer, s formatScenario, formatType string) {
|
func documentCSVRoundTripScenario(w *bufio.Writer, s FormatScenario, formatType string) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -348,7 +348,7 @@ func documentCSVRoundTripScenario(w *bufio.Writer, s formatScenario, formatType
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentCSVScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentCSVScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type formatScenario struct {
|
type FormatScenario struct {
|
||||||
input string
|
input string
|
||||||
indent int
|
indent int
|
||||||
expression string
|
expression string
|
||||||
@ -19,7 +19,7 @@ type formatScenario struct {
|
|||||||
expectedError string
|
expectedError string
|
||||||
}
|
}
|
||||||
|
|
||||||
func processFormatScenario(s formatScenario, decoder Decoder, encoder Encoder) (string, error) {
|
func processFormatScenario(s FormatScenario, decoder Decoder, encoder Encoder) (string, error) {
|
||||||
var output bytes.Buffer
|
var output bytes.Buffer
|
||||||
writer := bufio.NewWriter(&output)
|
writer := bufio.NewWriter(&output)
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ func processFormatScenario(s formatScenario, decoder Decoder, encoder Encoder) (
|
|||||||
return output.String(), nil
|
return output.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustProcessFormatScenario(s formatScenario, decoder Decoder, encoder Encoder) string {
|
func mustProcessFormatScenario(s FormatScenario, decoder Decoder, encoder Encoder) string {
|
||||||
|
|
||||||
result, err := processFormatScenario(s, decoder, encoder)
|
result, err := processFormatScenario(s, decoder, encoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ func (e *base64Encoder) PrintLeadingContent(_ io.Writer, _ string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *base64Encoder) Encode(writer io.Writer, node *CandidateNode) error {
|
func (e *base64Encoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as base64, can only operate on strings", node.Tag)
|
return fmt.Errorf("cannot encode %v as base64, can only operate on strings", node.Tag)
|
||||||
}
|
}
|
||||||
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(node.Value))))
|
_, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(node.Value))))
|
||||||
|
|||||||
@ -30,7 +30,7 @@ func (e *shEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *shEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
func (e *shEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ func (e *uriEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *uriEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
func (e *uriEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
|
||||||
}
|
}
|
||||||
_, err := writer.Write([]byte(url.QueryEscape(node.Value)))
|
_, err := writer.Write([]byte(url.QueryEscape(node.Value)))
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package yqlib
|
package exp_parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|||||||
@ -25,11 +25,6 @@ var JSONFormat = &Format{"json", []string{"j"},
|
|||||||
func() Decoder { return NewJSONDecoder() },
|
func() Decoder { return NewJSONDecoder() },
|
||||||
}
|
}
|
||||||
|
|
||||||
var PropertiesFormat = &Format{"props", []string{"p", "properties"},
|
|
||||||
func() Encoder { return NewPropertiesEncoder(ConfiguredPropertiesPreferences) },
|
|
||||||
func() Decoder { return NewPropertiesDecoder() },
|
|
||||||
}
|
|
||||||
|
|
||||||
var CSVFormat = &Format{"csv", []string{"c"},
|
var CSVFormat = &Format{"csv", []string{"c"},
|
||||||
func() Encoder { return NewCsvEncoder(ConfiguredCsvPreferences) },
|
func() Encoder { return NewCsvEncoder(ConfiguredCsvPreferences) },
|
||||||
func() Decoder { return NewCSVObjectDecoder(ConfiguredCsvPreferences) },
|
func() Decoder { return NewCSVObjectDecoder(ConfiguredCsvPreferences) },
|
||||||
@ -40,11 +35,6 @@ var TSVFormat = &Format{"tsv", []string{"t"},
|
|||||||
func() Decoder { return NewCSVObjectDecoder(ConfiguredTsvPreferences) },
|
func() Decoder { return NewCSVObjectDecoder(ConfiguredTsvPreferences) },
|
||||||
}
|
}
|
||||||
|
|
||||||
var XMLFormat = &Format{"xml", []string{"x"},
|
|
||||||
func() Encoder { return NewXMLEncoder(ConfiguredXMLPreferences) },
|
|
||||||
func() Decoder { return NewXMLDecoder(ConfiguredXMLPreferences) },
|
|
||||||
}
|
|
||||||
|
|
||||||
var Base64Format = &Format{"base64", []string{},
|
var Base64Format = &Format{"base64", []string{},
|
||||||
func() Encoder { return NewBase64Encoder() },
|
func() Encoder { return NewBase64Encoder() },
|
||||||
func() Decoder { return NewBase64Decoder() },
|
func() Decoder { return NewBase64Decoder() },
|
||||||
@ -78,10 +68,8 @@ var LuaFormat = &Format{"lua", []string{"l"},
|
|||||||
var Formats = []*Format{
|
var Formats = []*Format{
|
||||||
YamlFormat,
|
YamlFormat,
|
||||||
JSONFormat,
|
JSONFormat,
|
||||||
PropertiesFormat,
|
|
||||||
CSVFormat,
|
CSVFormat,
|
||||||
TSVFormat,
|
TSVFormat,
|
||||||
XMLFormat,
|
|
||||||
Base64Format,
|
Base64Format,
|
||||||
UriFormat,
|
UriFormat,
|
||||||
ShFormat,
|
ShFormat,
|
||||||
@ -90,6 +78,10 @@ var Formats = []*Format{
|
|||||||
LuaFormat,
|
LuaFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterFormat(f *Format) {
|
||||||
|
Formats = append(Formats, f)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Format) MatchesName(name string) bool {
|
func (f *Format) MatchesName(name string) bool {
|
||||||
if f.FormalName == name {
|
if f.FormalName == name {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var formattingExpressionScenarios = []formatScenario{
|
var formattingExpressionScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "Using expression files and comments",
|
description: "Using expression files and comments",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -43,7 +43,7 @@ var formattingExpressionScenarios = []formatScenario{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentExpressionScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentExpressionScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
|
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var goccyYamlFormatScenarios = []formatScenario{
|
var goccyYamlFormatScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "basic - 3",
|
description: "basic - 3",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -159,7 +159,7 @@ var goccyYamlFormatScenarios = []formatScenario{
|
|||||||
// },
|
// },
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGoccyYamlScenario(t *testing.T, s formatScenario) {
|
func testGoccyYamlScenario(t *testing.T, s FormatScenario) {
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewGoccyYAMLDecoder(), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewGoccyYAMLDecoder(), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ const roundTripMultiLineJson = `{
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var jsonScenarios = []formatScenario{
|
var jsonScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "array empty",
|
description: "array empty",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -307,7 +307,7 @@ var jsonScenarios = []formatScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentRoundtripNdJsonScenario(w *bufio.Writer, s formatScenario, indent int) {
|
func documentRoundtripNdJsonScenario(w *bufio.Writer, s FormatScenario, indent int) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -335,7 +335,7 @@ func documentRoundtripNdJsonScenario(w *bufio.Writer, s formatScenario, indent i
|
|||||||
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewJSONDecoder(), NewJSONEncoder(prefs))))
|
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewJSONDecoder(), NewJSONEncoder(prefs))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentDecodeNdJsonScenario(w *bufio.Writer, s formatScenario) {
|
func documentDecodeNdJsonScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -385,7 +385,7 @@ func decodeJSON(t *testing.T, jsonString string) *CandidateNode {
|
|||||||
return context.MatchingNodes.Front().Value.(*CandidateNode)
|
return context.MatchingNodes.Front().Value.(*CandidateNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJSONScenario(t *testing.T, s formatScenario) {
|
func testJSONScenario(t *testing.T, s FormatScenario) {
|
||||||
prefs := ConfiguredJSONPreferences.Copy()
|
prefs := ConfiguredJSONPreferences.Copy()
|
||||||
prefs.Indent = s.indent
|
prefs.Indent = s.indent
|
||||||
prefs.UnwrapScalar = false
|
prefs.UnwrapScalar = false
|
||||||
@ -413,7 +413,7 @@ func testJSONScenario(t *testing.T, s formatScenario) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentJSONDecodeScenario(t *testing.T, w *bufio.Writer, s formatScenario) {
|
func documentJSONDecodeScenario(t *testing.T, w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -443,7 +443,7 @@ func documentJSONDecodeScenario(t *testing.T, w *bufio.Writer, s formatScenario)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentJSONScenario(t *testing.T, w *bufio.Writer, i interface{}) {
|
func documentJSONScenario(t *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -464,7 +464,7 @@ func documentJSONScenario(t *testing.T, w *bufio.Writer, i interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentJSONEncodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentJSONEncodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package yqlib
|
package exp_parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/alecthomas/participle/v2/lexer"
|
"github.com/alecthomas/participle/v2/lexer"
|
||||||
)
|
)
|
||||||
|
|
||||||
var participleYqRules = []*participleYqRule{
|
var participleYqRules = []*ParticipleYqRule{
|
||||||
{"LINE_COMMENT", `line_?comment|lineComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{LineComment: true}), 0},
|
{"LINE_COMMENT", `line_?comment|lineComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{LineComment: true}), 0},
|
||||||
{"HEAD_COMMENT", `head_?comment|headComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{HeadComment: true}), 0},
|
{"HEAD_COMMENT", `head_?comment|headComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{HeadComment: true}), 0},
|
||||||
{"FOOT_COMMENT", `foot_?comment|footComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{FootComment: true}), 0},
|
{"FOOT_COMMENT", `foot_?comment|footComment`, opTokenWithPrefs(getCommentOpType, assignCommentOpType, commentOpPreferences{FootComment: true}), 0},
|
||||||
@ -58,7 +58,7 @@ var participleYqRules = []*participleYqRule{
|
|||||||
{"ArrayToMap", "array_?to_?map", expressionOpToken(`(.[] | select(. != null) ) as $i ireduce({}; .[$i | key] = $i)`), 0},
|
{"ArrayToMap", "array_?to_?map", expressionOpToken(`(.[] | select(. != null) ) as $i ireduce({}; .[$i | key] = $i)`), 0},
|
||||||
|
|
||||||
{"YamlEncodeWithIndent", `to_?yaml\([0-9]+\)`, encodeParseIndent(YamlFormat), 0},
|
{"YamlEncodeWithIndent", `to_?yaml\([0-9]+\)`, encodeParseIndent(YamlFormat), 0},
|
||||||
{"XMLEncodeWithIndent", `to_?xml\([0-9]+\)`, encodeParseIndent(XMLFormat), 0},
|
|
||||||
{"JSONEncodeWithIndent", `to_?json\([0-9]+\)`, encodeParseIndent(JSONFormat), 0},
|
{"JSONEncodeWithIndent", `to_?json\([0-9]+\)`, encodeParseIndent(JSONFormat), 0},
|
||||||
|
|
||||||
{"YamlDecode", `from_?yaml|@yamld|from_?json|@jsond`, decodeOp(YamlFormat), 0},
|
{"YamlDecode", `from_?yaml|@yamld|from_?json|@jsond`, decodeOp(YamlFormat), 0},
|
||||||
@ -67,13 +67,6 @@ var participleYqRules = []*participleYqRule{
|
|||||||
{"JSONEncode", `to_?json`, encodeWithIndent(JSONFormat, 2), 0},
|
{"JSONEncode", `to_?json`, encodeWithIndent(JSONFormat, 2), 0},
|
||||||
{"JSONEncodeNoIndent", `@json`, encodeWithIndent(JSONFormat, 0), 0},
|
{"JSONEncodeNoIndent", `@json`, encodeWithIndent(JSONFormat, 0), 0},
|
||||||
|
|
||||||
{"PropertiesDecode", `from_?props|@propsd`, decodeOp(PropertiesFormat), 0},
|
|
||||||
{"PropsEncode", `to_?props|@props`, encodeWithIndent(PropertiesFormat, 2), 0},
|
|
||||||
|
|
||||||
{"XmlDecode", `from_?xml|@xmld`, decodeOp(XMLFormat), 0},
|
|
||||||
{"XMLEncode", `to_?xml`, encodeWithIndent(XMLFormat, 2), 0},
|
|
||||||
{"XMLEncodeNoIndent", `@xml`, encodeWithIndent(XMLFormat, 0), 0},
|
|
||||||
|
|
||||||
{"CSVDecode", `from_?csv|@csvd`, decodeOp(CSVFormat), 0},
|
{"CSVDecode", `from_?csv|@csvd`, decodeOp(CSVFormat), 0},
|
||||||
{"CSVEncode", `to_?csv|@csv`, encodeWithIndent(CSVFormat, 0), 0},
|
{"CSVEncode", `to_?csv|@csv`, encodeWithIndent(CSVFormat, 0), 0},
|
||||||
|
|
||||||
@ -87,12 +80,8 @@ var participleYqRules = []*participleYqRule{
|
|||||||
{"Uri", `@uri`, encodeWithIndent(UriFormat, 0), 0},
|
{"Uri", `@uri`, encodeWithIndent(UriFormat, 0), 0},
|
||||||
{"SH", `@sh`, encodeWithIndent(ShFormat, 0), 0},
|
{"SH", `@sh`, encodeWithIndent(ShFormat, 0), 0},
|
||||||
|
|
||||||
{"LoadXML", `load_?xml|xml_?load`, loadOp(NewXMLDecoder(ConfiguredXMLPreferences), false), 0},
|
|
||||||
|
|
||||||
{"LoadBase64", `load_?base64`, loadOp(NewBase64Decoder(), false), 0},
|
{"LoadBase64", `load_?base64`, loadOp(NewBase64Decoder(), false), 0},
|
||||||
|
|
||||||
{"LoadProperties", `load_?props`, loadOp(NewPropertiesDecoder(), false), 0},
|
|
||||||
|
|
||||||
{"LoadString", `load_?str|str_?load`, loadOp(nil, true), 0},
|
{"LoadString", `load_?str|str_?load`, loadOp(nil, true), 0},
|
||||||
|
|
||||||
{"LoadYaml", `load`, loadOp(NewYamlDecoder(LoadYamlPreferences), false), 0},
|
{"LoadYaml", `load`, loadOp(NewYamlDecoder(LoadYamlPreferences), false), 0},
|
||||||
@ -229,7 +218,7 @@ var participleYqRules = []*participleYqRule{
|
|||||||
|
|
||||||
type yqAction func(lexer.Token) (*token, error)
|
type yqAction func(lexer.Token) (*token, error)
|
||||||
|
|
||||||
type participleYqRule struct {
|
type ParticipleYqRule struct {
|
||||||
Name string
|
Name string
|
||||||
Pattern string
|
Pattern string
|
||||||
CreateYqToken yqAction
|
CreateYqToken yqAction
|
||||||
@ -240,12 +229,16 @@ type participleLexer struct {
|
|||||||
lexerDefinition lexer.StringDefinition
|
lexerDefinition lexer.StringDefinition
|
||||||
}
|
}
|
||||||
|
|
||||||
func simpleOp(name string, opType *operationType) *participleYqRule {
|
func simpleOp(name string, opType *operationType) *ParticipleYqRule {
|
||||||
return &participleYqRule{strings.ToUpper(string(name[1])) + name[1:], name, opToken(opType), 0}
|
return &ParticipleYqRule{strings.ToUpper(string(name[1])) + name[1:], name, opToken(opType), 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignableOp(name string, opType *operationType, assignOpType *operationType) *participleYqRule {
|
func assignableOp(name string, opType *operationType, assignOpType *operationType) *ParticipleYqRule {
|
||||||
return &participleYqRule{strings.ToUpper(string(name[1])) + name[1:], name, opTokenWithPrefs(opType, assignOpType, nil), 0}
|
return &ParticipleYqRule{strings.ToUpper(string(name[1])) + name[1:], name, opTokenWithPrefs(opType, assignOpType, nil), 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterRules(rules []*ParticipleYqRule) {
|
||||||
|
participleYqRules = append(participleYqRules, rules...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParticipleLexer() expressionTokeniser {
|
func newParticipleLexer() expressionTokeniser {
|
||||||
@ -564,13 +557,13 @@ func literalToken(tt tokenType, checkForPost bool) yqAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *participleLexer) getYqDefinition(rawToken lexer.Token) *participleYqRule {
|
func (p *participleLexer) getYqDefinition(rawToken lexer.Token) *ParticipleYqRule {
|
||||||
for _, yqRule := range participleYqRules {
|
for _, yqRule := range participleYqRules {
|
||||||
if yqRule.ParticipleTokenType == rawToken.Type {
|
if yqRule.ParticipleTokenType == rawToken.Type {
|
||||||
return yqRule
|
return yqRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &participleYqRule{}
|
return &ParticipleYqRule{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *participleLexer) Tokenise(expression string) ([]*token, error) {
|
func (p *participleLexer) Tokenise(expression string) ([]*token, error) {
|
||||||
|
|||||||
@ -114,8 +114,8 @@ func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
|
|||||||
//process custom tags of scalar nodes.
|
//process custom tags of scalar nodes.
|
||||||
//dont worry about matching tags of maps or arrays.
|
//dont worry about matching tags of maps or arrays.
|
||||||
|
|
||||||
lhsTag := lhs.guessTagFromCustomType()
|
lhsTag := lhs.GuessTagFromCustomType()
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
|
|
||||||
if lhsTag != rhsTag {
|
if lhsTag != rhsTag {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var luaScenarios = []formatScenario{
|
var luaScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "Basic input example",
|
description: "Basic input example",
|
||||||
input: `return {
|
input: `return {
|
||||||
@ -250,7 +250,7 @@ numbers:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLuaScenario(t *testing.T, s formatScenario) {
|
func testLuaScenario(t *testing.T, s FormatScenario) {
|
||||||
switch s.scenarioType {
|
switch s.scenarioType {
|
||||||
case "", "decode":
|
case "", "decode":
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewLuaDecoder(ConfiguredLuaPreferences), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewLuaDecoder(ConfiguredLuaPreferences), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
||||||
@ -278,7 +278,7 @@ func testLuaScenario(t *testing.T, s formatScenario) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentLuaScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentLuaScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
|
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
@ -295,7 +295,7 @@ func documentLuaScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentLuaDecodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentLuaDecodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -317,7 +317,7 @@ func documentLuaDecodeScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewLuaDecoder(ConfiguredLuaPreferences), NewYamlEncoder(ConfiguredYamlPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewLuaDecoder(ConfiguredLuaPreferences), NewYamlEncoder(ConfiguredYamlPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentLuaEncodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentLuaEncodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -359,7 +359,7 @@ func documentLuaEncodeScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```lua\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewLuaEncoder(prefs))))
|
writeOrPanic(w, fmt.Sprintf("```lua\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewLuaEncoder(prefs))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentLuaRoundTripScenario(w *bufio.Writer, s formatScenario) {
|
func documentLuaRoundTripScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
|
|||||||
@ -74,11 +74,11 @@ func add(_ *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Candida
|
|||||||
|
|
||||||
func addScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
func addScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||||
lhsTag := lhs.Tag
|
lhsTag := lhs.Tag
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom := false
|
lhsIsCustom := false
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom = true
|
lhsIsCustom = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,10 @@ type assignPreferences struct {
|
|||||||
ClobberCustomTags bool
|
ClobberCustomTags bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PerformAssignment(context Context, path []interface{}) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func assignUpdateFunc(prefs assignPreferences) crossFunctionCalculation {
|
func assignUpdateFunc(prefs assignPreferences) crossFunctionCalculation {
|
||||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
if !prefs.OnlyWriteNull || lhs.Tag == "!!null" {
|
if !prefs.OnlyWriteNull || lhs.Tag == "!!null" {
|
||||||
|
|||||||
@ -69,8 +69,8 @@ func compareDateTime(layout string, prefs compareTypePref, lhs *CandidateNode, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
|
func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
|
||||||
lhsTag := lhs.guessTagFromCustomType()
|
lhsTag := lhs.GuessTagFromCustomType()
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
|
|
||||||
isDateTime := lhs.Tag == "!!timestamp"
|
isDateTime := lhs.Tag == "!!timestamp"
|
||||||
// if the lhs is a string, it might be a timestamp in a custom format.
|
// if the lhs is a string, it might be a timestamp in a custom format.
|
||||||
|
|||||||
@ -141,7 +141,7 @@ func fromUnixOp(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Conte
|
|||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
actualTag := candidate.guessTagFromCustomType()
|
actualTag := candidate.GuessTagFromCustomType()
|
||||||
|
|
||||||
if actualTag != "!!int" && actualTag != "!!float" {
|
if actualTag != "!!int" && actualTag != "!!float" {
|
||||||
return Context{}, fmt.Errorf("from_unix only works on numbers, found %v instead", candidate.Tag)
|
return Context{}, fmt.Errorf("from_unix only works on numbers, found %v instead", candidate.Tag)
|
||||||
|
|||||||
@ -32,11 +32,11 @@ func divide(_ *dataTreeNavigator, _ Context, lhs *CandidateNode, rhs *CandidateN
|
|||||||
|
|
||||||
func divideScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
func divideScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||||
lhsTag := lhs.Tag
|
lhsTag := lhs.Tag
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom := false
|
lhsIsCustom := false
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom = true
|
lhsIsCustom = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,11 +33,11 @@ func modulo(_ *dataTreeNavigator, _ Context, lhs *CandidateNode, rhs *CandidateN
|
|||||||
|
|
||||||
func moduloScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
func moduloScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||||
lhsTag := lhs.Tag
|
lhsTag := lhs.Tag
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom := false
|
lhsIsCustom := false
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom = true
|
lhsIsCustom = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -79,11 +79,11 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex
|
|||||||
|
|
||||||
func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
lhsTag := lhs.Tag
|
lhsTag := lhs.Tag
|
||||||
rhsTag := rhs.guessTagFromCustomType()
|
rhsTag := rhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom := false
|
lhsIsCustom := false
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom = true
|
lhsIsCustom = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,12 +92,12 @@ func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateT
|
|||||||
|
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(rhsTag, "!!") {
|
if !strings.HasPrefix(rhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
rhsTag = rhs.guessTagFromCustomType()
|
rhsTag = rhs.GuessTagFromCustomType()
|
||||||
}
|
}
|
||||||
|
|
||||||
isDateTime := lhsTag == "!!timestamp" && rhsTag == "!!timestamp"
|
isDateTime := lhsTag == "!!timestamp" && rhsTag == "!!timestamp"
|
||||||
|
|||||||
@ -130,7 +130,7 @@ func trimSpaceOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode)
|
|||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot trim %v, can only operate on strings. ", node.Tag)
|
return Context{}, fmt.Errorf("cannot trim %v, can only operate on strings. ", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ func changeCaseOperator(_ *dataTreeNavigator, context Context, expressionNode *E
|
|||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot change case with %v, can only operate on strings. ", node.Tag)
|
return Context{}, fmt.Errorf("cannot change case with %v, can only operate on strings. ", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ func substituteStringOperator(d *dataTreeNavigator, context Context, expressionN
|
|||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +425,7 @@ func matchOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
|
|||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ func captureOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
|||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
||||||
}
|
}
|
||||||
capture(matchPrefs, regEx, node, node.Value, results)
|
capture(matchPrefs, regEx, node, node.Value, results)
|
||||||
@ -465,7 +465,7 @@ func testOperator(d *dataTreeNavigator, context Context, expressionNode *Express
|
|||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
node := el.Value.(*CandidateNode)
|
node := el.Value.(*CandidateNode)
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
||||||
}
|
}
|
||||||
matches := regEx.FindStringSubmatch(node.Value)
|
matches := regEx.FindStringSubmatch(node.Value)
|
||||||
@ -535,7 +535,7 @@ func splitStringOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.guessTagFromCustomType() != "!!str" {
|
if node.GuessTagFromCustomType() != "!!str" {
|
||||||
return Context{}, fmt.Errorf("cannot split %v, can only split strings", node.Tag)
|
return Context{}, fmt.Errorf("cannot split %v, can only split strings", node.Tag)
|
||||||
}
|
}
|
||||||
kind, tag, content := split(node.Value, splitStr)
|
kind, tag, content := split(node.Value, splitStr)
|
||||||
|
|||||||
@ -77,13 +77,13 @@ func subtractScalars(context Context, target *CandidateNode, lhs *CandidateNode,
|
|||||||
lhsIsCustom := false
|
lhsIsCustom := false
|
||||||
if !strings.HasPrefix(lhsTag, "!!") {
|
if !strings.HasPrefix(lhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
lhsTag = lhs.guessTagFromCustomType()
|
lhsTag = lhs.GuessTagFromCustomType()
|
||||||
lhsIsCustom = true
|
lhsIsCustom = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(rhsTag, "!!") {
|
if !strings.HasPrefix(rhsTag, "!!") {
|
||||||
// custom tag - we have to have a guess
|
// custom tag - we have to have a guess
|
||||||
rhsTag = rhs.guessTagFromCustomType()
|
rhsTag = rhs.GuessTagFromCustomType()
|
||||||
}
|
}
|
||||||
|
|
||||||
isDateTime := lhsTag == "!!timestamp"
|
isDateTime := lhsTag == "!!timestamp"
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
package yqlib
|
|
||||||
|
|
||||||
type PropertiesPreferences struct {
|
|
||||||
UnwrapScalar bool
|
|
||||||
KeyValueSeparator string
|
|
||||||
UseArrayBrackets bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultPropertiesPreferences() PropertiesPreferences {
|
|
||||||
return PropertiesPreferences{
|
|
||||||
UnwrapScalar: true,
|
|
||||||
KeyValueSeparator: " = ",
|
|
||||||
UseArrayBrackets: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PropertiesPreferences) Copy() PropertiesPreferences {
|
|
||||||
return PropertiesPreferences{
|
|
||||||
UnwrapScalar: p.UnwrapScalar,
|
|
||||||
KeyValueSeparator: p.KeyValueSeparator,
|
|
||||||
UseArrayBrackets: p.UseArrayBrackets,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ConfiguredPropertiesPreferences = NewDefaultPropertiesPreferences()
|
|
||||||
@ -155,7 +155,7 @@ emptyArray =
|
|||||||
emptyMap =
|
emptyMap =
|
||||||
`
|
`
|
||||||
|
|
||||||
var propertyScenarios = []formatScenario{
|
var propertyScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "Encode properties",
|
description: "Encode properties",
|
||||||
subdescription: "Note that empty arrays and maps are not encoded by default.",
|
subdescription: "Note that empty arrays and maps are not encoded by default.",
|
||||||
@ -295,7 +295,7 @@ var propertyScenarios = []formatScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentUnwrappedEncodePropertyScenario(w *bufio.Writer, s formatScenario) {
|
func documentUnwrappedEncodePropertyScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -331,7 +331,7 @@ func documentUnwrappedEncodePropertyScenario(w *bufio.Writer, s formatScenario)
|
|||||||
writeOrPanic(w, fmt.Sprintf("```properties\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewPropertiesEncoder(prefs))))
|
writeOrPanic(w, fmt.Sprintf("```properties\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewPropertiesEncoder(prefs))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentWrappedEncodePropertyScenario(w *bufio.Writer, s formatScenario) {
|
func documentWrappedEncodePropertyScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -357,7 +357,7 @@ func documentWrappedEncodePropertyScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```properties\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewPropertiesEncoder(prefs))))
|
writeOrPanic(w, fmt.Sprintf("```properties\n%v```\n\n", mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewPropertiesEncoder(prefs))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentDecodePropertyScenario(w *bufio.Writer, s formatScenario) {
|
func documentDecodePropertyScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -382,7 +382,7 @@ func documentDecodePropertyScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewPropertiesDecoder(), NewYamlEncoder(ConfiguredYamlPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewPropertiesDecoder(), NewYamlEncoder(ConfiguredYamlPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentRoundTripPropertyScenario(w *bufio.Writer, s formatScenario) {
|
func documentRoundTripPropertyScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -408,7 +408,7 @@ func documentRoundTripPropertyScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentPropertyScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentPropertyScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var shellVariablesScenarios = []formatScenario{
|
var shellVariablesScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "Encode shell variables",
|
description: "Encode shell variables",
|
||||||
subdescription: "Note that comments are dropped and values will be enclosed in single quotes as needed.",
|
subdescription: "Note that comments are dropped and values will be enclosed in single quotes as needed.",
|
||||||
@ -69,7 +69,7 @@ func TestShellVariableScenarios(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentShellVariableScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentShellVariableScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,7 @@ var expectedSampleWithHeader = `servers:
|
|||||||
ip: 10.0.0.1
|
ip: 10.0.0.1
|
||||||
`
|
`
|
||||||
|
|
||||||
var tomlScenarios = []formatScenario{
|
var tomlScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
description: "blank",
|
description: "blank",
|
||||||
@ -240,7 +240,7 @@ var tomlScenarios = []formatScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTomlScenario(t *testing.T, s formatScenario) {
|
func testTomlScenario(t *testing.T, s FormatScenario) {
|
||||||
switch s.scenarioType {
|
switch s.scenarioType {
|
||||||
case "", "decode":
|
case "", "decode":
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewTomlDecoder(), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewTomlDecoder(), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
||||||
@ -256,7 +256,7 @@ func testTomlScenario(t *testing.T, s formatScenario) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentTomlDecodeScenario(w *bufio.Writer, s formatScenario) {
|
func documentTomlDecodeScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -278,7 +278,7 @@ func documentTomlDecodeScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewTomlDecoder(), NewYamlEncoder(ConfiguredYamlPreferences))))
|
writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", mustProcessFormatScenario(s, NewTomlDecoder(), NewYamlEncoder(ConfiguredYamlPreferences))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentTomlRoundtripScenario(w *bufio.Writer, s formatScenario) {
|
func documentTomlRoundtripScenario(w *bufio.Writer, s FormatScenario) {
|
||||||
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
writeOrPanic(w, fmt.Sprintf("## %v\n", s.description))
|
||||||
|
|
||||||
if s.subdescription != "" {
|
if s.subdescription != "" {
|
||||||
@ -301,7 +301,7 @@ func documentTomlRoundtripScenario(w *bufio.Writer, s formatScenario) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func documentTomlScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
func documentTomlScenario(_ *testing.T, w *bufio.Writer, i interface{}) {
|
||||||
s := i.(formatScenario)
|
s := i.(FormatScenario)
|
||||||
|
|
||||||
if s.skipDoc {
|
if s.skipDoc {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/mikefarah/yq/v4/test"
|
"github.com/mikefarah/yq/v4/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
var yamlFormatScenarios = []formatScenario{
|
var yamlFormatScenarios = []FormatScenario{
|
||||||
{
|
{
|
||||||
description: "scalar with doc separator",
|
description: "scalar with doc separator",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -111,7 +111,7 @@ var yamlParseScenarios = []expressionScenario{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testYamlScenario(t *testing.T, s formatScenario) {
|
func testYamlScenario(t *testing.T, s FormatScenario) {
|
||||||
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewYamlEncoder(ConfiguredYamlPreferences)), s.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
4.43.1: (not released yet)
|
4.43.1: (not released yet)
|
||||||
- Added tostring #72
|
- Added to_string #72
|
||||||
- Added string interpolation #1149
|
- Added string interpolation #1149
|
||||||
- Can specify parent(n) levels #1970
|
- Can specify parent(n) levels #1970
|
||||||
- Fixed CSV line break issue #1974
|
- Fixed CSV line break issue #1974
|
||||||
@ -151,7 +151,7 @@
|
|||||||
- XML Decoder: Fixed issue where content surrounding tags are lost #1447
|
- XML Decoder: Fixed issue where content surrounding tags are lost #1447
|
||||||
- XML Decoder: Fixed xml decode bug when there is content after a comment
|
- XML Decoder: Fixed xml decode bug when there is content after a comment
|
||||||
- Fixed loading yaml with header issue #1445
|
- Fixed loading yaml with header issue #1445
|
||||||
- guessTagFromCustomType warning log is now a debug.
|
- GuessTagFromCustomType warning log is now a debug.
|
||||||
- Special thanks to @Kopfbremse for reporting XML issues!
|
- Special thanks to @Kopfbremse for reporting XML issues!
|
||||||
|
|
||||||
4.30.4:
|
4.30.4:
|
||||||
|
|||||||
3
yq.go
3
yq.go
@ -4,9 +4,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
command "github.com/mikefarah/yq/v4/cmd"
|
command "github.com/mikefarah/yq/v4/cmd"
|
||||||
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
yqlib.RegisterPropertiesFormat()
|
||||||
|
|
||||||
cmd := command.New()
|
cmd := command.New()
|
||||||
|
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user