Skip to content

Commit

Permalink
Fix indentation for raw string newlines
Browse files Browse the repository at this point in the history
  • Loading branch information
shuheiktgw committed Jan 22, 2025
1 parent f739772 commit c559864
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 56 deletions.
10 changes: 6 additions & 4 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,11 +816,12 @@ func (n *StringNode) String() string {
// It works mostly, but inconsistencies occur if line break characters are mixed.
header := token.LiteralBlockHeader(n.Value)
space := strings.Repeat(" ", n.Token.Position.Column-1)
indent := strings.Repeat(" ", n.Token.Position.IndentNum)
values := []string{}
for _, v := range strings.Split(n.Value, lbc) {
values = append(values, fmt.Sprintf("%s %s", space, v))
values = append(values, fmt.Sprintf("%s%s%s", space, indent, v))
}
block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s %s", lbc, space)), fmt.Sprintf(" %s", space))
block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s%s%s", lbc, indent, space)), fmt.Sprintf("%s%s", indent, space))
return fmt.Sprintf("%s%s%s", header, lbc, block)
} else if len(n.Value) > 0 && (n.Value[0] == '{' || n.Value[0] == '[') {
return fmt.Sprintf(`'%s'`, n.Value)
Expand All @@ -847,11 +848,12 @@ func (n *StringNode) stringWithoutComment() string {
// It works mostly, but inconsistencies occur if line break characters are mixed.
header := token.LiteralBlockHeader(n.Value)
space := strings.Repeat(" ", n.Token.Position.Column-1)
indent := strings.Repeat(" ", n.Token.Position.IndentNum)
values := []string{}
for _, v := range strings.Split(n.Value, lbc) {
values = append(values, fmt.Sprintf("%s %s", space, v))
values = append(values, fmt.Sprintf("%s%s%s", space, indent, v))
}
block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s %s", lbc, space)), fmt.Sprintf(" %s", space))
block := strings.TrimSuffix(strings.TrimSuffix(strings.Join(values, lbc), fmt.Sprintf("%s%s%s", lbc, indent, space)), fmt.Sprintf(" %s", space))
return fmt.Sprintf("%s%s%s", header, lbc, block)
} else if len(n.Value) > 0 && (n.Value[0] == '{' || n.Value[0] == '[') {
return fmt.Sprintf(`'%s'`, n.Value)
Expand Down
47 changes: 25 additions & 22 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ const (
type Encoder struct {
writer io.Writer
opts []EncodeOption
indent int
indentSequence bool
singleQuote bool
isFlowStyle bool
isJSONStyle bool
Expand All @@ -41,11 +39,12 @@ type Encoder struct {
commentMap map[*Path][]*Comment
written bool

line int
column int
offset int
indentNum int
indentLevel int
line int
column int
offset int
indentNum int
indentLevel int
indentSequence bool
}

// NewEncoder returns a new encoder that writes to w.
Expand All @@ -54,12 +53,12 @@ func NewEncoder(w io.Writer, opts ...EncodeOption) *Encoder {
return &Encoder{
writer: w,
opts: opts,
indent: DefaultIndentSpaces,
anchorPtrToNameMap: map[uintptr]string{},
customMarshalerMap: map[reflect.Type]func(interface{}) ([]byte, error){},
line: 1,
column: 1,
offset: 0,
indentNum: DefaultIndentSpaces,
}
}

Expand Down Expand Up @@ -573,8 +572,13 @@ func (e *Encoder) encodeBool(v bool) *ast.BoolNode {

func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
if e.indentSequence {
e.column += e.indent
e.column += e.indentNum
}
defer func() {
if e.indentSequence {
e.column -= e.indentNum
}
}()
column := e.column
sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
for i := 0; i < value.Len(); i++ {
Expand All @@ -584,16 +588,18 @@ func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.Se
}
sequence.Values = append(sequence.Values, node)
}
if e.indentSequence {
e.column -= e.indent
}
return sequence, nil
}

func (e *Encoder) encodeArray(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
if e.indentSequence {
e.column += e.indent
e.column += e.indentNum
}
defer func() {
if e.indentSequence {
e.column -= e.indentNum
}
}()
column := e.column
sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
for i := 0; i < value.Len(); i++ {
Expand All @@ -603,9 +609,6 @@ func (e *Encoder) encodeArray(ctx context.Context, value reflect.Value) (*ast.Se
}
sequence.Values = append(sequence.Values, node)
}
if e.indentSequence {
e.column -= e.indent
}
return sequence, nil
}

Expand All @@ -617,7 +620,7 @@ func (e *Encoder) encodeMapItem(ctx context.Context, item MapItem, column int) (
return nil, err
}
if e.isMapNode(value) {
value.AddColumn(e.indent)
value.AddColumn(e.indentNum)
}
return ast.MappingValue(
token.New("", "", e.pos(column)),
Expand Down Expand Up @@ -660,7 +663,7 @@ func (e *Encoder) encodeMap(ctx context.Context, value reflect.Value, column int
return nil
}
if e.isMapNode(value) {
value.AddColumn(e.indent)
value.AddColumn(e.indentNum)
}
node.Values = append(node.Values, ast.MappingValue(
nil,
Expand Down Expand Up @@ -783,7 +786,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
return nil, err
}
if e.isMapNode(value) {
value.AddColumn(e.indent)
value.AddColumn(e.indentNum)
}
var key ast.MapKeyNode = e.encodeString(structField.RenderName, column)
switch {
Expand Down Expand Up @@ -833,8 +836,8 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
// if declared same key name, skip encoding this field
continue
}
key.AddColumn(-e.indent)
value.AddColumn(-e.indent)
key.AddColumn(-e.indentNum)
value.AddColumn(-e.indentNum)
node.Values = append(node.Values, ast.MappingValue(nil, key, value))
}
continue
Expand All @@ -848,7 +851,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
node.Values = append(node.Values, ast.MappingValue(nil, key, value))
}
if hasInlineAnchorField {
node.AddColumn(e.indent)
node.AddColumn(e.indentNum)
anchorName := "anchor"
anchorNode := ast.Anchor(token.New("&", "&", e.pos(column)))
anchorNode.Name = ast.String(token.New(anchorName, anchorName, e.pos(column)))
Expand Down
80 changes: 51 additions & 29 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1540,49 +1540,71 @@ func TestIssue356(t *testing.T) {
}

func TestMarshalIndentWithMultipleText(t *testing.T) {
t.Run("depth1", func(t *testing.T) {
b, err := yaml.MarshalWithOptions(map[string]interface{}{
"key": []string{`line1
tests := []struct {
name string
input map[string]interface{}
indent yaml.EncodeOption
want string
}{
{
name: "depth1",
input: map[string]interface{}{
"key": []string{`line1
line2
line3`},
}, yaml.Indent(2))
if err != nil {
t.Fatal(err)
}
got := string(b)
expected := `key:
},
indent: yaml.Indent(2),
want: `key:
- |-
line1
line2
line3
`
if expected != got {
t.Fatalf("failed to encode.\nexpected:\n%s\nbut got:\n%s\n", expected, got)
}
})
t.Run("depth2", func(t *testing.T) {
b, err := yaml.MarshalWithOptions(map[string]interface{}{
"key": map[string]interface{}{
"key2": []string{`line1
`,
},
{
name: "depth2",
input: map[string]interface{}{
"key": map[string]interface{}{
"key2": []string{`line1
line2
line3`},
},
},
}, yaml.Indent(2))
if err != nil {
t.Fatal(err)
}
got := string(b)
expected := `key:
indent: yaml.Indent(2),
want: `key:
key2:
- |-
line1
line2
line3
`
if expected != got {
t.Fatalf("failed to encode.\nexpected:\n%s\nbut got:\n%s\n", expected, got)
}
})
`,
},
{
name: "raw string new lines",
input: map[string]interface{}{
"key": "line1\nline2\nline3",
},
indent: yaml.Indent(4),
want: `key: |-
line1
line2
line3
`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b, err := yaml.MarshalWithOptions(tt.input, tt.indent)
if err != nil {
t.Fatalf("failed to marshal yaml: %v", err)
}
got := string(b)
if tt.want != got {
t.Fatalf("failed to encode.\nexpected:\n%s\nbut got:\n%s\n", tt.want, got)
}
})
}
}

type bytesMarshaler struct{}
Expand Down
2 changes: 1 addition & 1 deletion option.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ type EncodeOption func(e *Encoder) error
// Indent change indent number
func Indent(spaces int) EncodeOption {
return func(e *Encoder) error {
e.indent = spaces
e.indentNum = spaces
return nil
}
}
Expand Down

0 comments on commit c559864

Please sign in to comment.