Skip to content

Commit 9a419c9

Browse files
committed
Add boundChange to RangeComparator
FEATURE: `RangeSet.compare` now supports a `boundChange` callback that is called when there's a change in the way ranges are split. See https://discuss.codemirror.net/t/codemirror6-selection-match-not-merge-when-the-selection-is-repeated-characters/8871
1 parent 84b5484 commit 9a419c9

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

src/rangeset.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ export interface RangeComparator<T extends RangeValue> {
6363
compareRange(from: number, to: number, activeA: T[], activeB: T[]): void
6464
/// Notification for a changed (or inserted, or deleted) point range.
6565
comparePoint(from: number, to: number, pointA: T | null, pointB: T | null): void
66+
/// Notification for a changed boundary between ranges. For example,
67+
/// if the same span is covered by two partial ranges before and one
68+
/// bigger range after, this is called at the point where the ranges
69+
/// used to be split.
70+
boundChange?(pos: number): void
6671
}
6772

6873
/// Methods used when iterating over the spans created by a set of
@@ -827,14 +832,15 @@ function compare<T extends RangeValue>(a: SpanCursor<T>, startA: number,
827832
let endB = startB + length
828833
let pos = startB, dPos = startB - startA
829834
for (;;) {
830-
let diff = (a.to + dPos) - b.to || a.endSide - b.endSide
835+
let dEnd = (a.to + dPos) - b.to, diff = dEnd || a.endSide - b.endSide
831836
let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB)
832837
if (a.point || b.point) {
833838
if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) &&
834839
sameValues(a.activeForPoint(a.to), b.activeForPoint(b.to))))
835840
comparator.comparePoint(pos, clipEnd, a.point, b.point)
836841
} else {
837842
if (clipEnd > pos && !sameValues(a.active, b.active)) comparator.compareRange(pos, clipEnd, a.active, b.active)
843+
else if (end < endB && (dEnd || a.openEnd != b.openEnd) && comparator.boundChange) comparator.boundChange(clipEnd)
838844
}
839845
if (end > endB) break
840846
pos = end

test/test-rangeset.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ describe("RangeSet", () => {
123123
})
124124

125125
describe("map", () => {
126-
function test(positions: Range<Value>[], changes: [number, number, number][], newPositions: (number | [number, number])[]) {
126+
function test(positions: Range<Value>[], changes: [number, number, number][],
127+
newPositions: (number | [number, number])[]) {
127128
let set = mkSet(positions)
128129
let mapped = set.map(changeSet(changes))
129130
let out: string[] = []

0 commit comments

Comments
 (0)