77 lines
1.5 KiB
Go
77 lines
1.5 KiB
Go
package scanner
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/go-envparse"
|
|
)
|
|
|
|
var envvarRegex = regexp.MustCompile(`\$\{?([A-Z][A-Z0-9_]*)\}?`)
|
|
|
|
type Scanner struct {
|
|
envfile, r io.Reader
|
|
w io.Writer
|
|
}
|
|
|
|
// New returns a new Scanner with the provided arguments.
|
|
func New(w io.Writer, r io.Reader, envfile io.Reader) *Scanner {
|
|
return &Scanner{
|
|
w: w,
|
|
r: r,
|
|
envfile: envfile,
|
|
}
|
|
}
|
|
|
|
const nl = "\n"
|
|
|
|
func (s *Scanner) Scan() error {
|
|
vars, err := envparse.Parse(s.envfile)
|
|
if err != nil {
|
|
return fmt.Errorf("error parsing envfile: %v", err)
|
|
}
|
|
|
|
scanner := bufio.NewScanner(s.r)
|
|
for scanner.Scan() {
|
|
text := scanner.Text()
|
|
matchIndices := envvarRegex.FindAllStringSubmatchIndex(text, -1)
|
|
|
|
var sb strings.Builder
|
|
var c int
|
|
for _, idx := range matchIndices {
|
|
m1, m2, n1, n2 := idx[0], idx[1], idx[2], idx[3]
|
|
writeString(&sb, text[c:m1])
|
|
c = m2
|
|
|
|
name := text[n1:n2]
|
|
if val, ok := vars[name]; ok {
|
|
writeString(&sb, val)
|
|
} else {
|
|
writeString(&sb, text[m1:m2])
|
|
}
|
|
}
|
|
|
|
writeString(&sb, text[c:])
|
|
writeString(&sb, nl)
|
|
|
|
if _, err := s.w.Write([]byte(sb.String())); err != nil {
|
|
return fmt.Errorf("error writing to output: %v", err)
|
|
}
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return fmt.Errorf("error reading input: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// writeString writes a string to a StringBuilder, discarding the result and
|
|
// (non-existent) error.
|
|
func writeString(sb *strings.Builder, s string) {
|
|
_, _ = sb.WriteString(s)
|
|
}
|