130 lines
2.7 KiB
Go
130 lines
2.7 KiB
Go
package nginx
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
var (
|
|
defaultPrefix = ""
|
|
defaultIndent = "\t"
|
|
)
|
|
|
|
// Encoder implements parser.Encoder
|
|
type Encoder struct {
|
|
writer io.Writer
|
|
prefix []byte
|
|
indent []byte
|
|
}
|
|
|
|
// SetIndent with the <prefix> that begins each line (default is emptys string)
|
|
// and the <indent> string repeated for each indentation level (default is tab '\t')
|
|
func (e *Encoder) SetIndent(prefix, indent string) {
|
|
e.prefix = make([]byte, 0)
|
|
e.prefix = append(e.prefix, []byte(prefix)...)
|
|
|
|
e.indent = make([]byte, 0)
|
|
e.indent = append(e.indent, []byte(indent)...)
|
|
}
|
|
|
|
// Encode is the main function of the parser.Encoder interface
|
|
func (e *Encoder) Encode(v interface{}) error {
|
|
|
|
// default indentation
|
|
if e.prefix == nil || e.indent == nil {
|
|
e.SetIndent(defaultPrefix, defaultIndent)
|
|
}
|
|
|
|
// check 'v'
|
|
vcast, ok := v.(*Line)
|
|
if !ok {
|
|
return ErrInvalidReceiver
|
|
}
|
|
|
|
// empty config
|
|
if len(vcast.Lines) < 1 {
|
|
return nil
|
|
}
|
|
|
|
// actual indentation level
|
|
indent := 0
|
|
|
|
// actual lines to write
|
|
stack := make([]*Line, 0)
|
|
|
|
// push nginx.Lines in reverse order
|
|
for l := len(vcast.Lines) - 1; l >= 0; l-- {
|
|
stack = append(stack, vcast.Lines[l])
|
|
}
|
|
|
|
for len(stack) > 0 {
|
|
|
|
// pop stack
|
|
line := stack[len(stack)-1]
|
|
stack = stack[:len(stack)-1]
|
|
|
|
// line representation
|
|
repr := make([]byte, 0)
|
|
|
|
if line == nil { // section end
|
|
indent--
|
|
}
|
|
|
|
// 1. add indentation
|
|
repr = append(repr, []byte(e.prefix)...)
|
|
for i := 0; i < indent; i++ {
|
|
repr = append(repr, []byte(e.indent)...)
|
|
}
|
|
|
|
// 2. section end
|
|
if line == nil {
|
|
repr = append(repr, []byte("}\n\n")...)
|
|
// Note: new line after section for readability
|
|
|
|
// 3. comments
|
|
} else if line.Type == COMMENT {
|
|
|
|
repr = append(repr, []byte(fmt.Sprintf("#%s\n", line.Components[0]))...)
|
|
} else if line.Type == COLONCOMMENT {
|
|
repr = append(repr, []byte(fmt.Sprintf(";%s\n", line.Components[0]))...)
|
|
|
|
// 4.assignments
|
|
} else if line.Type == ASSIGNMENT {
|
|
repr = append(repr, []byte(fmt.Sprintf("%s\t\t%s;\n", line.Components[0], line.Components[1]))...)
|
|
|
|
// 5. include
|
|
} else if line.Type == INCLUDE {
|
|
repr = append(repr, []byte(fmt.Sprintf("include %s;\n", line.Components[0]))...)
|
|
|
|
// 6. section
|
|
} else {
|
|
// push to stack
|
|
stack = append(stack, nil)
|
|
|
|
// push children lines in reverse order
|
|
if len(line.Lines) > 0 {
|
|
for l := len(line.Lines) - 1; l >= 0; l-- {
|
|
stack = append(stack, line.Lines[l])
|
|
}
|
|
}
|
|
|
|
if len(line.Components) > 1 {
|
|
repr = append(repr, []byte(fmt.Sprintf("%s %s {\n", line.Components[0], line.Components[1]))...)
|
|
} else {
|
|
repr = append(repr, []byte(fmt.Sprintf("%s {\n", line.Components[0]))...)
|
|
}
|
|
|
|
indent++
|
|
|
|
}
|
|
|
|
_, err := e.writer.Write(repr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|