@@ -24,10 +24,11 @@ type LineStates interface {
2424
2525// highlightStorage is used to store the found ranges
2626type 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
9192func (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
148203func (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