Skip to content

Commit

Permalink
Fix Cummualtive Range Offset
Browse files Browse the repository at this point in the history
  • Loading branch information
thecoolwinter committed Jun 22, 2024
1 parent 28afd25 commit 146fd17
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
35 changes: 13 additions & 22 deletions Sources/CodeEditTextView/MarkedTextManager/MarkedTextManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,21 @@ class MarkedTextManager {
/// - Parameters:
/// - insertLength: The length of the string being inserted.
/// - textSelections: The current text selections.
func updateMarkedRanges(
insertLength: Int,
textSelections: [NSRange]
) {
func updateMarkedRanges(insertLength: Int, textSelections: [NSRange]) {
var cumulativeExistingDiff = 0
if markedRanges.isEmpty {
let lengthDiff = insertLength
var newRanges = [NSRange]()
for (idx, range) in textSelections.sorted(by: { $0.location < $1.location }).enumerated() {
let rangeOffset = (lengthDiff * idx) - cumulativeExistingDiff
newRanges.append(NSRange(location: range.location + rangeOffset, length: insertLength))
cumulativeExistingDiff += range.length
}
markedRanges = newRanges
} else if let firstRange = markedRanges.first {
let lengthDiff = insertLength - firstRange.length
var newRanges = [NSRange]()
for (idx, range) in markedRanges.sorted(by: { $0.location < $1.location }).enumerated() {
let rangeOffset = (lengthDiff * idx) - cumulativeExistingDiff
newRanges.append(NSRange(location: range.location + rangeOffset, length: insertLength))
cumulativeExistingDiff += range.length
}
markedRanges = newRanges
let lengthDiff = insertLength
var newRanges = [NSRange]()
let ranges: [NSRange] = if markedRanges.isEmpty {
textSelections.sorted(by: { $0.location < $1.location })
} else {
markedRanges.sorted(by: { $0.location < $1.location })
}

for (idx, range) in ranges.enumerated() {
newRanges.append(NSRange(location: range.location + cumulativeExistingDiff, length: insertLength))
cumulativeExistingDiff += insertLength - range.length
}
markedRanges = newRanges
}

/// Finds any marked ranges for a line and returns them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ extension TextView: NSTextInputClient {
insertLength: (insertString as NSString).length,
textSelections: selectionCopies
)

// Reset the selected ranges to reflect the replaced text.
selectionManager.setSelectedRanges(layoutManager.markedTextManager.markedRanges.map({
NSRange(location: $0.max, length: 0)
Expand Down
22 changes: 22 additions & 0 deletions Tests/CodeEditTextViewTests/MarkedTextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@ class MarkedTextTests: XCTestCase {
)
}

func test_markedTextMultipleSelectionMultipleChar() {
let textView = TextView(string: "ABCDE")
textView.selectionManager.setSelectedRanges([NSRange(location: 0, length: 1), NSRange(location: 4, length: 1)])

textView.setMarkedText("´", selectedRange: .notFound, replacementRange: .notFound)
XCTAssertEqual(textView.string, "´BCD´")

textView.setMarkedText("´´´", selectedRange: .notFound, replacementRange: .notFound)
XCTAssertEqual(textView.string, "´´´BCD´´´")
XCTAssertEqual(
textView.selectionManager.textSelections.map(\.range).sorted(by: { $0.location < $1.location }),
[NSRange(location: 3, length: 0), NSRange(location: 9, length: 0)]
)

textView.insertText("é", replacementRange: .notFound)
XCTAssertEqual(textView.string, "éBCDé")
XCTAssertEqual(
textView.selectionManager.textSelections.map(\.range).sorted(by: { $0.location < $1.location }),
[NSRange(location: 1, length: 0), NSRange(location: 5, length: 0)]
)
}

func test_cancelMarkedText() {
let textView = TextView(string: "")
textView.selectionManager.setSelectedRange(.zero)
Expand Down

0 comments on commit 146fd17

Please sign in to comment.