Skip to content

Commit

Permalink
emitter: add indentless_block_sequence option (#13)
Browse files Browse the repository at this point in the history
* emitter: add indentless_block_sequence option

Add an option that will force block sequence items not to be indented.

* add formatting test suites
  • Loading branch information
braydonk committed Mar 18, 2023
1 parent 29fa296 commit 82670ba
Show file tree
Hide file tree
Showing 18 changed files with 186 additions and 75 deletions.
6 changes: 6 additions & 0 deletions apic.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,16 @@ func yaml_emitter_set_explicit_document_start(emitter *yaml_emitter_t, document_
emitter.explicit_document_start = document_start
}

// Set assume folded as literal.
func yaml_emitter_set_assume_folded_as_literal(emitter *yaml_emitter_t, folded_as_literal bool) {
emitter.assume_folded_as_literal = folded_as_literal
}

// Set indentless block sequence.
func yaml_emitter_set_indentless_block_sequence(emitter *yaml_emitter_t, indentless_block_sequence bool) {
emitter.indentless_block_sequence = indentless_block_sequence
}

///*
// * Destroy a token object.
// */
Expand Down
3 changes: 1 addition & 2 deletions emitterc.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool
} else if !indentless {
// [Go] This was changed so that indentations are more regular.
if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
// The first indent inside a sequence will just skip the "- " indicator.
emitter.indent += 2
} else {
// Everything else aligns to the chosen indentation.
Expand Down Expand Up @@ -727,7 +726,7 @@ func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_e
// Expect a block item node.
func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
if first {
if !yaml_emitter_increase_indent(emitter, false, false) {
if !yaml_emitter_increase_indent(emitter, false, emitter.indentless_block_sequence) {
return false
}
}
Expand Down
3 changes: 3 additions & 0 deletions formattest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Format Tests

This is where I will write any formatting tests that mess with decoding and immediately encoding a document.
53 changes: 53 additions & 0 deletions formattest/encode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package formattest

import (
"testing"

"github.com/braydonk/yaml"
)

func TestExplicitDocumentStart(t *testing.T) {
formatTestCase{
name: "explicit document start",
folder: "document_start",
configureDecoder: noopDecoder,
configureEncoder: func(enc *yaml.Encoder) {
enc.SetExplicitDocumentStart(true)
},
}.Run(t)
}

func TestIndentless(t *testing.T) {
formatTestCase{
name: "indentless array",
folder: "indentless",
configureDecoder: noopDecoder,
configureEncoder: func(enc *yaml.Encoder) {
enc.SetIndentlessBlockSequence(true)
},
}.Run(t)
}

func TestIndentedToIndentless(t *testing.T) {
formatTestCase{
name: "indented to indentless array",
folder: "indented_to_indentless",
configureDecoder: noopDecoder,
configureEncoder: func(enc *yaml.Encoder) {
enc.SetIndentlessBlockSequence(true)
},
}.Run(t)
}

func TestBlockScalar(t *testing.T) {
formatTestCase{
name: "block scalar decoding and encoding",
folder: "block_scalar",
configureDecoder: func(dec *yaml.Decoder) {
dec.SetScanBlockScalarAsLiteral(true)
},
configureEncoder: func(enc *yaml.Encoder) {
enc.SetAssumeBlockAsLiteral(true)
},
}.Run(t)
}
77 changes: 77 additions & 0 deletions formattest/testcase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package formattest

import (
"bytes"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"testing"

"github.com/braydonk/yaml"
)

type decoderConfigureFunc func(*yaml.Decoder)

func noopDecoder(dec *yaml.Decoder) {}

type encoderConfigureFunc func(*yaml.Encoder)

type formatTestCase struct {
name string
folder string
configureDecoder decoderConfigureFunc
configureEncoder encoderConfigureFunc
}

func (tc formatTestCase) Run(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
// Read test input
input, err := tc.readTestdataFile("input.yaml")
if err != nil {
t.Fatal(err)
}

// Configure Decoder
reader := bytes.NewReader(input)
decoder := yaml.NewDecoder(reader)
tc.configureDecoder(decoder)

// Decode input document
var n yaml.Node
err = decoder.Decode(&n)
if err != nil && !errors.Is(err, io.EOF) {
t.Fatalf("expect EOF, got:\n%v", err)
}

// Configure Encoder
var buf bytes.Buffer
enc := yaml.NewEncoder(&buf)
tc.configureEncoder(enc)

// Encode the decoded input document
err = enc.Encode(&n)
if err != nil {
t.Fatalf("expected nil err, got:\n%v", err)
}

// Read the expected output
expected, err := tc.readTestdataFile("expected.yaml")
if err != nil {
t.Fatal(err)
}
if buf.String() != string(expected) {
t.Fatalf("expected:\n%s\nactual:\n%s", string(expected), buf.String())
}
})
}

func (tc formatTestCase) readTestdataFile(path string) ([]byte, error) {
fullPath := filepath.Join("testdata", tc.folder, path)
content, err := os.ReadFile(fullPath)
if err != nil {
return nil, fmt.Errorf("path %s not found", fullPath)
}
return content, nil
}
4 changes: 4 additions & 0 deletions formattest/testdata/block_scalar/expected.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
commands: >
[ -f "/usr/local/bin/foo" ] &&
echo "skip install" ||
go install github.com/foo/foo@latest
4 changes: 4 additions & 0 deletions formattest/testdata/block_scalar/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
commands: >
[ -f "/usr/local/bin/foo" ] &&
echo "skip install" ||
go install github.com/foo/foo@latest
2 changes: 2 additions & 0 deletions formattest/testdata/document_start/expected.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
a: 1
1 change: 1 addition & 0 deletions formattest/testdata/document_start/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a: 1
3 changes: 3 additions & 0 deletions formattest/testdata/indented_to_indentless/expected.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
a:
- 1
- 2
3 changes: 3 additions & 0 deletions formattest/testdata/indented_to_indentless/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
a:
- 1
- 2
7 changes: 7 additions & 0 deletions formattest/testdata/indentless/expected.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
a:
- 1
- 2
b:
c:
- 1
- 2
7 changes: 7 additions & 0 deletions formattest/testdata/indentless/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
a:
- 1
- 2
b:
c:
- 1
- 2
3 changes: 0 additions & 3 deletions test/README.md

This file was deleted.

32 changes: 0 additions & 32 deletions test/encode_test.go

This file was deleted.

31 changes: 0 additions & 31 deletions test/node_test.go

This file was deleted.

7 changes: 7 additions & 0 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,17 @@ func (e *Encoder) SetExplicitDocumentStart(documentStart bool) {
yaml_emitter_set_explicit_document_start(&e.encoder.emitter, documentStart)
}

// SetAssumeBlockAsLiteral is a workaround to allow block literals
// to retain their scanned form in the resulting marshalled document.
func (e *Encoder) SetAssumeBlockAsLiteral(assumeLiteralBlock bool) {
yaml_emitter_set_assume_folded_as_literal(&e.encoder.emitter, assumeLiteralBlock)
}

// SetIndentlessBlockSequence forces block sequence items not to be indented.
func (e *Encoder) SetIndentlessBlockSequence(indentlessBlockSequence bool) {
yaml_emitter_set_indentless_block_sequence(&e.encoder.emitter, indentlessBlockSequence)
}

// Close closes the encoder by writing any remaining data.
// It does not write a stream terminating string "...".
func (e *Encoder) Close() (err error) {
Expand Down
15 changes: 8 additions & 7 deletions yamlh.go
Original file line number Diff line number Diff line change
Expand Up @@ -730,13 +730,14 @@ type yaml_emitter_t struct {

// Emitter stuff

canonical bool // If the output is in the canonical style?
best_indent int // The number of indentation spaces.
best_width int // The preferred width of the output lines.
unicode bool // Allow unescaped non-ASCII characters?
line_break yaml_break_t // The preferred line break.
explicit_document_start bool // Force an explicit document start
assume_folded_as_literal bool // Assume blocks were scanned as literals
canonical bool // If the output is in the canonical style?
best_indent int // The number of indentation spaces.
best_width int // The preferred width of the output lines.
unicode bool // Allow unescaped non-ASCII characters?
line_break yaml_break_t // The preferred line break.
explicit_document_start bool // Force an explicit document start
assume_folded_as_literal bool // Assume blocks were scanned as literals
indentless_block_sequence bool // Do not indent block sequences

state yaml_emitter_state_t // The current emitter state.
states []yaml_emitter_state_t // The stack of states.
Expand Down

0 comments on commit 82670ba

Please sign in to comment.