Skip to content

Commit f0711b9

Browse files
committed
highlighter: Add capability to remove childrens of already captured groups
1 parent 1c9dbbb commit f0711b9

1 file changed

Lines changed: 92 additions & 37 deletions

File tree

pkg/highlight/highlighter.go

Lines changed: 92 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ type LineStates interface {
2424

2525
// highlightStorage is used to store the found ranges
2626
type highlightStorage struct {
27-
start int
28-
end int
29-
group Group
30-
region *region
27+
start int
28+
end int
29+
group Group
30+
region *region
31+
children []*highlightStorage
3132
}
3233

3334
// A Highlighter contains the information needed to highlight a string
@@ -89,60 +90,114 @@ func findAllIndex(regex *regexp.Regexp, skip *regexp.Regexp, str []byte) [][]int
8990
}
9091

9192
func (h *Highlighter) removeRange(start int, end int, removeStart int) {
93+
var children []highlightStorage
9294
removeEnd := removeStart
9395
for i := removeStart; i < len(h.storage); i++ {
94-
next := h.storage[i]
95-
if start < next.start && next.start < end {
96-
// log.Println("removed: start:", next.start, "end:", next.end, "group:", next.group)
96+
e := h.storage[i]
97+
if start < e.start && e.start < end {
98+
// log.Println("remove: start:", e.start, "end:", e.end, "group:", e.group)
9799
removeEnd++
100+
for childIdx, _ := range h.storage[i].children {
101+
// log.Println("attached child: start:", h.storage[i].children[childIdx].start, "end:", h.storage[i].children[childIdx].end, "group:", h.storage[i].children[childIdx].group)
102+
children = append(children, *(h.storage[i].children[childIdx]))
103+
}
98104
}
99105
}
100106
if removeStart < removeEnd {
101107
h.storage = append(h.storage[:removeStart], h.storage[removeEnd:]...)
102108
}
109+
110+
// remove possible children too
111+
childLoop:
112+
for childIdx, _ := range children {
113+
for storageIdx, _ := range h.storage {
114+
if children[childIdx].start == h.storage[storageIdx].start && children[childIdx].end == h.storage[storageIdx].end && children[childIdx].group == h.storage[storageIdx].group && children[childIdx].region == h.storage[storageIdx].region {
115+
// log.Println("remove child: start:", h.storage[storageIdx].start, "end:", h.storage[storageIdx].end, "group:", h.storage[storageIdx].group)
116+
h.storage = append(h.storage[:storageIdx], h.storage[storageIdx+1:]...)
117+
continue childLoop
118+
}
119+
}
120+
}
103121
}
104122

105-
func (h *Highlighter) storeRange(start int, end int, group Group, region *region) {
123+
func (h *Highlighter) storeRange(start int, end int, group Group, r *region, isPattern bool) {
106124
// log.Println("storeRange: start:", start, "end:", end, "group:", group)
125+
var parent *region
126+
if isPattern {
127+
parent = r
128+
} else if r != nil {
129+
parent = r.parent
130+
}
131+
132+
updated := false
107133
for k, e := range h.storage {
108-
if e.region != nil && region != nil {
109-
if e.region.parent == region.parent {
110-
if region == e.region {
111-
if group == e.group && start == e.end {
112-
// same region, update ...
113-
h.storage[k].end = end
114-
// log.Println("exchanged to: start:", h.storage[k].start, "end:", h.storage[k].end, "group:", h.storage[k].group)
115-
return
116-
}
117-
} else {
134+
if r == e.region && group == e.group && start == e.end {
135+
// same region, update ...
136+
h.storage[k].end = end
137+
// log.Println("exchanged to: start:", h.storage[k].start, "end:", h.storage[k].end, "group:", h.storage[k].group)
138+
updated = true
139+
start = h.storage[k].start
140+
}
141+
}
142+
143+
for k, e := range h.storage {
144+
if e.region != nil && r != nil {
145+
if e.region.parent == parent {
146+
if r != e.region {
118147
// sibling regions, search for overlaps ...
119148
if start < e.start && end > e.start {
120149
// overlap
121-
} else if (start < e.start && end >= e.end) || (start <= e.start && end > e.end) {
150+
} else if start == e.start && end == e.end {
151+
// same match
152+
continue
153+
} else if start <= e.start && end >= e.end {
122154
// larger match
123155
} else if start >= e.start && end <= e.end {
124-
// smaller or same match
156+
// smaller match
125157
return
126158
} else {
127159
continue
128160
}
129161

130-
// log.Println("exchanged from: start:", e.start, "end:", e.end, "group:", e.group)
131-
h.storage[k] = highlightStorage{start, end, group, region}
162+
if !updated {
163+
// log.Println("exchanged from: start:", e.start, "end:", e.end, "group:", e.group)
164+
h.storage[k] = highlightStorage{start, end, group, r, nil}
132165

133-
// check and remove follow-ups matching the same
134-
h.removeRange(start, end, k + 1)
166+
// check and remove follow-ups matching the same
167+
h.removeRange(start, end, k+1)
168+
} else {
169+
h.removeRange(start, end, k)
170+
}
135171
return
136172
}
137173
} else {
138-
if region.parent != e.region && start >= e.start && end <= e.end {
174+
if parent != e.region && start >= e.start && end <= e.end {
139175
return
140176
}
141177
}
142178
}
143179
}
144180

145-
h.storage = append(h.storage, highlightStorage{start, end, group, region})
181+
if !updated {
182+
h.storage = append(h.storage, highlightStorage{start, end, group, r, nil})
183+
}
184+
185+
// add possible child entry
186+
if parent != nil {
187+
storageLoop:
188+
for k, e := range h.storage {
189+
if e.region == parent && e.start < start && end < e.end {
190+
for _, child := range h.storage[k].children {
191+
if child == &(h.storage[len(h.storage)-1]) {
192+
continue storageLoop
193+
}
194+
}
195+
196+
// log.Println("add child: start:", h.storage[k].start, "end:", h.storage[k].end, "group:", h.storage[k].group)
197+
h.storage[k].children = append(h.storage[k].children, &(h.storage[len(h.storage)-1]))
198+
}
199+
}
200+
}
146201
}
147202

148203
func (h *Highlighter) highlightPatterns(start int, lineNum int, line []byte, curRegion *region) {
@@ -162,7 +217,7 @@ func (h *Highlighter) highlightPatterns(start int, lineNum int, line []byte, cur
162217
for _, p := range patterns {
163218
matches := findAllIndex(p.regex, nil, line)
164219
for _, m := range matches {
165-
h.storeRange(start+m[0], start+m[1], p.group, nil)
220+
h.storeRange(start+m[0], start+m[1], p.group, curRegion, true)
166221
}
167222
}
168223
}
@@ -227,9 +282,9 @@ regionLoop:
227282
h.lastEnd = start + endMatch[1]
228283
update = true
229284
}
230-
h.storeRange(start+startMatch[0], start+startMatch[1], r.limitGroup, r)
231-
h.storeRange(start+startMatch[1], start+endMatch[0], r.group, r)
232-
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r)
285+
h.storeRange(start+startMatch[0], start+startMatch[1], r.limitGroup, r, false)
286+
h.storeRange(start+startMatch[1], start+endMatch[0], r.group, r, false)
287+
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r, false)
233288
h.highlightRegions(start+startMatch[1], lineNum, util.SliceStartEnd(line, startMatch[1], endMatch[0]), r, r.rules.regions, true)
234289
if samePattern {
235290
startIdx += 1
@@ -251,8 +306,8 @@ regionLoop:
251306
// log.Println("end < start")
252307
h.lastStart = start
253308
h.lastEnd = start + endMatch[1]
254-
h.storeRange(start, start+endMatch[0], r.group, r)
255-
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r)
309+
h.storeRange(start, start+endMatch[0], r.group, r, false)
310+
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r, false)
256311
h.highlightRegions(start, lineNum, util.SliceStart(line, endMatch[0]), r, r.rules.regions, true)
257312
h.highlightPatterns(start+endMatch[1], lineNum, util.SliceStartEnd(line, endMatch[1], startMatch[0]), nil)
258313
if curRegion != nil {
@@ -271,8 +326,8 @@ regionLoop:
271326
h.lastEnd = start + lineLen - 1
272327
h.lastRegion = r
273328
}
274-
h.storeRange(start+startMatch[0], start+startMatch[1], r.limitGroup, r)
275-
h.storeRange(start+startMatch[1], start+lineLen, r.group, r)
329+
h.storeRange(start+startMatch[0], start+startMatch[1], r.limitGroup, r, false)
330+
h.storeRange(start+startMatch[1], start+lineLen, r.group, r, false)
276331
h.highlightRegions(start+startMatch[1], lineNum, util.SliceEnd(line, startMatch[1]), r, r.rules.regions, true)
277332
continue regionLoop
278333
}
@@ -284,8 +339,8 @@ regionLoop:
284339
// log.Println("... end")
285340
h.lastStart = start
286341
h.lastEnd = start + endMatch[1]
287-
h.storeRange(start, start+endMatch[0], r.group, r)
288-
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r)
342+
h.storeRange(start, start+endMatch[0], r.group, r, false)
343+
h.storeRange(start+endMatch[0], start+endMatch[1], r.limitGroup, r, false)
289344
h.highlightRegions(start, lineNum, util.SliceStart(line, endMatch[0]), r, r.rules.regions, true)
290345
if curRegion != nil {
291346
h.lastRegion = r.parent
@@ -298,7 +353,7 @@ regionLoop:
298353
}
299354
} else if len(startMatches) == 0 && len(endMatches) == 0 {
300355
// no start and end found in this region
301-
h.storeRange(start, start+lineLen, curRegion.group, r)
356+
h.storeRange(start, start+lineLen, curRegion.group, r, false)
302357
}
303358
}
304359
}

0 commit comments

Comments
 (0)