@@ -70,7 +70,7 @@ class StyledRangeContainer {
7070 }
7171 }
7272
73- var _storage : [ ProviderID : RangeStore < StyleElement > ] = [ : ]
73+ var _storage : [ ProviderID : ( store : RangeStore < StyleElement > , priority : Int ) ] = [ : ]
7474 weak var delegate : StyledRangeContainerDelegate ?
7575
7676 /// Initialize the container with a list of provider identifiers. Each provider is given an id, they should be
@@ -80,17 +80,21 @@ class StyledRangeContainer {
8080 /// - providers: An array of identifiers given to providers.
8181 init ( documentLength: Int , providers: [ ProviderID ] ) {
8282 for provider in providers {
83- _storage [ provider] = RangeStore < StyleElement > ( documentLength: documentLength)
83+ _storage [ provider] = ( store : RangeStore < StyleElement > ( documentLength: documentLength) , priority : provider )
8484 }
8585 }
8686
87- func addProvider( _ id: ProviderID , documentLength: Int ) {
87+ func addProvider( _ id: ProviderID , priority : Int , documentLength: Int ) {
8888 assert ( !_storage. keys. contains ( id) , " Provider already exists " )
89- _storage [ id] = RangeStore < StyleElement > ( documentLength: documentLength)
89+ _storage [ id] = ( store: RangeStore < StyleElement > ( documentLength: documentLength) , priority: priority)
90+ }
91+
92+ func setPriority( providerId: ProviderID , priority: Int ) {
93+ _storage [ providerId] ? . priority = priority
9094 }
9195
9296 func removeProvider( _ id: ProviderID ) {
93- guard let provider = _storage [ id] else { return }
97+ guard let provider = _storage [ id] ? . store else { return }
9498 applyHighlightResult (
9599 provider: id,
96100 highlights: [ ] ,
@@ -99,64 +103,9 @@ class StyledRangeContainer {
99103 _storage. removeValue ( forKey: id)
100104 }
101105
102- /// Coalesces all styled runs into a single continuous array of styled runs.
103- ///
104- /// When there is an overlapping, conflicting style (eg: provider 2 gives `.comment` to the range `0..<2`, and
105- /// provider 1 gives `.string` to `1..<2`), the provider with a lower identifier will be prioritized. In the example
106- /// case, the final value would be `0..<1=.comment` and `1..<2=.string`.
107- ///
108- /// - Parameter range: The range to query.
109- /// - Returns: An array of continuous styled runs.
110- func runsIn( range: NSRange ) -> [ RangeStoreRun < StyleElement > ] {
111- func combineLowerPriority( _ lhs: inout RangeStoreRun < StyleElement > , _ rhs: RangeStoreRun < StyleElement > ) {
112- lhs. value = lhs. value? . combineLowerPriority ( rhs. value) ?? rhs. value
113- }
114-
115- func combineHigherPriority( _ lhs: inout RangeStoreRun < StyleElement > , _ rhs: RangeStoreRun < StyleElement > ) {
116- lhs. value = lhs. value? . combineHigherPriority ( rhs. value) ?? rhs. value
117- }
118-
119- // Ordered by priority, lower = higher priority.
120- var allRuns = _storage. sorted ( by: { $0. key < $1. key } ) . map { $0. value. runs ( in: range. intRange) }
121- var runs : [ RangeStoreRun < StyleElement > ] = [ ]
122-
123- var minValue = allRuns. compactMap { $0. last } . enumerated ( ) . min ( by: { $0. 1 . length < $1. 1 . length } )
124-
125- while let value = minValue {
126- // Get minimum length off the end of each array
127- let minRunIdx = value. offset
128- var minRun = value. element
129-
130- for idx in ( 0 ..< allRuns. count) . reversed ( ) where idx != minRunIdx {
131- guard let last = allRuns [ idx] . last else { continue }
132- if idx < minRunIdx {
133- combineHigherPriority ( & minRun, last)
134- } else {
135- combineLowerPriority ( & minRun, last)
136- }
137-
138- if last. length == minRun. length {
139- allRuns [ idx] . removeLast ( )
140- } else {
141- // safe due to guard a few lines above.
142- allRuns [ idx] [ allRuns [ idx] . count - 1 ] . subtractLength ( minRun)
143- }
144- }
145-
146- if !allRuns[ minRunIdx] . isEmpty {
147- allRuns [ minRunIdx] . removeLast ( )
148- }
149-
150- runs. append ( minRun)
151- minValue = allRuns. compactMap { $0. last } . enumerated ( ) . min ( by: { $0. 1 . length < $1. 1 . length } )
152- }
153-
154- return runs. reversed ( )
155- }
156-
157106 func storageUpdated( editedRange: NSRange , changeInLength delta: Int ) {
158107 for key in _storage. keys {
159- _storage [ key] ? . storageUpdated ( editedRange: editedRange, changeInLength: delta)
108+ _storage [ key] ? . store . storageUpdated ( editedRange: editedRange, changeInLength: delta)
160109 }
161110 }
162111}
@@ -171,7 +120,7 @@ extension StyledRangeContainer: HighlightProviderStateDelegate {
171120 /// - rangeToHighlight: The range to apply the highlights to.
172121 func applyHighlightResult( provider: ProviderID , highlights: [ HighlightRange ] , rangeToHighlight: NSRange ) {
173122 assert ( rangeToHighlight != . notFound, " NSNotFound is an invalid highlight range " )
174- guard var storage = _storage [ provider] else {
123+ guard var storage = _storage [ provider] ? . store else {
175124 assertionFailure ( " No storage found for the given provider: \( provider) " )
176125 return
177126 }
@@ -193,12 +142,12 @@ extension StyledRangeContainer: HighlightProviderStateDelegate {
193142 lastIndex = highlight. range. max
194143 }
195144
196- if lastIndex != rangeToHighlight. upperBound {
145+ if lastIndex < rangeToHighlight. upperBound {
197146 runs. append ( . empty( length: rangeToHighlight. upperBound - lastIndex) )
198147 }
199148
200149 storage. set ( runs: runs, for: rangeToHighlight. intRange)
201- _storage [ provider] = storage
150+ _storage [ provider] ? . store = storage
202151 delegate? . styleContainerDidUpdate ( in: rangeToHighlight)
203152 }
204153}
0 commit comments