main.go - randomcrap - random crap programs of varying quality
 (HTM) git clone git://git.codemadness.org/randomcrap
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       main.go (2337B)
       ---
            1 package main
            2 
            3 import (
            4         "encoding/csv"
            5         "flag"
            6         "fmt"
            7         "io"
            8         "io/ioutil"
            9         "log"
           10         "os"
           11         "strings"
           12         "text/template"
           13         "unicode"
           14 )
           15 
           16 // only allow a-zA-Z0-9 and '_', rest is removed.
           17 func normalizeheader(s string) string {
           18         return strings.Map(func(r rune) rune {
           19                 switch {
           20                 case unicode.IsLetter(r):
           21                         return unicode.ToLower(r)
           22                 case unicode.IsDigit(r):
           23                         return r
           24                 case r == '_':
           25                         return r
           26                 }
           27                 return -1
           28         }, s)
           29 }
           30 
           31 func main() {
           32         config_templatefile := ""
           33         config_separator := ";"
           34 
           35         flag.StringVar(&config_templatefile, "template", config_templatefile, "Text template file")
           36         flag.StringVar(&config_separator, "separator", config_separator, "Field separator")
           37         flag.Parse()
           38 
           39         if config_templatefile == "" {
           40                 fmt.Fprint(os.Stderr, "Usage: ", os.Args[0], "\n")
           41                 flag.PrintDefaults()
           42                 os.Exit(1)
           43         }
           44         templatedata, err := ioutil.ReadFile(config_templatefile)
           45         if err != nil {
           46                 log.Fatalf("reading template file \"%s\" failed: %s", config_templatefile, err)
           47         }
           48 
           49         t := template.New(config_templatefile)
           50         t = AddTemplateFuncs(t)
           51         // parse template.
           52         t, err = t.Parse(string(templatedata))
           53         if err != nil {
           54                 log.Fatalf("template parsing failed: %s", err)
           55         }
           56 
           57         r := csv.NewReader(os.Stdin)
           58         // if set: use first rune as separator.
           59         if len(config_separator) > 0 {
           60                 r.Comma = rune(config_separator[0])
           61         }
           62 
           63         var errset error
           64         c := make(chan map[string]string, 0)
           65         go func() {
           66                 var headers []string
           67                 headerslen := 0
           68                 recordlen := 0
           69                 linecount := 0
           70                 keepreading := true
           71                 for keepreading {
           72                         record, err := r.Read()
           73                         if err != nil {
           74                                 keepreading = false
           75                                 if err != io.EOF {
           76                                         errset = err
           77                                 }
           78                                 break
           79                         }
           80                         recordlen = len(record)
           81                         // first line are the headers.
           82                         if linecount == 0 {
           83                                 headers = record
           84                                 for i := 0; i < recordlen; i++ {
           85                                         headers[i] = normalizeheader(record[i])
           86                                 }
           87                                 headerslen = recordlen
           88                         } else {
           89                                 // ... rest are items.
           90                                 item := make(map[string]string)
           91                                 i := 0
           92                                 for i = 0; i < recordlen && i < headerslen; i++ {
           93                                         item[headers[i]] = record[i]
           94                                 }
           95                                 // set remaining fields to empty string.
           96                                 for ; i < headerslen; i++ {
           97                                         item[headers[i]] = ""
           98                                 }
           99                                 c <- item
          100                         }
          101                         linecount++
          102                 }
          103                 close(c)
          104         }()
          105         if err = t.Execute(os.Stdout, map[string]interface{}{"rows": c}); err != nil {
          106                 log.Fatalln(err)
          107         }
          108         if errset != nil {
          109                 log.Fatalln(errset)
          110         }
          111 }