1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 21:31:33 +03:00

gojq: Update rebased fq fork

Also sync colorjson encoder with gojq encoder
This commit is contained in:
Mattias Wadman 2022-09-28 15:44:16 +02:00
parent d2d77dae88
commit 376f0ebb24
3 changed files with 107 additions and 116 deletions

6
go.mod
View File

@ -4,7 +4,7 @@ go 1.18
require ( require (
// fork of github.com/itchyny/gojq, see github.com/wader/gojq fq branch // fork of github.com/itchyny/gojq, see github.com/wader/gojq fq branch
github.com/wader/gojq v0.12.1-0.20220822132002-64fe65a68424 github.com/wader/gojq v0.12.1-0.20220928130353-e72ca4fd7c40
// fork of github.com/chzyer/readline, see github.com/wader/readline fq branch // fork of github.com/chzyer/readline, see github.com/wader/readline fq branch
github.com/wader/readline v0.0.0-20220928125628-732951d41240 github.com/wader/readline v0.0.0-20220928125628-732951d41240
) )
@ -74,9 +74,9 @@ require (
) )
require ( require (
github.com/itchyny/timefmt-go v0.1.3 // indirect github.com/itchyny/timefmt-go v0.1.4 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
) )

12
go.sum
View File

@ -8,8 +8,8 @@ github.com/gomarkdown/markdown v0.0.0-20220627144906-e9a81102ebeb h1:5b/eFaSaKPF
github.com/gomarkdown/markdown v0.0.0-20220627144906-e9a81102ebeb/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/markdown v0.0.0-20220627144906-e9a81102ebeb/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/gopacket/gopacket v0.0.0-20220819214934-ee81b8c880da h1:AAwDU9N39fQNYUtg270aiU6N7U2ZVsGZKiRwsCMsWEo= github.com/gopacket/gopacket v0.0.0-20220819214934-ee81b8c880da h1:AAwDU9N39fQNYUtg270aiU6N7U2ZVsGZKiRwsCMsWEo=
github.com/gopacket/gopacket v0.0.0-20220819214934-ee81b8c880da/go.mod h1:DlRRfaM/QjAu2ADqraIure1Eif0HpNL8hmyVQ+qci5Y= github.com/gopacket/gopacket v0.0.0-20220819214934-ee81b8c880da/go.mod h1:DlRRfaM/QjAu2ADqraIure1Eif0HpNL8hmyVQ+qci5Y=
github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU= github.com/itchyny/timefmt-go v0.1.4 h1:hFEfWVdwsEi+CY8xY2FtgWHGQaBaC3JeHd+cve0ynVM=
github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= github.com/itchyny/timefmt-go v0.1.4/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@ -23,8 +23,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/wader/gojq v0.12.1-0.20220822132002-64fe65a68424 h1:4SZxNA1ti22+TemKXy5H2qyFPPqi5X55vtyjmOnLsqk= github.com/wader/gojq v0.12.1-0.20220928130353-e72ca4fd7c40 h1:Njp3KQtQX2QBkCRA0OdnJl5wj0r9fQAVV6q3h1TOT4U=
github.com/wader/gojq v0.12.1-0.20220822132002-64fe65a68424/go.mod h1:HM2cB+ANeJ4kBhxQp/4cNKewKjvYHACuCpBneQBgHkg= github.com/wader/gojq v0.12.1-0.20220928130353-e72ca4fd7c40/go.mod h1:/+WKHSfP8sgyJDXeD9VjxlGjExGfjPUy0zm/Zy3Ind0=
github.com/wader/readline v0.0.0-20220928125628-732951d41240 h1:fqNaldd6kVsMNGXLXH4TtB1kJtaPQOzGwqNYgswIM94= github.com/wader/readline v0.0.0-20220928125628-732951d41240 h1:fqNaldd6kVsMNGXLXH4TtB1kJtaPQOzGwqNYgswIM94=
github.com/wader/readline v0.0.0-20220928125628-732951d41240/go.mod h1:Zgz8IJWvJoe7NK23CCPpC109XMCqJCpUhpHcnnA4XaM= github.com/wader/readline v0.0.0-20220928125628-732951d41240/go.mod h1:Zgz8IJWvJoe7NK23CCPpC109XMCqJCpUhpHcnnA4XaM=
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c= golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c=
@ -34,8 +34,8 @@ golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2F
golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -1,8 +1,8 @@
// This is gojq:s cli/encoder.go extract to be reusable and non-global color config // Package colorjson is gojq:s cli/encoder.go extract to be reusable and have non-global color config
// TODO: possible gojq can export it? // TODO: possible gojq can export it?
// //
// The MIT License (MIT) // The MIT License (MIT)
// Copyright (c) 2019-2021 itchyny // Copyright (c) 2019-2022 itchyny
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -21,23 +21,17 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
//
// skip errcheck to keep code similar to gojq version
//
//nolint:errcheck
package colorjson package colorjson
import ( import (
"bufio" "bytes"
"fmt" "fmt"
"io" "io"
"math" "math"
"math/big" "math/big"
"sort"
"strconv" "strconv"
"unicode/utf8" "unicode/utf8"
"golang.org/x/exp/slices"
) )
type Colors struct { type Colors struct {
@ -53,13 +47,14 @@ type Colors struct {
} }
type Encoder struct { type Encoder struct {
w *bufio.Writer out io.Writer
wErr error w *bytes.Buffer
color bool
tab bool tab bool
indent int indent int
depth int depth int
buf [64]byte buf [64]byte
color bool
valueFn func(v any) any valueFn func(v any) any
colors Colors colors Colors
} }
@ -67,6 +62,7 @@ type Encoder struct {
func NewEncoder(color bool, tab bool, indent int, valueFn func(v any) any, colors Colors) *Encoder { func NewEncoder(color bool, tab bool, indent int, valueFn func(v any) any, colors Colors) *Encoder {
// reuse the buffer in multiple calls of marshal // reuse the buffer in multiple calls of marshal
return &Encoder{ return &Encoder{
w: new(bytes.Buffer),
color: color, color: color,
tab: tab, tab: tab,
indent: indent, indent: indent,
@ -75,16 +71,22 @@ func NewEncoder(color bool, tab bool, indent int, valueFn func(v any) any, color
} }
} }
func (e *Encoder) Marshal(v any, w io.Writer) error { func (e *Encoder) flush() error {
e.w = bufio.NewWriter(w) _, err := e.out.Write(e.w.Bytes())
e.encode(v) e.w.Reset()
if e.wErr != nil { return err
return e.wErr
}
return e.w.Flush()
} }
func (e *Encoder) encode(v any) { func (e *Encoder) Marshal(v interface{}, w io.Writer) error {
e.out = w
err := e.encode(v)
if ferr := e.flush(); ferr != nil && err == nil {
err = ferr
}
return err
}
func (e *Encoder) encode(v interface{}) error {
switch v := v.(type) { switch v := v.(type) {
case nil: case nil:
e.write([]byte("null"), e.colors.Null) e.write([]byte("null"), e.colors.Null)
@ -102,18 +104,26 @@ func (e *Encoder) encode(v any) {
e.write(v.Append(e.buf[:0], 10), e.colors.Number) e.write(v.Append(e.buf[:0], 10), e.colors.Number)
case string: case string:
e.encodeString(v, e.colors.String) e.encodeString(v, e.colors.String)
case []any: case []interface{}:
e.encodeArray(v) if err := e.encodeArray(v); err != nil {
case map[string]any: return err
e.encodeMap(v) }
case map[string]interface{}:
if err := e.encodeMap(v); err != nil {
return err
}
default: default:
if e.valueFn != nil { if e.valueFn != nil {
v = e.valueFn(v) v = e.valueFn(v)
} else { } else {
panic(fmt.Sprintf("invalid value: %#+v", v)) panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
} }
e.encode(v) return e.encode(v)
} }
if e.w.Len() > 8*1024 {
return e.flush()
}
return nil
} }
// ref: floatEncoder in encoding/json // ref: floatEncoder in encoding/json
@ -144,37 +154,38 @@ func (e *Encoder) encodeFloat64(f float64) {
// ref: encodeState#string in encoding/json // ref: encodeState#string in encoding/json
func (e *Encoder) encodeString(s string, color []byte) { func (e *Encoder) encodeString(s string, color []byte) {
if e.color { if color != nil {
e.w.Write(color) e.setColor(e.w, color)
} }
e.w.WriteByte('"') e.w.WriteByte('"')
start := 0 start := 0
for i := 0; i < len(s); { for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf { if b := s[i]; b < utf8.RuneSelf {
if ']' <= b && b <= '~' || '#' <= b && b <= '[' || b == ' ' || b == '!' { if ' ' <= b && b <= '~' && b != '"' && b != '\\' {
i++ i++
continue continue
} }
if start < i { if start < i {
e.w.WriteString(s[start:i]) e.w.WriteString(s[start:i])
} }
e.w.WriteByte('\\')
switch b { switch b {
case '\\', '"': case '"':
e.w.WriteByte(b) e.w.WriteString(`\"`)
case '\\':
e.w.WriteString(`\\`)
case '\b': case '\b':
e.w.WriteByte('b') e.w.WriteString(`\b`)
case '\f': case '\f':
e.w.WriteByte('f') e.w.WriteString(`\f`)
case '\n': case '\n':
e.w.WriteByte('n') e.w.WriteString(`\n`)
case '\r': case '\r':
e.w.WriteByte('r') e.w.WriteString(`\r`)
case '\t': case '\t':
e.w.WriteByte('t') e.w.WriteString(`\t`)
default: default:
const hex = "0123456789abcdef" const hex = "0123456789abcdef"
e.w.WriteString("u00") e.w.WriteString(`\u00`)
e.w.WriteByte(hex[b>>4]) e.w.WriteByte(hex[b>>4])
e.w.WriteByte(hex[b&0xF]) e.w.WriteByte(hex[b&0xF])
} }
@ -198,40 +209,39 @@ func (e *Encoder) encodeString(s string, color []byte) {
e.w.WriteString(s[start:]) e.w.WriteString(s[start:])
} }
e.w.WriteByte('"') e.w.WriteByte('"')
if e.color { if color != nil {
e.w.Write(e.colors.Reset) e.setColor(e.w, e.colors.Reset)
} }
} }
func (e *Encoder) encodeArray(vs []any) { func (e *Encoder) encodeArray(vs []interface{}) error {
e.writeByte('[', e.colors.Array) e.writeByte('[', e.colors.Array)
e.depth += e.indent e.depth += e.indent
for i, v := range vs { for i, v := range vs {
if e.wErr != nil {
return
}
if i > 0 { if i > 0 {
e.writeByte(',', e.colors.Array) e.writeByte(',', e.colors.Array)
} }
if e.indent != 0 { if e.indent != 0 {
e.writeIndent() e.writeIndent()
} }
e.encode(v) if err := e.encode(v); err != nil {
return err
}
} }
e.depth -= e.indent e.depth -= e.indent
if len(vs) > 0 && e.indent != 0 { if len(vs) > 0 && e.indent != 0 {
e.writeIndent() e.writeIndent()
} }
e.writeByte(']', e.colors.Array) e.writeByte(']', e.colors.Array)
return nil
} }
func (e *Encoder) encodeMap(vs map[string]any) { func (e *Encoder) encodeMap(vs map[string]interface{}) error {
e.writeByte('{', e.colors.Object) e.writeByte('{', e.colors.Object)
e.depth += e.indent e.depth += e.indent
type keyVal struct { type keyVal struct {
key string key string
val any val interface{}
} }
kvs := make([]keyVal, len(vs)) kvs := make([]keyVal, len(vs))
var i int var i int
@ -239,12 +249,10 @@ func (e *Encoder) encodeMap(vs map[string]any) {
kvs[i] = keyVal{k, v} kvs[i] = keyVal{k, v}
i++ i++
} }
slices.SortFunc(kvs, func(a, b keyVal) bool { return a.key < b.key }) sort.Slice(kvs, func(i, j int) bool {
return kvs[i].key < kvs[j].key
})
for i, kv := range kvs { for i, kv := range kvs {
if e.wErr != nil {
return
}
if i > 0 { if i > 0 {
e.writeByte(',', e.colors.Object) e.writeByte(',', e.colors.Object)
} }
@ -256,82 +264,65 @@ func (e *Encoder) encodeMap(vs map[string]any) {
if e.indent != 0 { if e.indent != 0 {
e.w.WriteByte(' ') e.w.WriteByte(' ')
} }
e.encode(kv.val) if err := e.encode(kv.val); err != nil {
return err
}
} }
e.depth -= e.indent e.depth -= e.indent
if len(vs) > 0 && e.indent != 0 { if len(vs) > 0 && e.indent != 0 {
e.writeIndent() e.writeIndent()
} }
e.writeByte('}', e.colors.Object) e.writeByte('}', e.colors.Object)
return nil
} }
func (e *Encoder) writeIndent() { func (e *Encoder) writeIndent() {
e.w.WriteByte('\n') e.w.WriteByte('\n')
if n := e.depth; n > 0 { if n := e.depth; n > 0 {
if e.tab { if e.tab {
const tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" e.writeIndentInternal(n, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")
for n > len(tabs) {
e.w.Write([]byte(tabs))
n -= len(tabs)
}
e.w.Write([]byte(tabs)[:n])
} else { } else {
const spaces = " " e.writeIndentInternal(n, " ")
for n > len(spaces) {
e.w.Write([]byte(spaces))
n -= len(spaces)
} }
e.w.Write([]byte(spaces)[:n]) }
}
func (e *Encoder) writeIndentInternal(n int, spaces string) {
if l := len(spaces); n <= l {
e.w.WriteString(spaces[:n])
} else {
e.w.WriteString(spaces)
for n -= l; n > 0; n, l = n-l, l*2 {
if n < l {
l = n
}
e.w.Write(e.w.Bytes()[e.w.Len()-l:])
} }
} }
} }
func (e *Encoder) writeByte(b byte, color []byte) { func (e *Encoder) writeByte(b byte, color []byte) {
if e.wErr != nil {
return
}
if color == nil { if color == nil {
if err := e.w.WriteByte(b); err != nil { e.w.WriteByte(b)
e.wErr = err
}
} else { } else {
if e.color { e.setColor(e.w, color)
if _, err := e.w.Write(color); err != nil { e.w.WriteByte(b)
e.wErr = err e.setColor(e.w, e.colors.Reset)
}
}
if err := e.w.WriteByte(b); err != nil {
e.wErr = err
}
if e.color {
if _, err := e.w.Write(e.colors.Reset); err != nil {
e.wErr = err
}
}
} }
} }
func (e *Encoder) write(bs []byte, color []byte) { func (e *Encoder) write(bs []byte, color []byte) {
if e.wErr != nil {
return
}
if color == nil { if color == nil {
if _, err := e.w.Write(bs); err != nil { e.w.Write(bs)
e.wErr = err
}
} else { } else {
e.setColor(e.w, color)
e.w.Write(bs)
e.setColor(e.w, e.colors.Reset)
}
}
func (e *Encoder) setColor(buf *bytes.Buffer, color []byte) {
if e.color { if e.color {
if _, err := e.w.Write(color); err != nil { buf.Write(color)
e.wErr = err
}
}
if _, err := e.w.Write(bs); err != nil {
e.wErr = err
}
if e.color {
if _, err := e.w.Write(e.colors.Reset); err != nil {
e.wErr = err
}
}
} }
} }