Skip to content

Commit 330e1e5

Browse files
committed
make sequence style configurable
1 parent 70ebea7 commit 330e1e5

File tree

4 files changed

+200
-3
lines changed

4 files changed

+200
-3
lines changed

goyaml.v3/emitterc.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_
226226
}
227227

228228
// Increase the indentation level.
229-
func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
229+
func yaml_emitter_increase_indent_compact(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool {
230230
emitter.indents = append(emitter.indents, emitter.indent)
231231
if emitter.indent < 0 {
232232
if flow {
@@ -241,7 +241,14 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
241241
emitter.indent += 2
242242
} else {
243243
// Everything else aligns to the chosen indentation.
244-
emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
244+
emitter.indent = emitter.best_indent * ((emitter.indent + emitter.best_indent) / emitter.best_indent)
245+
if compact_seq {
246+
// The value compact_seq passed in is almost always set to `false` when this function is called,
247+
// except when we are dealing with sequence nodes. So this gets triggered to subtract 2 only when we
248+
// are increasing the indent to account for sequence nodes, which will be correct because we need to
249+
// subtract 2 to account for the - at the beginning of the sequence node.
250+
emitter.indent = emitter.indent - 2
251+
}
245252
}
246253
}
247254
return true
@@ -728,7 +735,16 @@ func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_e
728735
// Expect a block item node.
729736
func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
730737
if first {
731-
if !yaml_emitter_increase_indent(emitter, false, false) {
738+
// emitter.mapping context tells us if we are currently in a mapping context.
739+
// emiiter.column tells us which column we are in in the yaml output. 0 is the first char of the column.
740+
// emitter.indentation tells us if the last character was an indentation character.
741+
// emitter.compact_sequence_indent tells us if '- ' is considered part of the indentation for sequence elements.
742+
// So, `seq` means that we are in a mapping context, and we are either at the first char of the column or
743+
// the last character was not an indentation character, and we consider '- ' part of the indentation
744+
// for sequence elements.
745+
seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
746+
emitter.compact_sequence_indent
747+
if !yaml_emitter_increase_indent_compact(emitter, false, false, seq) {
732748
return false
733749
}
734750
}

goyaml.v3/patch.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package yaml
18+
19+
// yaml_emitter_increase_indent preserves the original signature and delegates to
20+
// yaml_emitter_increase_indent_compact without compact-sequence indentation
21+
func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
22+
return yaml_emitter_increase_indent_compact(emitter, flow, indentless, false)
23+
}
24+
25+
// CompactSeqIndent makes it so that '- ' is considered part of the indentation.
26+
func (e *Encoder) CompactSeqIndent() {
27+
e.encoder.emitter.compact_sequence_indent = true
28+
}
29+
30+
// DefaultSeqIndent makes it so that '- ' is not considered part of the indentation.
31+
func (e *Encoder) DefaultSeqIndent() {
32+
e.encoder.emitter.compact_sequence_indent = false
33+
}

goyaml.v3/patch_test.go

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package yaml_test
18+
19+
import (
20+
"bytes"
21+
22+
. "gopkg.in/check.v1"
23+
yaml "sigs.k8s.io/yaml/goyaml.v3"
24+
)
25+
26+
func (s *S) TestCompactSeqIndentDefault(c *C) {
27+
var buf bytes.Buffer
28+
enc := yaml.NewEncoder(&buf)
29+
enc.CompactSeqIndent()
30+
err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
31+
c.Assert(err, Equals, nil)
32+
err = enc.Close()
33+
c.Assert(err, Equals, nil)
34+
// The default indent is 4, so these sequence elements get 2 indents as before
35+
c.Assert(buf.String(), Equals, `a:
36+
- b
37+
- c
38+
`)
39+
}
40+
41+
func (s *S) TestCompactSequenceWithSetIndent(c *C) {
42+
var buf bytes.Buffer
43+
enc := yaml.NewEncoder(&buf)
44+
enc.CompactSeqIndent()
45+
enc.SetIndent(2)
46+
err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
47+
c.Assert(err, Equals, nil)
48+
err = enc.Close()
49+
c.Assert(err, Equals, nil)
50+
// The sequence indent is 2, so these sequence elements don't get indented at all
51+
c.Assert(buf.String(), Equals, `a:
52+
- b
53+
- c
54+
`)
55+
}
56+
57+
type normal string
58+
type compact string
59+
60+
// newlinePlusNormalToNewlinePlusCompact maps the normal encoding (prefixed with a newline)
61+
// to the compact encoding (prefixed with a newline), for test cases in marshalTests
62+
var newlinePlusNormalToNewlinePlusCompact = map[normal]compact{
63+
normal(`
64+
v:
65+
- A
66+
- B
67+
`): compact(`
68+
v:
69+
- A
70+
- B
71+
`),
72+
73+
normal(`
74+
v:
75+
- A
76+
- |-
77+
B
78+
C
79+
`): compact(`
80+
v:
81+
- A
82+
- |-
83+
B
84+
C
85+
`),
86+
87+
normal(`
88+
v:
89+
- A
90+
- 1
91+
- B:
92+
- 2
93+
- 3
94+
`): compact(`
95+
v:
96+
- A
97+
- 1
98+
- B:
99+
- 2
100+
- 3
101+
`),
102+
103+
normal(`
104+
a:
105+
- 1
106+
- 2
107+
`): compact(`
108+
a:
109+
- 1
110+
- 2
111+
`),
112+
113+
normal(`
114+
a:
115+
b:
116+
- c: 1
117+
d: 2
118+
`): compact(`
119+
a:
120+
b:
121+
- c: 1
122+
d: 2
123+
`),
124+
}
125+
126+
func (s *S) TestEncoderCompactIndents(c *C) {
127+
for i, item := range marshalTests {
128+
c.Logf("test %d. %q", i, item.data)
129+
var buf bytes.Buffer
130+
enc := yaml.NewEncoder(&buf)
131+
enc.CompactSeqIndent()
132+
err := enc.Encode(item.value)
133+
c.Assert(err, Equals, nil)
134+
err = enc.Close()
135+
c.Assert(err, Equals, nil)
136+
137+
// Default to expecting the item data
138+
expected := item.data
139+
// If there's a different compact representation, use that
140+
if c, ok := newlinePlusNormalToNewlinePlusCompact[normal("\n"+item.data)]; ok {
141+
expected = string(c[1:])
142+
}
143+
144+
c.Assert(buf.String(), Equals, expected)
145+
}
146+
}

goyaml.v3/yamlh.go

+2
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ type yaml_emitter_t struct {
742742

743743
indent int // The current indentation level.
744744

745+
compact_sequence_indent bool // Is '- ' is considered part of the indentation for sequence elements?
746+
745747
flow_level int // The current flow level.
746748

747749
root_context bool // Is it the document root context?

0 commit comments

Comments
 (0)