mirror of
https://github.com/mikefarah/yq.git
synced 2026-09-01 22:31:12 +08:00
Add INI support
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
//go:build !yq_noini
|
||||
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-ini/ini"
|
||||
)
|
||||
|
||||
type iniEncoder struct {
|
||||
indentString string
|
||||
}
|
||||
|
||||
// NewINIEncoder creates a new INI encoder with the specified indent level for formatting.
|
||||
func NewINIEncoder(indent int) Encoder {
|
||||
var indentString = ""
|
||||
for index := 0; index < indent; index++ {
|
||||
indentString = indentString + " "
|
||||
}
|
||||
return &iniEncoder{indentString}
|
||||
}
|
||||
|
||||
// CanHandleAliases indicates whether the encoder supports aliases. INI does not support aliases.
|
||||
func (ie *iniEncoder) CanHandleAliases() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// PrintDocumentSeparator is a no-op since INI does not support multiple documents.
|
||||
func (ie *iniEncoder) PrintDocumentSeparator(_ io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintLeadingContent is a no-op since INI does not support leading content or comments at the encoder level.
|
||||
func (ie *iniEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode converts a CandidateNode into INI format and writes it to the provided writer.
|
||||
func (ie *iniEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||
log.Debugf("I need to encode %v", NodeToString(node))
|
||||
log.Debugf("kids %v", len(node.Content))
|
||||
|
||||
if node.Kind == ScalarNode {
|
||||
return writeStringINI(writer, node.Value+"\n")
|
||||
}
|
||||
|
||||
// Create a new INI configuration.
|
||||
cfg := ini.Empty()
|
||||
|
||||
if node.Kind == MappingNode {
|
||||
// Default section for key-value pairs at the root level.
|
||||
defaultSection, err := cfg.NewSection(ini.DefaultSection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Process the node's content.
|
||||
for i := 0; i < len(node.Content); i += 2 {
|
||||
keyNode := node.Content[i]
|
||||
valueNode := node.Content[i+1]
|
||||
key := keyNode.Value
|
||||
|
||||
if valueNode.Kind == ScalarNode {
|
||||
// Add key-value pair to the default section.
|
||||
_, err := defaultSection.NewKey(key, valueNode.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if valueNode.Kind == MappingNode {
|
||||
// Create a new section for nested MappingNode.
|
||||
section, err := cfg.NewSection(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Process nested key-value pairs.
|
||||
for j := 0; j < len(valueNode.Content); j += 2 {
|
||||
nestedKeyNode := valueNode.Content[j]
|
||||
nestedValueNode := valueNode.Content[j+1]
|
||||
if nestedValueNode.Kind == ScalarNode {
|
||||
_, err := section.NewKey(nestedKeyNode.Value, nestedValueNode.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Debugf("Skipping nested non-scalar value for key %s: %v", nestedKeyNode.Value, nestedValueNode.Kind)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debugf("Skipping non-scalar value for key %s: %v", key, valueNode.Kind)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("INI encoder supports only MappingNode at the root level, got %v", node.Kind)
|
||||
}
|
||||
|
||||
// Use a buffer to store the INI output as the library doesn't support direct io.Writer with indent.
|
||||
var buffer bytes.Buffer
|
||||
_, err := cfg.WriteToIndent(&buffer, ie.indentString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the buffer content to the provided writer.
|
||||
_, err = writer.Write(buffer.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
// writeStringINI is a helper function to write a string to the provided writer for INI encoder.
|
||||
func writeStringINI(writer io.Writer, content string) error {
|
||||
_, err := writer.Write([]byte(content))
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user