import Foundation public enum Modification: Codable, Equatable { case deleted(ClosedRange) case inserted(Int, [String]) case deletedSelection(CursorRange) } public extension [String] { mutating func apply(_ modifications: [Modification]) { for modification in modifications { switch modification { case let .deleted(range): if isEmpty { break } let removingRange = range.lowerBound..<(range.upperBound + 1) removeSubrange(removingRange.clamped(to: 0.. Array { var newArray = self newArray.apply(modifications) return newArray } } public extension NSMutableArray { func apply(_ modifications: [Modification]) { for modification in modifications { switch modification { case let .deleted(range): if count == 0 { break } let newRange = range.clamped(to: 0...(count - 1)) removeObjects(in: NSRange(newRange)) case let .inserted(index, strings): for string in strings.reversed() { insert(string, at: Swift.min(count, index)) } case let .deletedSelection(cursorRange): if count == 0 { break } let startLine = cursorRange.start.line let startCharacter = cursorRange.start.character let endLine = cursorRange.end.line let endCharacter = cursorRange.end.character guard startLine < count && endLine < count else { break } if startLine == endLine { if let line = self[startLine] as? String { let startIndex = line.index(line.startIndex, offsetBy: startCharacter) let endIndex = line.index(line.startIndex, offsetBy: endCharacter) let newLine = line.replacingCharacters(in: startIndex..