1package config
2
3import (
4	"fmt"
5	"io"
6	"strings"
7)
8
9// An Encoder writes config files to an output stream.
10type Encoder struct {
11	w io.Writer
12}
13
14// NewEncoder returns a new encoder that writes to w.
15func NewEncoder(w io.Writer) *Encoder {
16	return &Encoder{w}
17}
18
19// Encode writes the config in git config format to the stream of the encoder.
20func (e *Encoder) Encode(cfg *Config) error {
21	for _, s := range cfg.Sections {
22		if err := e.encodeSection(s); err != nil {
23			return err
24		}
25	}
26
27	return nil
28}
29
30func (e *Encoder) encodeSection(s *Section) error {
31	if len(s.Options) > 0 {
32		if err := e.printf("[%s]\n", s.Name); err != nil {
33			return err
34		}
35
36		if err := e.encodeOptions(s.Options); err != nil {
37			return err
38		}
39	}
40
41	for _, ss := range s.Subsections {
42		if err := e.encodeSubsection(s.Name, ss); err != nil {
43			return err
44		}
45	}
46
47	return nil
48}
49
50func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error {
51	//TODO: escape
52	if err := e.printf("[%s \"%s\"]\n", sectionName, s.Name); err != nil {
53		return err
54	}
55
56	if err := e.encodeOptions(s.Options); err != nil {
57		return err
58	}
59
60	return nil
61}
62
63func (e *Encoder) encodeOptions(opts Options) error {
64	for _, o := range opts {
65		pattern := "\t%s = %s\n"
66		if strings.Index(o.Value, "\\") != -1 {
67			pattern = "\t%s = %q\n"
68		}
69
70		if err := e.printf(pattern, o.Key, o.Value); err != nil {
71			return err
72		}
73	}
74
75	return nil
76}
77
78func (e *Encoder) printf(msg string, args ...interface{}) error {
79	_, err := fmt.Fprintf(e.w, msg, args...)
80	return err
81}
82