wip refactoring printer

This commit is contained in:
Mike Farah 2021-12-22 12:22:29 +11:00
parent 9c6d84d184
commit d105efbcf1
9 changed files with 165 additions and 77 deletions

View File

@ -1,8 +1,4 @@
# above_cat #hi
cat: # inline_cat ---
# above_array # hi
array: # inline_array - - fish
- 3 # inline_3
# above_4
- 4 # inline_4
# below_cat

View File

@ -1,2 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <!-- before cat -->
<cat legs="4">BiBi</cat> <cat>
<!-- in cat before -->
<x>3<!-- multi
line comment
for x --></x>
<y>
<!-- in y before -->
<d><!-- in d before -->4<!-- in d after --></d>
<!-- in y after -->
</y>
<!-- in_cat_after -->
</cat>
<!-- after cat -->

View File

@ -1,35 +1,89 @@
package yqlib package yqlib
import ( import (
"bufio"
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"strings"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
) )
type Encoder interface { type Encoder interface {
Encode(node *yaml.Node) error Encode(node *yaml.Node) error
PrintDocumentSeparator() error
PrintLeadingContent(content string) error
} }
type yamlEncoder struct { type yamlEncoder struct {
destination io.Writer destination io.Writer
indent int indent int
colorise bool colorise bool
firstDoc 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 { if indent < 0 {
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 { 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 destination := ye.destination
tempBuffer := bytes.NewBuffer(nil) tempBuffer := bytes.NewBuffer(nil)
if ye.colorise { if ye.colorise {
@ -88,6 +142,14 @@ func NewJsonEncoder(destination io.Writer, indent int) Encoder {
return &jsonEncoder{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 { func (je *jsonEncoder) Encode(node *yaml.Node) error {
var dataBucket orderedMap var dataBucket orderedMap
// firstly, convert all map keys to strings // firstly, convert all map keys to strings

View File

@ -18,6 +18,14 @@ func NewCsvEncoder(destination io.Writer, separator rune) Encoder {
return &csvEncoder{csvWriter} 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 { func (e *csvEncoder) encodeRow(contents []*yaml.Node) error {
stringValues := make([]string, len(contents)) stringValues := make([]string, len(contents))

View File

@ -1,8 +1,11 @@
package yqlib package yqlib
import ( import (
"bufio"
"errors"
"fmt" "fmt"
"io" "io"
"strings"
"github.com/magiconair/properties" "github.com/magiconair/properties"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
@ -16,6 +19,43 @@ func NewPropertiesEncoder(destination io.Writer) Encoder {
return &propertiesEncoder{destination} 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 { func (pe *propertiesEncoder) Encode(node *yaml.Node) error {
mapKeysToStrings(node) mapKeysToStrings(node)
p := properties.NewProperties() p := properties.NewProperties()

View File

@ -25,6 +25,15 @@ func NewXmlEncoder(writer io.Writer, indent int, attributePrefix string, content
encoder.Indent("", indentString) encoder.Indent("", indentString)
return &xmlEncoder{encoder, attributePrefix, contentName} 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 { func (e *xmlEncoder) Encode(node *yaml.Node) error {
switch node.Kind { switch node.Kind {
case yaml.MappingNode: case yaml.MappingNode:

View File

@ -86,7 +86,8 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
var chompRegexp = regexp.MustCompile(`\n$`) var chompRegexp = regexp.MustCompile(`\n$`)
var output bytes.Buffer var output bytes.Buffer
var writer = bufio.NewWriter(&output) 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 return Context{}, err
} }
if err := writer.Flush(); err != nil { if err := writer.Flush(); err != nil {

View File

@ -49,6 +49,7 @@ func OutputFormatFromString(format string) (PrinterOutputFormat, error) {
type resultsPrinter struct { type resultsPrinter struct {
outputFormat PrinterOutputFormat outputFormat PrinterOutputFormat
encoder Encoder
unwrapScalar bool unwrapScalar bool
colorsEnabled bool colorsEnabled bool
indent int indent int
@ -91,27 +92,22 @@ func (p *resultsPrinter) printNode(node *yaml.Node, writer io.Writer) error {
p.printedMatches = p.printedMatches || (node.Tag != "!!null" && p.printedMatches = p.printedMatches || (node.Tag != "!!null" &&
(node.Tag != "!!bool" || node.Value != "false")) (node.Tag != "!!bool" || node.Value != "false"))
var encoder Encoder // switch p.outputFormat {
if node.Kind == yaml.ScalarNode && p.unwrapScalar && p.outputFormat == YamlOutputFormat { // case JsonOutputFormat:
return writeString(writer, node.Value+"\n") // 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 { return p.encoder.Encode(node)
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)
} }
func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
@ -152,14 +148,14 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
commentsStartWithSepExp := regexp.MustCompile(`^\$yqDocSeperator\$`) commentsStartWithSepExp := regexp.MustCompile(`^\$yqDocSeperator\$`)
commentStartsWithSeparator := commentsStartWithSepExp.MatchString(mappedDoc.LeadingContent) 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") log.Debug("-- writing doc sep")
if err := writeString(writer, "---\n"); err != nil { if err := p.encoder.PrintDocumentSeparator(); err != nil {
return err return err
} }
} }
if err := processLeadingContent(mappedDoc, writer, p.printDocSeparators, p.outputFormat); err != nil { if err := p.encoder.PrintLeadingContent(mappedDoc.LeadingContent); err != nil {
return err 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 { if p.appendixReader != nil && p.outputFormat == YamlOutputFormat {
writer, err := p.printerWriter.GetWriter(nil) writer, err := p.printerWriter.GetWriter(nil)
if err != nil { if err != nil {

View File

@ -38,43 +38,6 @@ func writeString(writer io.Writer, txt string) error {
return errorWriting 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) { func processReadStream(reader *bufio.Reader) (io.Reader, string, error) {
var commentLineRegEx = regexp.MustCompile(`^\s*#`) var commentLineRegEx = regexp.MustCompile(`^\s*#`)
var sb strings.Builder var sb strings.Builder