annotate icf/icf.go @ 14:a51dfcb0faeb default tip

forgot to remove bestPatPath variable that's not used anymore
author Atarwn Gard <a@qwa.su>
date Mon, 23 Mar 2026 13:48:32 +0500
parents 9460f83a5664
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
1 // Package icf implements the Inherited Configuration Format parser.
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
2 //
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
3 // ICF is a rule-based configuration format with variables, abstract blocks
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
4 // (mixins), pattern matching with named capture groups, and brace expansion.
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
5 package icf
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
6
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
7 import (
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
8 "bufio"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
9 "fmt"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
10 "io"
13
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
11 "path"
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
12 "strings"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
13 )
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
14
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
15 type Directive struct {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
16 Key string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
17 Args []string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
18 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
19
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
20 type Config struct {
6
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
21 vars map[string]string
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
22 abstract map[string][]Directive
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
23 abstractMixin map[string]string // mixin name for each abstract block
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
24 Blocks []ParsedBlock
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
25 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
26
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
27 type ParsedBlock struct {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
28 ID string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
29 Mixin string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
30 Directives []Directive
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
31 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
32
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
33 type rawBlock struct {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
34 id string
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
35 mixin string
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
36 directives []rawDirective
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
37 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
38
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
39 type rawDirective struct {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
40 key string
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
41 args []string // after brace expansion, before var substitution
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
42 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
43
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
44 func Parse(r io.Reader) (*Config, error) {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
45 lines, err := readLines(r)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
46 if err != nil {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
47 return nil, err
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
48 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
49
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
50 // --- Pass 1: collect variables ---
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
51 vars := make(map[string]string)
4
dacc92aae6d5 expand vars in vars
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
52 subst := makeSubst(vars)
dacc92aae6d5 expand vars in vars
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
53
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
54 for _, line := range lines {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
55 if i := strings.Index(line, "="); i > 0 && !strings.HasPrefix(line, "|>") {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
56 key := line[:i]
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
57 if isVarName(key) {
4
dacc92aae6d5 expand vars in vars
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
58 vars[key] = subst(strings.TrimSpace(line[i+1:]), nil)
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
59 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
60 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
61 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
62
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
63 // --- Pass 2: parse blocks (raw, no capture substitution yet) ---
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
64 var raws []rawBlock
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
65 var cur *rawBlock
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
66
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
67 flush := func() {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
68 if cur != nil {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
69 raws = append(raws, *cur)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
70 cur = nil
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
71 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
72 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
73
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
74 for _, line := range lines {
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
75 if i := strings.Index(line, "="); i > 0 && !strings.HasPrefix(line, "|>") {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
76 if isVarName(line[:i]) {
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
77 continue
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
78 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
79 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
80
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
81 if strings.HasPrefix(line, "|>") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
82 if cur == nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
83 return nil, fmt.Errorf("icf: directive outside block: %q", line)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
84 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
85 parts := strings.Fields(strings.TrimSpace(line[2:]))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
86 if len(parts) == 0 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
87 continue
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
88 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
89 cur.directives = append(cur.directives, rawDirective{
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
90 key: parts[0],
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
91 args: braceExpand(parts[1:]),
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
92 })
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
93 continue
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
94 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
95
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
96 flush()
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
97 parts := strings.Fields(line)
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
98 rb := rawBlock{id: subst(parts[0], nil)}
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
99 if len(parts) >= 2 && strings.HasPrefix(parts[1], "@") {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
100 rb.mixin = subst(parts[1][1:], nil)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
101 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
102 cur = &rb
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
103 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
104 flush()
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
105
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
106 // --- Pass 3: separate abstract from concrete, apply var substitution ---
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
107 c := &Config{
6
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
108 vars: vars,
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
109 abstract: make(map[string][]Directive),
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
110 abstractMixin: make(map[string]string),
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
111 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
112
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
113 for _, rb := range raws {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
114 dirs := make([]Directive, len(rb.directives))
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
115 for i, rd := range rb.directives {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
116 args := make([]string, len(rd.args))
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
117 for j, a := range rd.args {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
118 args[j] = subst(a, nil)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
119 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
120 dirs[i] = Directive{Key: rd.key, Args: args}
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
121 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
122
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
123 if strings.HasPrefix(rb.id, "@") {
6
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
124 name := rb.id[1:]
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
125 c.abstract[name] = dirs
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
126 if rb.mixin != "" {
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
127 c.abstractMixin[name] = rb.mixin
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
128 }
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
129 } else {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
130 c.Blocks = append(c.Blocks, ParsedBlock{
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
131 ID: rb.id,
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
132 Mixin: rb.mixin,
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
133 Directives: dirs,
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
134 })
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
135 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
136 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
137
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
138 return c, nil
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
139 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
140
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
141 // Abstract returns the directives of a named abstract block.
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
142 // Returns nil if not found.
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
143 func (c *Config) Abstract(name string) []Directive {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
144 return c.abstract[name]
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
145 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
146
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
147 // Match finds the most specific block matching input (e.g. "host/path") and
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
148 // returns resolved directives plus named captures.
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
149 // Domain is matched exactly; path uses prefix match.
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
150 func (c *Config) Match(input string) ([]Directive, map[string]string, string) {
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
151 inHost, inPath, _ := strings.Cut(input, "/")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
152
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
153 type hit struct {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
154 block ParsedBlock
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
155 captures map[string]string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
156 score int
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
157 rem string
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
158 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
159 var best *hit
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
160
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
161 for _, b := range c.Blocks {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
162 patHost, patPath, hasPath := strings.Cut(b.ID, "/")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
163 caps := make(map[string]string)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
164
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
165 domScore, ok := matchExact(patHost, inHost, caps)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
166 if !ok {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
167 continue
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
168 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
169
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
170 pathScore := 0
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
171 rem := inPath
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
172 if hasPath {
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
173 var pathRem string
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
174 pathScore, pathRem, ok = matchPrefix(patPath, inPath, caps)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
175 if !ok {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
176 continue
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
177 }
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
178 rem = pathRem
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
179 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
180
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
181 score := domScore*1000 + pathScore
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
182 if best == nil || score > best.score {
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
183 best = &hit{block: b, captures: caps, score: score, rem: rem}
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
184 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
185 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
186
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
187 if best == nil {
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
188 return nil, nil, ""
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
189 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
190
13
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
191 // subPath is the filesystem path relative to rootDir.
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
192 // rem is the unmatched suffix after the path pattern
14
a51dfcb0faeb forgot to remove bestPatPath variable that's not used anymore
Atarwn Gard <a@qwa.su>
parents: 13
diff changeset
193 _, _, bestHasPath := strings.Cut(best.block.ID, "/")
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
194 subPath := best.rem
13
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
195 if bestHasPath && subPath == "" {
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
196 base := path.Base(inPath)
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
197 if strings.Contains(base, ".") {
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
198 subPath = "/" + inPath
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
199 } else {
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
200 subPath = "/"
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
201 }
9460f83a5664 subPath fix
Atarwn Gard <a@qwa.su>
parents: 12
diff changeset
202 } else if !strings.HasPrefix(subPath, "/") {
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
203 subPath = "/" + subPath
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
204 }
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
205 return c.ResolveBlock(best.block, best.captures), best.captures, subPath
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
206 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
207
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
208 // ResolveBlock merges mixin directives (lower priority) with block directives,
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
209 // then substitutes capture variables.
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
210 func (c *Config) ResolveBlock(b ParsedBlock, caps map[string]string) []Directive {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
211 var merged []Directive
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
212 if b.Mixin != "" {
6
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
213 merged = append(merged, c.resolveAbstract(b.Mixin, make(map[string]bool))...)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
214 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
215 merged = append(merged, b.Directives...)
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
216
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
217 if len(caps) == 0 {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
218 return merged
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
219 }
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
220
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
221 // Substitute capture variables into a copy
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
222 subst := makeSubst(c.vars)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
223 out := make([]Directive, len(merged))
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
224 for i, d := range merged {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
225 out[i].Key = d.Key
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
226 out[i].Args = make([]string, len(d.Args))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
227 for j, a := range d.Args {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
228 out[i].Args[j] = subst(a, caps)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
229 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
230 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
231 return out
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
232 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
233
6
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
234 // resolveAbstract recursively expands an abstract block and its mixin chain.
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
235 // visited guards against circular references.
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
236 func (c *Config) resolveAbstract(name string, visited map[string]bool) []Directive {
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
237 if visited[name] {
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
238 return nil
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
239 }
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
240 visited[name] = true
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
241
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
242 var out []Directive
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
243 if parent, ok := c.abstractMixin[name]; ok {
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
244 out = append(out, c.resolveAbstract(parent, visited)...)
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
245 }
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
246 out = append(out, c.abstract[name]...)
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
247 return out
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
248 }
54ab94198677 abstract mixins + building sctipt + documentation
Atarwn Gard <a@qwa.su>
parents: 4
diff changeset
249
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
250 // makeSubst returns a function that substitutes $VAR in s,
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
251 // checking caps first, then vars.
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
252 func makeSubst(vars map[string]string) func(s string, caps map[string]string) string {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
253 return func(s string, caps map[string]string) string {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
254 if !strings.Contains(s, "$") {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
255 return s
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
256 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
257 var b strings.Builder
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
258 i := 0
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
259 for i < len(s) {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
260 if s[i] != '$' {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
261 b.WriteByte(s[i])
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
262 i++
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
263 continue
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
264 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
265 j := i + 1
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
266 for j < len(s) && isVarChar(s[j]) {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
267 j++
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
268 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
269 name := s[i+1 : j]
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
270 if caps != nil {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
271 if v, ok := caps[name]; ok {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
272 b.WriteString(v)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
273 i = j
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
274 continue
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
275 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
276 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
277 if v, ok := vars[name]; ok {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
278 b.WriteString(v)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
279 } else {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
280 b.WriteString(s[i:j])
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
281 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
282 i = j
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
283 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
284 return b.String()
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
285 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
286 }
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
287
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
288 func readLines(r io.Reader) ([]string, error) {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
289 var out []string
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
290 scanner := bufio.NewScanner(r)
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
291 for scanner.Scan() {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
292 line := stripComment(strings.TrimSpace(scanner.Text()))
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
293 if line != "" {
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
294 out = append(out, line)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
295 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
296 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
297 return out, scanner.Err()
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
298 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
299
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
300 func matchExact(pat, s string, caps map[string]string) (int, bool) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
301 score, rem, ok := matchCaptures(pat, s, caps)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
302 if !ok || rem != "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
303 return 0, false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
304 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
305 return score, true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
306 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
307
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
308 func matchPrefix(pat, s string, caps map[string]string) (int, string, bool) {
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
309 score, rem, ok := matchCaptures(pat, s, caps)
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
310 return score, rem, ok
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
311 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
312
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
313 func matchCaptures(pat, inp string, caps map[string]string) (int, string, bool) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
314 for {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
315 if pat == "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
316 return 0, inp, true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
317 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
318
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
319 if strings.HasPrefix(pat, "<") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
320 end := strings.Index(pat, ">")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
321 if end == -1 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
322 return 0, "", false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
323 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
324 capName := pat[1:end]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
325 rest := pat[end+1:]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
326
8
2ffb8028ccbb add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents: 6
diff changeset
327 for split := len(inp); split >= 1; split-- {
12
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
328 // Captures never span path separators: <n> matches one segment only.
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
329 if strings.Contains(inp[:split], "/") {
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
330 continue
84384cccda0e bubfix subpaths and remove hardcode
atarwn@g5
parents: 8
diff changeset
331 }
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
332 score, finalRem, ok := matchCaptures(rest, inp[split:], caps)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
333 if ok {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
334 if capName != "_" {
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
335 caps[capName] = inp[:split]
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
336 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
337 return score, finalRem, true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
338 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
339 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
340 return 0, "", false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
341 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
342
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
343 if inp == "" || pat[0] != inp[0] {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
344 return 0, "", false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
345 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
346 score, rem, ok := matchCaptures(pat[1:], inp[1:], caps)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
347 return score + 1, rem, ok
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
348 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
349 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
350
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
351 func braceExpand(args []string) []string {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
352 var out []string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
353 for _, a := range args {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
354 out = append(out, expandOne(a)...)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
355 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
356 return out
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
357 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
358
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
359 func expandOne(s string) []string {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
360 start := strings.Index(s, "{")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
361 end := strings.Index(s, "}")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
362 if start == -1 || end == -1 || end < start {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
363 return []string{s}
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
364 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
365 prefix := s[:start]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
366 suffix := s[end+1:]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
367 var out []string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
368 for _, v := range strings.Split(s[start+1:end], ",") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
369 out = append(out, prefix+strings.TrimSpace(v)+suffix)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
370 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
371 return out
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
372 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
373
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
374 func stripComment(line string) string {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
375 if strings.HasPrefix(line, ";") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
376 return ""
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
377 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
378 if i := strings.Index(line, " ;"); i != -1 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
379 return strings.TrimSpace(line[:i])
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
380 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
381 return line
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
382 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
383
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
384 func isVarName(s string) bool {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
385 if s == "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
386 return false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
387 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
388 for i := 0; i < len(s); i++ {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
389 if !isVarChar(s[i]) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
390 return false
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
391 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
392 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
393 return true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
394 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
395
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
396 func isVarChar(c byte) bool {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
397 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
398 (c >= '0' && c <= '9') || c == '_'
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
399 }