hclwrite: Generate multi-line objects and maps

The previous syntax for object and map values was a single line of
key-value pairs. For example:

  object = { bar = 5, baz = true, foo = "foo" }

This is very compact, but in practice for many HCL values, less readable
and less common than a multi-line object format. This commit changes the
generated output from hclwrite to one line per attribute.

Examples of the new format:

  // Empty object/map is a single line
  a = {}

  // Single-value object/map has the attribute on a separate line
  b = {
    bar = 5
  }

  // Multi-value object/map has one line per attribute
  c = {
    bar = 5
    baz = true
  }
This commit is contained in:
Alisdair McDiarmid 2020-05-06 09:45:13 -04:00
parent 7098edec61
commit 926e53e338
3 changed files with 53 additions and 24 deletions

View File

@ -48,9 +48,13 @@ func Example_generateFromScratch() {
// Output:
// string = "foo"
//
// object = { bar = 5, baz = true, foo = "foo" }
// bool = false
// path = env.PATH
// object = {
// bar = 5
// baz = true
// foo = "foo"
// }
// bool = false
// path = env.PATH
//
// foo {
// hello = "world"

View File

@ -119,15 +119,15 @@ func appendTokensForValue(val cty.Value, toks Tokens) Tokens {
Type: hclsyntax.TokenOBrace,
Bytes: []byte{'{'},
})
if val.LengthInt() > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
})
}
i := 0
for it := val.ElementIterator(); it.Next(); {
if i > 0 {
toks = append(toks, &Token{
Type: hclsyntax.TokenComma,
Bytes: []byte{','},
})
}
eKey, eVal := it.Element()
if hclsyntax.ValidIdentifier(eKey.AsString()) {
toks = append(toks, &Token{
@ -142,6 +142,10 @@ func appendTokensForValue(val cty.Value, toks Tokens) Tokens {
Bytes: []byte{'='},
})
toks = appendTokensForValue(eVal, toks)
toks = append(toks, &Token{
Type: hclsyntax.TokenNewline,
Bytes: []byte{'\n'},
})
i++
}

View File

@ -340,10 +340,14 @@ func TestTokensForValue(t *testing.T) {
Type: hclsyntax.TokenOBrace,
Bytes: []byte(`{`),
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte(`foo`),
SpacesBefore: 1,
SpacesBefore: 2,
},
{
Type: hclsyntax.TokenEqual,
@ -356,9 +360,12 @@ func TestTokensForValue(t *testing.T) {
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
SpacesBefore: 1,
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
},
},
},
@ -372,10 +379,14 @@ func TestTokensForValue(t *testing.T) {
Type: hclsyntax.TokenOBrace,
Bytes: []byte(`{`),
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte(`bar`),
SpacesBefore: 1,
SpacesBefore: 2,
},
{
Type: hclsyntax.TokenEqual,
@ -388,13 +399,13 @@ func TestTokensForValue(t *testing.T) {
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenComma,
Bytes: []byte(`,`),
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenIdent,
Bytes: []byte(`foo`),
SpacesBefore: 1,
SpacesBefore: 2,
},
{
Type: hclsyntax.TokenEqual,
@ -407,9 +418,12 @@ func TestTokensForValue(t *testing.T) {
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
SpacesBefore: 1,
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
},
},
},
@ -422,10 +436,14 @@ func TestTokensForValue(t *testing.T) {
Type: hclsyntax.TokenOBrace,
Bytes: []byte(`{`),
},
{
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenOQuote,
Bytes: []byte(`"`),
SpacesBefore: 1,
SpacesBefore: 2,
},
{
Type: hclsyntax.TokenQuotedLit,
@ -446,9 +464,12 @@ func TestTokensForValue(t *testing.T) {
SpacesBefore: 1,
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
SpacesBefore: 1,
Type: hclsyntax.TokenNewline,
Bytes: []byte("\n"),
},
{
Type: hclsyntax.TokenCBrace,
Bytes: []byte(`}`),
},
},
},