-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcsv.go
70 lines (63 loc) · 1.6 KB
/
csv.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
package main
import (
"fmt"
"io"
"regexp"
"strings"
"sync"
"text/template"
)
const (
PATH = iota + 1
NAME
FUNC
PARAM
)
var fieldregexp = regexp.MustCompile(`^\s*([[:alnum:]\.]+)=([[:alnum:]\s\.]+)(?:\s*\|\s*([[:alnum:]]+)(?:\(([[:alnum:]\s]+)\))?)?\s*`)
func CSVCompiler(format string) (Formatter, error) {
fieldformats := strings.Split(format, ",")
fieldtemplates, fieldnames := []string{}, []string{}
for _, fieldformatstring := range fieldformats {
fieldformat := fieldregexp.FindStringSubmatch(fieldformatstring)
if fieldformat == nil || len(fieldformat) == 0 {
return nil, fmt.Errorf("Invalid CSV format string")
}
fieldtemplate := "{{." + fieldformat[PATH]
if len(fieldformat[FUNC]) > 0 {
fieldtemplate += "|" + fieldformat[FUNC]
if len(fieldformat[PARAM]) > 0 {
fieldtemplate += " " + fieldformat[PARAM]
}
}
fieldtemplates = append(fieldtemplates, fieldtemplate+"}}")
fieldnames = append(fieldnames, fieldformat[NAME])
}
fieldtemplate := strings.Join(fieldtemplates, ",")
t, err := template.New("jsonformat").
Funcs(defaultFuncs).
Parse(fieldtemplate)
if err != nil {
return nil, err
}
return &CSVFormatter{
fieldnames: fieldnames,
template: t,
}, nil
}
type CSVFormatter struct {
fieldnames []string
template *template.Template
sync.Once
}
func (c *CSVFormatter) Execute(w io.Writer, data interface{}) error {
c.Once.Do(func() {
io.WriteString(w, strings.Join(c.fieldnames, ",")+"\n")
})
return c.template.Execute(w, data)
}
func init() {
Formats["csv"] = Format{
Compiler: CSVCompiler,
Description: `Shortcut for CSV-style output`,
}
}