diff --git a/examples/data1.yaml b/examples/data1.yaml index bfea295a..38071207 100644 --- a/examples/data1.yaml +++ b/examples/data1.yaml @@ -1,8 +1,4 @@ -# above_cat -cat: # inline_cat - # above_array - array: # inline_array - - 3 # inline_3 - # above_4 - - 4 # inline_4 -# below_cat \ No newline at end of file +#hi +--- +# hi +- - fish \ No newline at end of file diff --git a/examples/mike.xml b/examples/mike.xml index 2e1813a4..94773b86 100644 --- a/examples/mike.xml +++ b/examples/mike.xml @@ -1,2 +1,14 @@ - -BiBi \ No newline at end of file + + + + 3 + + + 4 + + + + + \ No newline at end of file diff --git a/pkg/yqlib/encoder.go b/pkg/yqlib/encoder.go index 71ec6c38..80b0380f 100644 --- a/pkg/yqlib/encoder.go +++ b/pkg/yqlib/encoder.go @@ -1,35 +1,89 @@ package yqlib import ( + "bufio" "bytes" "encoding/json" "errors" "fmt" "io" + "strings" yaml "gopkg.in/yaml.v3" ) type Encoder interface { Encode(node *yaml.Node) error + PrintDocumentSeparator() error + PrintLeadingContent(content string) error } type yamlEncoder struct { - destination io.Writer - indent int - colorise bool - firstDoc bool + destination io.Writer + indent int + colorise bool + firstDoc bool + printDocSeparators bool } -func NewYamlEncoder(destination io.Writer, indent int, colorise bool) Encoder { +func NewYamlEncoder(destination io.Writer, indent int, colorise bool, printDocSeparators bool) Encoder { if indent < 0 { indent = 0 } - return &yamlEncoder{destination, indent, colorise, true} + return &yamlEncoder{destination, indent, colorise, true, printDocSeparators} +} +func (ye *yamlEncoder) PrintDocumentSeparator() error { + if ye.printDocSeparators { + if err := writeString(ye.destination, "---\n"); err != nil { + return err + } + } + return nil +} + +func (ye *yamlEncoder) PrintLeadingContent(content string) error { + log.Debug("headcommentwas %v", content) + log.Debug("finished headcomment") + reader := bufio.NewReader(strings.NewReader(content)) + + for { + + readline, errReading := reader.ReadString('\n') + if errReading != nil && !errors.Is(errReading, io.EOF) { + return errReading + } + if strings.Contains(readline, "$yqDocSeperator$") { + + if err := ye.PrintDocumentSeparator(); err != nil { + return err + } + + } else { + if err := writeString(ye.destination, readline); err != nil { + return err + } + } + + if errors.Is(errReading, io.EOF) { + if readline != "" { + // the last comment we read didn't have a new line, put one in + if err := writeString(ye.destination, "\n"); err != nil { + return err + } + } + break + } + } + + return nil } func (ye *yamlEncoder) Encode(node *yaml.Node) error { + if node.Kind == yaml.ScalarNode && ye.unwrapScalar { + return writeString(ye.destination, node.Value+"\n") + } + destination := ye.destination tempBuffer := bytes.NewBuffer(nil) if ye.colorise { @@ -88,6 +142,14 @@ func NewJsonEncoder(destination io.Writer, indent int) Encoder { return &jsonEncoder{encoder} } +func (je *jsonEncoder) PrintDocumentSeparator() error { + return nil +} + +func (je *jsonEncoder) PrintLeadingContent(content string) error { + return nil +} + func (je *jsonEncoder) Encode(node *yaml.Node) error { var dataBucket orderedMap // firstly, convert all map keys to strings diff --git a/pkg/yqlib/encoder_csv.go b/pkg/yqlib/encoder_csv.go index 654e05ac..2f16dbb5 100644 --- a/pkg/yqlib/encoder_csv.go +++ b/pkg/yqlib/encoder_csv.go @@ -18,6 +18,14 @@ func NewCsvEncoder(destination io.Writer, separator rune) Encoder { return &csvEncoder{csvWriter} } +func (e *csvEncoder) PrintDocumentSeparator() error { + return nil +} + +func (e *csvEncoder) PrintLeadingContent(content string) error { + return nil +} + func (e *csvEncoder) encodeRow(contents []*yaml.Node) error { stringValues := make([]string, len(contents)) diff --git a/pkg/yqlib/encoder_properties.go b/pkg/yqlib/encoder_properties.go index 8cae7ee1..36c86a2e 100644 --- a/pkg/yqlib/encoder_properties.go +++ b/pkg/yqlib/encoder_properties.go @@ -1,8 +1,11 @@ package yqlib import ( + "bufio" + "errors" "fmt" "io" + "strings" "github.com/magiconair/properties" yaml "gopkg.in/yaml.v3" @@ -16,6 +19,43 @@ func NewPropertiesEncoder(destination io.Writer) Encoder { return &propertiesEncoder{destination} } +func (e *propertiesEncoder) PrintDocumentSeparator() error { + return nil +} + +func (e *propertiesEncoder) PrintLeadingContent(content string) error { + reader := bufio.NewReader(strings.NewReader(content)) + for { + + readline, errReading := reader.ReadString('\n') + if errReading != nil && !errors.Is(errReading, io.EOF) { + return errReading + } + if strings.Contains(readline, "$yqDocSeperator$") { + + if err := e.PrintDocumentSeparator(); err != nil { + return err + } + + } else { + if err := writeString(e.destination, readline); err != nil { + return err + } + } + + if errors.Is(errReading, io.EOF) { + if readline != "" { + // the last comment we read didn't have a new line, put one in + if err := writeString(e.destination, "\n"); err != nil { + return err + } + } + break + } + } + return nil +} + func (pe *propertiesEncoder) Encode(node *yaml.Node) error { mapKeysToStrings(node) p := properties.NewProperties() diff --git a/pkg/yqlib/encoder_xml.go b/pkg/yqlib/encoder_xml.go index 255a1279..ff307409 100644 --- a/pkg/yqlib/encoder_xml.go +++ b/pkg/yqlib/encoder_xml.go @@ -25,6 +25,15 @@ func NewXmlEncoder(writer io.Writer, indent int, attributePrefix string, content encoder.Indent("", indentString) return &xmlEncoder{encoder, attributePrefix, contentName} } + +func (e *xmlEncoder) PrintDocumentSeparator() error { + return nil +} + +func (e *xmlEncoder) PrintLeadingContent(content string) error { + return nil +} + func (e *xmlEncoder) Encode(node *yaml.Node) error { switch node.Kind { case yaml.MappingNode: diff --git a/pkg/yqlib/operator_comments.go b/pkg/yqlib/operator_comments.go index ebc78b9d..375cfb53 100644 --- a/pkg/yqlib/operator_comments.go +++ b/pkg/yqlib/operator_comments.go @@ -86,7 +86,8 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode * var chompRegexp = regexp.MustCompile(`\n$`) var output bytes.Buffer var writer = bufio.NewWriter(&output) - if err := processLeadingContent(candidate, writer, false, YamlOutputFormat); err != nil { + var encoder = NewYamlEncoder(writer, 2, false, true) + if err := encoder.PrintLeadingContent(candidate.LeadingContent); err != nil { return Context{}, err } if err := writer.Flush(); err != nil { diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go index 2c1706e8..9b3e4630 100644 --- a/pkg/yqlib/printer.go +++ b/pkg/yqlib/printer.go @@ -49,6 +49,7 @@ func OutputFormatFromString(format string) (PrinterOutputFormat, error) { type resultsPrinter struct { outputFormat PrinterOutputFormat + encoder Encoder unwrapScalar bool colorsEnabled bool indent int @@ -91,27 +92,22 @@ func (p *resultsPrinter) printNode(node *yaml.Node, writer io.Writer) error { p.printedMatches = p.printedMatches || (node.Tag != "!!null" && (node.Tag != "!!bool" || node.Value != "false")) - var encoder Encoder - if node.Kind == yaml.ScalarNode && p.unwrapScalar && p.outputFormat == YamlOutputFormat { - return writeString(writer, node.Value+"\n") - } + // switch p.outputFormat { + // case JsonOutputFormat: + // encoder = NewJsonEncoder(writer, p.indent) + // case PropsOutputFormat: + // encoder = NewPropertiesEncoder(writer) + // case CsvOutputFormat: + // encoder = NewCsvEncoder(writer, ',') + // case TsvOutputFormat: + // encoder = NewCsvEncoder(writer, '\t') + // case YamlOutputFormat: + // encoder = NewYamlEncoder(writer, p.indent, p.colorsEnabled) + // case XmlOutputFormat: + // encoder = NewXmlEncoder(writer, p.indent, XmlPreferences.AttributePrefix, XmlPreferences.ContentName) + // } - switch p.outputFormat { - case JsonOutputFormat: - encoder = NewJsonEncoder(writer, p.indent) - case PropsOutputFormat: - encoder = NewPropertiesEncoder(writer) - case CsvOutputFormat: - encoder = NewCsvEncoder(writer, ',') - case TsvOutputFormat: - encoder = NewCsvEncoder(writer, '\t') - case YamlOutputFormat: - encoder = NewYamlEncoder(writer, p.indent, p.colorsEnabled) - case XmlOutputFormat: - encoder = NewXmlEncoder(writer, p.indent, XmlPreferences.AttributePrefix, XmlPreferences.ContentName) - } - - return encoder.Encode(node) + return p.encoder.Encode(node) } func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { @@ -152,14 +148,14 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { commentsStartWithSepExp := regexp.MustCompile(`^\$yqDocSeperator\$`) commentStartsWithSeparator := commentsStartWithSepExp.MatchString(mappedDoc.LeadingContent) - if (p.previousDocIndex != mappedDoc.Document || p.previousFileIndex != mappedDoc.FileIndex) && p.printDocSeparators && !commentStartsWithSeparator { + if (p.previousDocIndex != mappedDoc.Document || p.previousFileIndex != mappedDoc.FileIndex) && !commentStartsWithSeparator { log.Debug("-- writing doc sep") - if err := writeString(writer, "---\n"); err != nil { + if err := p.encoder.PrintDocumentSeparator(); err != nil { return err } } - if err := processLeadingContent(mappedDoc, writer, p.printDocSeparators, p.outputFormat); err != nil { + if err := p.encoder.PrintLeadingContent(mappedDoc.LeadingContent); err != nil { return err } @@ -173,6 +169,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { } } + // what happens if I remove output format check? if p.appendixReader != nil && p.outputFormat == YamlOutputFormat { writer, err := p.printerWriter.GetWriter(nil) if err != nil { diff --git a/pkg/yqlib/utils.go b/pkg/yqlib/utils.go index ecfa6a99..47871f05 100644 --- a/pkg/yqlib/utils.go +++ b/pkg/yqlib/utils.go @@ -38,43 +38,6 @@ func writeString(writer io.Writer, txt string) error { return errorWriting } -func processLeadingContent(mappedDoc *CandidateNode, writer io.Writer, printDocSeparators bool, outputFormat PrinterOutputFormat) error { - log.Debug("headcommentwas %v", mappedDoc.LeadingContent) - log.Debug("finished headcomment") - reader := bufio.NewReader(strings.NewReader(mappedDoc.LeadingContent)) - - for { - - readline, errReading := reader.ReadString('\n') - if errReading != nil && !errors.Is(errReading, io.EOF) { - return errReading - } - if strings.Contains(readline, "$yqDocSeperator$") { - if printDocSeparators { - if err := writeString(writer, "---\n"); err != nil { - return err - } - } - } else if outputFormat == YamlOutputFormat { - if err := writeString(writer, readline); err != nil { - return err - } - } - - if errors.Is(errReading, io.EOF) { - if readline != "" { - // the last comment we read didn't have a new line, put one in - if err := writeString(writer, "\n"); err != nil { - return err - } - } - break - } - } - - return nil -} - func processReadStream(reader *bufio.Reader) (io.Reader, string, error) { var commentLineRegEx = regexp.MustCompile(`^\s*#`) var sb strings.Builder