/
expand.go
88 lines (84 loc) · 1.81 KB
/
expand.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
package glob
import (
"fmt"
"github.com/gobwas/glob/syntax/ast"
"github.com/gobwas/glob/syntax/lexer"
"github.com/livebud/bud/internal/orderedset"
)
func Expand(str string) ([]string, error) {
lex := lexer.NewLexer(str)
node, err := ast.Parse(lex)
if err != nil {
return nil, err
}
patterns, err := expand(node)
if err != nil {
return nil, err
}
return orderedset.Strings(patterns...), nil
}
func expand(node *ast.Node) (patterns []string, err error) {
prefix := ""
write := func(value string) {
prefix += value
for i := range patterns {
patterns[i] += value
}
}
for _, child := range node.Children {
switch child.Kind {
case ast.KindText:
text, ok := child.Value.(ast.Text)
if !ok {
return nil, fmt.Errorf("expected text value, got %T", child.Value)
}
write(text.Text)
case ast.KindList:
list, ok := child.Value.(ast.List)
if !ok {
return nil, fmt.Errorf("expected list value, got %T", child.Value)
}
write("[")
if list.Not {
write("^")
}
write(list.Chars)
write("]")
case ast.KindRange:
rng, ok := child.Value.(ast.Range)
if !ok {
return nil, fmt.Errorf("expected rng value, got %T", child.Value)
}
write("[")
if rng.Not {
write("^")
}
write(string(rng.Lo))
write("-")
write(string(rng.Hi))
write("]")
case ast.KindAny:
write("*")
case ast.KindSuper:
write("**")
case ast.KindSingle:
write("?")
case ast.KindAnyOf:
for _, child := range child.Children {
results, err := expand(child)
if err != nil {
return nil, err
}
for _, result := range results {
patterns = append(patterns, prefix+result)
}
}
default:
return nil, fmt.Errorf("unknown node kind: %v", child.Kind)
}
}
if len(patterns) == 0 {
patterns = append(patterns, prefix)
}
return patterns, nil
}