This repository has been archived by the owner on Aug 22, 2018. It is now read-only.
/
flagfile.go
116 lines (107 loc) · 2.02 KB
/
flagfile.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package tally
import (
"bufio"
"bytes"
"errors"
"flag"
"fmt"
"io"
"os"
"strings"
)
type LineReader interface {
ReadLine() ([]byte, bool, error)
}
type FlagFile struct {
*flag.FlagSet
}
type SyntaxError struct {
msg string
path string
line int
}
func (e *SyntaxError) Error() string {
var prefix string
if e.path != "" {
prefix = e.path + ":"
}
return fmt.Sprintf("%s%d: %s", prefix, e.line, e.msg)
}
func NewFlagFile(path string) (ff *FlagFile, err error) {
file, err := os.Open(path)
if err != nil {
return
}
ff = &FlagFile{flag.NewFlagSet(os.Args[0], flag.ExitOnError)}
err = ff.ReadFlags(file)
synerr, ok := err.(*SyntaxError)
if ok {
synerr.path = path
}
return
}
func readLine(reader LineReader) (string, error) {
var buffer bytes.Buffer
for {
line_bytes, isPrefix, err := reader.ReadLine()
if err != nil {
return "", err
}
buffer.Write(line_bytes)
if !isPrefix {
break
}
}
return buffer.String(), nil
}
func readArg(reader *bufio.Reader) (name string, val string, n int, err error) {
for {
var line string
n++
line, err = readLine(reader)
if err != nil {
return
}
if idx := strings.IndexRune(line, '#'); idx >= 0 {
line = line[:idx]
}
line = strings.TrimSpace(line)
if len(line) != 0 {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
err = errors.New(fmt.Sprintf("assignment required: %#v", line))
return
}
name = strings.TrimSpace(parts[0])
val = strings.TrimSpace(parts[1])
return
}
}
return
}
func (ff *FlagFile) ReadFlags(reader io.Reader) error {
lineNo := 0
bufReader := bufio.NewReader(reader)
for {
name, val, n, err := readArg(bufReader)
lineNo += n
if err != nil {
if err == io.EOF {
break
}
return &SyntaxError{err.Error(), "", lineNo}
}
flag := flag.Lookup(name)
if flag == nil {
return &SyntaxError{
fmt.Sprintf("undefined flag: %s", name),
"",
lineNo,
}
}
if err = flag.Value.Set(val); err != nil {
return &SyntaxError{err.Error(), "", lineNo}
}
}
return nil
}