-
Notifications
You must be signed in to change notification settings - Fork 31
/
sink.go
98 lines (83 loc) · 2.67 KB
/
sink.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package editor
import (
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/hcl/v2/hclwrite"
)
// Sink is an interface which reads HCL and writes bytes.
type Sink interface {
// Sink reads HCL and writes bytes.
Sink(*hclwrite.File) ([]byte, error)
}
// formater is a Sink implementation to format HCL.
type formater struct {
}
// Sink reads HCL and writes formatted contents.
func (f *formater) Sink(inFile *hclwrite.File) ([]byte, error) {
raw := inFile.BuildTokens(nil).Bytes()
out := hclwrite.Format(raw)
return out, nil
}
// verticalFormater is a Sink implementation to format HCL.
// At time of writing, the default hcl formatter does not support vertical
// formatting. However, it's useful in some cases such as removing a block
// because leading and trailing newline tokens don't belong to a block, so
// deleting a block leaves extra newline tokens.
// This is not included in the original hcl implementation, so we should not be
// the default behavior of the formater not to break existing fomatted hcl configurations.
// Opt-in only where you neeed this feature.
// Note that verticalFormatter formats not only in vertical but also horizontal
// because we cannot use multiple Sink implementations at once.
type verticalFormater struct {
}
// Sink reads HCL and writes formatted contents in vertical and horizontal.
func (f *verticalFormater) Sink(inFile *hclwrite.File) ([]byte, error) {
tokens := inFile.BuildTokens(nil)
vertical := VerticalFormat(tokens)
// default horizontal format
out := hclwrite.Format(vertical.Bytes())
return out, nil
}
// VerticalFormat formats token in vertical.
func VerticalFormat(tokens hclwrite.Tokens) hclwrite.Tokens {
trimmed := trimNewLine(tokens)
removed := removeDuplicatedNewLine(trimmed)
return removed
}
// trimNewLine trimsleading and trailing newlines from tokens
func trimNewLine(tokens hclwrite.Tokens) hclwrite.Tokens {
begin := 0
for ; begin < len(tokens); begin++ {
if tokens[begin].Type != hclsyntax.TokenNewline {
break
}
}
end := len(tokens)
var eof *hclwrite.Token
for ; end > begin; end-- {
if tokens[end-1].Type == hclsyntax.TokenEOF {
// skip EOF
eof = tokens[end-1]
continue
}
if tokens[end-1].Type != hclsyntax.TokenNewline {
break
}
}
ret := append(tokens[begin:end], eof)
return ret
}
// removeDuplicatedNewLine removes duplicated newlines
func removeDuplicatedNewLine(tokens hclwrite.Tokens) hclwrite.Tokens {
var removed hclwrite.Tokens
before := false
for _, token := range tokens {
if token.Type != hclsyntax.TokenNewline {
removed = append(removed, token)
before = false
} else if !before {
removed = append(removed, token)
before = true
}
}
return removed
}