-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtemplate.go
71 lines (57 loc) · 1.7 KB
/
template.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
package fauna
import (
"fmt"
"regexp"
)
type templateCategory string
const (
templateVariable templateCategory = "variable"
templateLiteral templateCategory = "literal"
)
var (
templateRegex = regexp.MustCompile(`\$(?:(?P<escaped>\$)|{(?P<braced>[_a-zA-Z0-9]*)}|(?P<invalid>))`)
escapedIndex = templateRegex.SubexpIndex("escaped")
bracedIndex = templateRegex.SubexpIndex("braced")
invalidIndex = templateRegex.SubexpIndex("invalid")
)
type templatePart struct {
Text string
Category templateCategory
}
// Parse parses Text and returns a slice of template parts.
func parseTemplate(text string) ([]templatePart, error) {
end := len(text)
currentPosition := 0
matches := templateRegex.FindAllStringSubmatch(text, -1)
matchIndexes := templateRegex.FindAllStringSubmatchIndex(text, -1)
parts := make([]templatePart, 0)
for i, m := range matches {
matchIndex := matchIndexes[i]
invalidStartPos := matchIndex[invalidIndex*2]
if invalidStartPos >= 0 {
// TODO: Improve with line/column num
return nil, fmt.Errorf("invalid placeholder in template: position %d", invalidStartPos)
}
matchStartPos := matchIndex[0]
matchEndPos := matchIndex[1]
escaped := m[escapedIndex]
variable := m[bracedIndex]
if currentPosition < matchStartPos {
parts = append(parts, templatePart{
Text: text[currentPosition:matchStartPos] + escaped,
Category: templateLiteral,
})
}
if len(variable) > 0 {
parts = append(parts, templatePart{
Text: variable,
Category: templateVariable,
})
}
currentPosition = matchEndPos
}
if currentPosition < end {
parts = append(parts, templatePart{Text: text[currentPosition:], Category: templateLiteral})
}
return parts, nil
}