62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
|
|
package settings
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
KeyValueDelimiterChars = []byte{':', '='}
|
||
|
|
|
||
|
|
ErrNoValidDelimiter = fmt.Errorf("no valid delimiter found (use %s)", KeyValueDelimiterCharsToString())
|
||
|
|
)
|
||
|
|
|
||
|
|
func KeyValueDelimiterCharsToString() string {
|
||
|
|
var builder strings.Builder
|
||
|
|
for i, char := range KeyValueDelimiterChars {
|
||
|
|
builder.WriteString(fmt.Sprintf("'%c'", char))
|
||
|
|
if i < len(KeyValueDelimiterChars)-1 {
|
||
|
|
builder.WriteString(" or ")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return builder.String()
|
||
|
|
}
|
||
|
|
|
||
|
|
func LineIsComment(line string) bool {
|
||
|
|
return strings.HasPrefix(line, "//") || strings.HasPrefix(line, "#")
|
||
|
|
}
|
||
|
|
|
||
|
|
type Scanner struct {
|
||
|
|
lineNumber int
|
||
|
|
scanner *bufio.Scanner
|
||
|
|
}
|
||
|
|
|
||
|
|
// returns errors without any key/value.
|
||
|
|
// does not clone the strings it extracted.
|
||
|
|
func (s *Scanner) ReadNextLine() (key, value string, err error) {
|
||
|
|
for s.scanner.Scan() {
|
||
|
|
s.lineNumber++
|
||
|
|
line := strings.TrimSpace(s.scanner.Text())
|
||
|
|
if len(line) == 0 || LineIsComment(line) {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
splitIndex := strings.IndexAny(line, string(KeyValueDelimiterChars))
|
||
|
|
if splitIndex == -1 {
|
||
|
|
return "", "", fmt.Errorf("line %d: %w", s.lineNumber, ErrNoValidDelimiter)
|
||
|
|
}
|
||
|
|
key = strings.TrimSpace(line[:splitIndex])
|
||
|
|
value = strings.TrimSpace(line[splitIndex+1:])
|
||
|
|
return
|
||
|
|
}
|
||
|
|
return "", "", io.EOF
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewScanner(r io.Reader) *Scanner {
|
||
|
|
return &Scanner{
|
||
|
|
lineNumber: 0,
|
||
|
|
scanner: bufio.NewScanner(r),
|
||
|
|
}
|
||
|
|
}
|