Improve duplicateLine(in:)

This commit is contained in:
1024jp 2020-03-21 17:20:14 +09:00
parent 5c21038c6c
commit 9b30ec3d44
3 changed files with 31 additions and 6 deletions

View File

@ -9,6 +9,7 @@ Change Log
- Adjust the text baseline to draw characters vertically center in lines.
- Adjust invisible characters position in the vertical text orientation.
- Duplicate lines more intelligently.
- Improve drawing performance.

View File

@ -361,8 +361,22 @@ extension String {
var replacementRanges = [NSRange]()
var selectedRanges = [NSRange]()
for range in ranges {
let lineRange = string.lineRange(for: range)
// group the ranges sharing the same lines
let rangeGroups: [[NSRange]] = ranges.sorted(\.location)
.reduce(into: []) { (groups, range) in
if let last = groups.last?.last,
string.lineRange(for: last).intersection(string.lineRange(for: range)) != nil
{
groups[groups.count - 1].append(range)
} else {
groups.append([range])
}
}
var offset = 0
for group in rangeGroups {
let unionRange = group.reduce(into: group[0]) { $0.formUnion($1) }
let lineRange = string.lineRange(for: unionRange)
let replacementRange = NSRange(location: lineRange.location, length: 0)
var lineString = string.substring(with: lineRange)
@ -374,10 +388,10 @@ extension String {
replacementStrings.append(lineString)
replacementRanges.append(replacementRange)
let offset = replacementStrings.map { $0.length }.reduce(0, +)
let selectedRange = range.shifted(offset: offset)
selectedRanges.append(selectedRange)
offset += lineString.length
for range in group {
selectedRanges.append(range.shifted(offset: offset))
}
}
return (strings: replacementStrings, ranges: replacementRanges, selectedRanges: selectedRanges)

View File

@ -182,6 +182,16 @@ final class StringLineProcessingTests: XCTestCase {
XCTAssertEqual(info?.strings, ["bbbb\n"])
XCTAssertEqual(info?.ranges, [NSRange(3, 0)])
XCTAssertEqual(info?.selectedRanges, [NSRange(9, 1)])
info = string.duplicateLine(in: [NSRange(4, 1), NSRange(6, 4)])
XCTAssertEqual(info?.strings, ["bbbb\nccc\n"])
XCTAssertEqual(info?.ranges, [NSRange(3, 0)])
XCTAssertEqual(info?.selectedRanges, [NSRange(13, 1), NSRange(15, 4)])
info = string.duplicateLine(in: [NSRange(4, 1), NSRange(6, 1), NSRange(10, 0)])
XCTAssertEqual(info?.strings, ["bbbb\n", "ccc\n"])
XCTAssertEqual(info?.ranges, [NSRange(3, 0), NSRange(8, 0)])
XCTAssertEqual(info?.selectedRanges, [NSRange(9, 1), NSRange(11, 1), NSRange(19, 0)])
}