2015-10-24 21:04:31 +00:00
|
|
|
package printer
|
2015-10-24 22:23:50 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2015-10-25 13:08:09 +00:00
|
|
|
"io"
|
2015-10-24 22:23:50 +00:00
|
|
|
|
|
|
|
"github.com/fatih/hcl/ast"
|
|
|
|
)
|
|
|
|
|
2015-10-25 13:08:09 +00:00
|
|
|
const (
|
|
|
|
blank = byte(' ')
|
|
|
|
newline = byte('\n')
|
|
|
|
tab = byte('\t')
|
|
|
|
)
|
|
|
|
|
2015-10-24 22:23:50 +00:00
|
|
|
func (p *printer) printNode(n ast.Node) []byte {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
|
|
|
switch t := n.(type) {
|
|
|
|
case *ast.ObjectList:
|
2015-10-25 13:08:09 +00:00
|
|
|
for i, item := range t.Items {
|
2015-10-24 22:23:50 +00:00
|
|
|
buf.Write(p.printObjectItem(item))
|
2015-10-25 13:08:09 +00:00
|
|
|
if i != len(t.Items)-1 {
|
2015-10-25 13:12:08 +00:00
|
|
|
buf.Write([]byte{newline, newline})
|
2015-10-25 13:08:09 +00:00
|
|
|
}
|
2015-10-24 22:23:50 +00:00
|
|
|
}
|
|
|
|
case *ast.ObjectKey:
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteString(t.Token.Text)
|
2015-10-24 22:23:50 +00:00
|
|
|
case *ast.ObjectItem:
|
|
|
|
buf.Write(p.printObjectItem(t))
|
|
|
|
case *ast.LiteralType:
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteString(t.Token.Text)
|
2015-10-24 22:23:50 +00:00
|
|
|
case *ast.ListType:
|
|
|
|
buf.Write(p.printList(t))
|
|
|
|
case *ast.ObjectType:
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.Write(p.printObjectType(t))
|
2015-10-24 22:23:50 +00:00
|
|
|
default:
|
|
|
|
fmt.Printf(" unknown type: %T\n", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *printer) printObjectItem(o *ast.ObjectItem) []byte {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
|
|
|
for i, k := range o.Keys {
|
|
|
|
buf.WriteString(k.Token.Text)
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(blank)
|
2015-10-24 22:23:50 +00:00
|
|
|
|
|
|
|
// reach end of key
|
|
|
|
if i == len(o.Keys)-1 {
|
|
|
|
buf.WriteString("=")
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(blank)
|
2015-10-24 22:23:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.Write(p.printNode(o.Val))
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *printer) printLiteral(l *ast.LiteralType) []byte {
|
|
|
|
return []byte(l.Token.Text)
|
|
|
|
}
|
|
|
|
|
2015-10-25 13:08:09 +00:00
|
|
|
func (p *printer) printObjectType(o *ast.ObjectType) []byte {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
buf.WriteString("{")
|
|
|
|
buf.WriteByte(newline)
|
|
|
|
|
|
|
|
for _, item := range o.List.Items {
|
|
|
|
// buf.WriteByte(tab)
|
|
|
|
// buf.Write(p.printObjectItem(item))
|
|
|
|
|
|
|
|
a := p.printObjectItem(item)
|
|
|
|
a = indent(a)
|
|
|
|
buf.Write(a)
|
|
|
|
|
|
|
|
buf.WriteByte(newline)
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString("}")
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
|
2015-10-24 22:23:50 +00:00
|
|
|
func (p *printer) printList(l *ast.ListType) []byte {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
buf.WriteString("[")
|
|
|
|
|
|
|
|
for i, item := range l.List {
|
|
|
|
if item.Pos().Line != l.Lbrack.Line {
|
|
|
|
// not same line
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(newline)
|
2015-10-24 22:23:50 +00:00
|
|
|
}
|
|
|
|
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(tab)
|
2015-10-24 22:23:50 +00:00
|
|
|
buf.Write(p.printNode(item))
|
|
|
|
|
|
|
|
if i != len(l.List)-1 {
|
|
|
|
buf.WriteString(",")
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(blank)
|
2015-10-24 22:23:50 +00:00
|
|
|
} else if item.Pos().Line != l.Lbrack.Line {
|
|
|
|
buf.WriteString(",")
|
2015-10-25 13:08:09 +00:00
|
|
|
buf.WriteByte(newline)
|
2015-10-24 22:23:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString("]")
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
2015-10-25 13:08:09 +00:00
|
|
|
|
|
|
|
func writeBlank(buf io.ByteWriter, indent int) {
|
|
|
|
for i := 0; i < indent; i++ {
|
|
|
|
buf.WriteByte(blank)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func indent(buf []byte) []byte {
|
|
|
|
splitted := bytes.Split(buf, []byte{newline})
|
|
|
|
newBuf := make([]byte, len(splitted))
|
|
|
|
for i, s := range splitted {
|
|
|
|
s = append(s, 0)
|
|
|
|
copy(s[1:], s[0:])
|
|
|
|
s[0] = tab
|
|
|
|
newBuf = append(newBuf, s...)
|
|
|
|
|
|
|
|
if i != len(splitted)-1 {
|
|
|
|
newBuf = append(newBuf, newline)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newBuf
|
|
|
|
}
|