cue/format: some tweaks
Always keep tabs used for indentation and explicitly
expand. This fixes some alignment issues.
This also prepares for having better eval output.
The default for single-element objects without
position information is now to not simplify.
Change-Id: I47546bce433cf99e2fc153540591cea51841b24c
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2165
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cmd/cue/cmd/testdata/partial/eval.out b/cmd/cue/cmd/testdata/partial/eval.out
index 0f97899..ac847f1 100644
--- a/cmd/cue/cmd/testdata/partial/eval.out
+++ b/cmd/cue/cmd/testdata/partial/eval.out
@@ -5,16 +5,20 @@
A = a
b: {
idx: A[str]
- a b: 4
+ a: {
+ b: 4
+ }
str: string
}
a: {
- b: 3
- c: 4
+ b: 3
+ c: 4
}
c: {
idx: 3
- a b: 4
+ a: {
+ b: 4
+ }
str: "b"
}
}
diff --git a/cue/export_test.go b/cue/export_test.go
index 6835f60..68d59bd 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -256,7 +256,7 @@
{
b: [{
<X>: int
- "f": 4 if a > 4
+ f: 4 if a > 4
}][a]
a: int
c: 1
@@ -277,7 +277,7 @@
buf := &bytes.Buffer{}
opts := options{raw: !tc.eval}
- err := format.Node(buf, export(ctx, v.eval(ctx), opts))
+ err := format.Node(buf, export(ctx, v.eval(ctx), opts), format.Simplify())
if err != nil {
log.Fatal(err)
}
@@ -330,7 +330,7 @@
buf := &bytes.Buffer{}
opts := options{raw: false}
- err = format.Node(buf, export(ctx, v.eval(ctx), opts))
+ err = format.Node(buf, export(ctx, v.eval(ctx), opts), format.Simplify())
if err != nil {
log.Fatal(err)
}
diff --git a/cue/format/format.go b/cue/format/format.go
index 89f0438..9bb81a5 100644
--- a/cue/format/format.go
+++ b/cue/format/format.go
@@ -107,14 +107,18 @@
type config struct {
UseSpaces bool
TabIndent bool
- Tabwidth int // default: 8
+ Tabwidth int // default: 4
Indent int // default: 0 (all code is indented at least by this much)
simplify bool
}
func newConfig(opt []Option) *config {
- cfg := &config{Tabwidth: 8, TabIndent: true, UseSpaces: true}
+ cfg := &config{
+ Tabwidth: 8,
+ TabIndent: true,
+ UseSpaces: true,
+ }
for _, o := range opt {
o(cfg)
}
@@ -123,27 +127,24 @@
// Config defines the output of Fprint.
func (cfg *config) fprint(output io.Writer, node interface{}) (err error) {
- // print node
var p printer
p.init(cfg)
if err = printNode(node, &p); err != nil {
return err
}
- minwidth := cfg.Tabwidth
-
padchar := byte('\t')
if cfg.UseSpaces {
- padchar = ' '
+ padchar = byte(' ')
}
- twmode := tabwriter.DiscardEmptyColumns | tabwriter.StripEscape
+ twmode := tabwriter.StripEscape | tabwriter.TabIndent | tabwriter.DiscardEmptyColumns
if cfg.TabIndent {
- minwidth = 0
twmode |= tabwriter.TabIndent
}
- tw := tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padchar, twmode)
+ buf := &bytes.Buffer{}
+ tw := tabwriter.NewWriter(buf, 0, cfg.Tabwidth, 1, padchar, twmode)
// write printer result via tabwriter/trimmer to output
if _, err = tw.Write(p.output); err != nil {
@@ -151,7 +152,16 @@
}
err = tw.Flush()
- return
+ if err != nil {
+ return err
+ }
+
+ b := buf.Bytes()
+ if !cfg.TabIndent {
+ b = bytes.ReplaceAll(b, []byte{'\t'}, bytes.Repeat([]byte{' '}, cfg.Tabwidth))
+ }
+ _, err = output.Write(b)
+ return err
}
// A formatter walks a syntax.Node, interspersed with comments and spacing
diff --git a/cue/format/format_test.go b/cue/format/format_test.go
index c6e49ae..46b8a4a 100644
--- a/cue/format/format_test.go
+++ b/cue/format/format_test.go
@@ -58,7 +58,7 @@
// if any.
func format(src []byte, mode checkMode) ([]byte, error) {
// parse src
- var opts []Option
+ opts := []Option{TabIndent(true)}
if mode&simplify != 0 {
opts = append(opts, Simplify())
}
diff --git a/cue/format/node.go b/cue/format/node.go
index 6054e31..97850f2 100644
--- a/cue/format/node.go
+++ b/cue/format/node.go
@@ -116,7 +116,9 @@
lastSize := len(f.labelBuf)
f.labelBuf = f.labelBuf[:0]
first, opt := n.Label, n.Optional != token.NoPos
- for {
+ // If the field has a valid position, we assume that an unspecified
+ // Lbrace does not signal the intend to collapse fields.
+ for n.Label.Pos().IsValid() || f.printer.cfg.simplify {
obj, ok := n.Value.(*ast.StructLit)
if !ok || len(obj.Elts) != 1 || (obj.Lbrace.IsValid() && !f.printer.cfg.simplify) {
break
diff --git a/internal/protobuf/protobuf_test.go b/internal/protobuf/protobuf_test.go
index d75126d..e21a126 100644
--- a/internal/protobuf/protobuf_test.go
+++ b/internal/protobuf/protobuf_test.go
@@ -46,7 +46,7 @@
if f, err := Parse(filename, nil, c); err != nil {
fmt.Fprintln(out, err)
} else {
- format.Node(out, f)
+ format.Node(out, f, format.Simplify())
}
wantFile := filepath.Join("testdata", filepath.Base(file)+".out.cue")
diff --git a/internal/protobuf/testdata/client_config.proto.out.cue b/internal/protobuf/testdata/client_config.proto.out.cue
index 880309e..efa1f40 100644
--- a/internal/protobuf/testdata/client_config.proto.out.cue
+++ b/internal/protobuf/testdata/client_config.proto.out.cue
@@ -52,8 +52,8 @@
"FAIL_CLOSE"
NetworkFailPolicy_FailPolicy_value: {
- "FAIL_OPEN": 0
- "FAIL_CLOSE": 1
+ FAIL_OPEN: 0
+ FAIL_CLOSE: 1
}
// Defines the per-service client configuration.
diff --git a/internal/protobuf/testdata/gateway.proto.out.cue b/internal/protobuf/testdata/gateway.proto.out.cue
index 14e4624..dc17a26 100644
--- a/internal/protobuf/testdata/gateway.proto.out.cue
+++ b/internal/protobuf/testdata/gateway.proto.out.cue
@@ -213,8 +213,8 @@
// label search is restricted to the configuration namespace in which the
// the resource is present. In other words, the Gateway resource must
// reside in the same namespace as the gateway workload instance.
- selector <_>: string
- selector?: {<name>: name}
+ selector <_>: string
+ selector? <name>: name
}
// `Server` describes the properties of the proxy on a given load balancer
@@ -413,10 +413,10 @@
"AUTO_PASSTHROUGH"
Server_TLSOptions_TLSmode_value: {
- "PASSTHROUGH": 0
- "SIMPLE": 1
- "MUTUAL": 2
- "AUTO_PASSTHROUGH": 3
+ PASSTHROUGH: 0
+ SIMPLE: 1
+ MUTUAL: 2
+ AUTO_PASSTHROUGH: 3
}
// TLS protocol versions.
@@ -428,11 +428,11 @@
"TLSV1_3" // TLS version 1.3
Server_TLSOptions_TLSProtocol_value: {
- "TLS_AUTO": 0
- "TLSV1_0": 1
- "TLSV1_1": 2
- "TLSV1_2": 3
- "TLSV1_3": 4
+ TLS_AUTO: 0
+ TLSV1_0: 1
+ TLSV1_1: 2
+ TLSV1_2: 3
+ TLSV1_3: 4
}
// Port describes the properties of a specific port of a service.
diff --git a/internal/third_party/yaml/decode_test.go b/internal/third_party/yaml/decode_test.go
index 71cbf3c..d33e56c 100644
--- a/internal/third_party/yaml/decode_test.go
+++ b/internal/third_party/yaml/decode_test.go
@@ -209,7 +209,9 @@
// Structs
{
"a: {b: c}",
- `a b: "c"`,
+ `a: {
+ b: "c"
+}`,
},
{
"hello: world",
@@ -231,7 +233,10 @@
"a: true",
}, {
"{ a: 1, b: {c: 1} }",
- "a: 1\nb c: 1",
+ `a: 1
+b: {
+ c: 1
+}`,
},
// Some cross type conversions
@@ -396,7 +401,12 @@
d: 2`,
}, {
"a: &a {c: 1}\nb: *a",
- "a c: 1\nb c: 1",
+ `a: {
+ c: 1
+}
+b: {
+ c: 1
+}`,
}, {
"a: &a [1, 2]\nb: *a",
"a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a
@@ -449,7 +459,9 @@
// issue #295 (allow scalars with colons in flow mappings and sequences)
{
"a: {b: https://github.com/go-yaml/yaml}",
- `a b: "https://github.com/go-yaml/yaml"`,
+ `a: {
+ b: "https://github.com/go-yaml/yaml"
+}`,
},
{
"a: [https://github.com/go-yaml/yaml]",
@@ -493,13 +505,19 @@
a: 1
d: 4
c: 3
-sub e: 5`,
+sub: {
+ e: 5
+}`,
},
// Issue #39.
{
"a:\n b:\n c: d\n",
- `a b c: "d"`,
+ `a: {
+ b: {
+ c: "d"
+ }
+}`,
},
// Timestamps
diff --git a/internal/third_party/yaml/testdata/merge.out b/internal/third_party/yaml/testdata/merge.out
index e3edf5a..b8ed7a4 100644
--- a/internal/third_party/yaml/testdata/merge.out
+++ b/internal/third_party/yaml/testdata/merge.out
@@ -1,16 +1,18 @@
// From http://yaml.org/type/merge.html
// Test
-anchors list: [{
- x: 1
- y: 2
-}, {
- x: 0
- y: 2
-}, {
- r: 10
-}, {
- r: 1
-}]
+anchors: {
+ list: [{
+ x: 1
+ y: 2
+ }, {
+ x: 0
+ y: 2
+ }, {
+ r: 10
+ }, {
+ r: 1
+ }]
+}
// All the following maps are equal:
plain: {
// Explicit keys