Skip to content

Instantly share code, notes, and snippets.

@ngs
Created May 17, 2018 02:32
Show Gist options
  • Select an option

  • Save ngs/dfc764ddc99e51ddfe8ae76adf89aee2 to your computer and use it in GitHub Desktop.

Select an option

Save ngs/dfc764ddc99e51ddfe8ae76adf89aee2 to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
import Differ
//let viewController = GraphViewController(string1: "kitten", string2: "sitting")
//viewController.view.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
//PlaygroundPage.current.liveView = viewController.view
//print("Done")
extension NSAttributedString {
struct PatchAttributedString {
let before: NSAttributedString
let after: NSAttributedString
}
func patchAttributedString(with string: String) -> PatchAttributedString {
let baseAttributes = attributes(at: 0, effectiveRange: nil)
let before = mutableCopy() as! NSMutableAttributedString
let after = NSMutableAttributedString(string: string, attributes: baseAttributes)
let (beforeTags, beforeRanges) = self.tags
let (afterTags, afterRanges) = after.tags
//
let deleteAttribute: [NSAttributedStringKey: Any] = baseAttributes.merging([
NSAttributedStringKey.foregroundColor: UIColor.red
], uniquingKeysWith: { $1 })
let insertAttribute: [NSAttributedStringKey: Any] = baseAttributes.merging([
NSAttributedStringKey.foregroundColor: UIColor.green
], uniquingKeysWith: { $1 })
let pathResult = patch(from: beforeTags, to: afterTags)
var indexOffset = 0
pathResult.forEach {
switch $0 {
case .deletion(let index):
before.addAttributes(deleteAttribute, range: beforeRanges[index + indexOffset])
case .insertion(let index, _):
after.addAttributes(insertAttribute, range: afterRanges[index])
indexOffset += 1
}
}
return PatchAttributedString(
before: before.copy() as! NSAttributedString,
after: after.copy() as! NSAttributedString
)
}
var tags: ([String], [NSRange]) {
let options = NSLinguisticTagger.Options.omitWhitespace
let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: Int(options.rawValue))
tagger.string = self.string
let range = NSRange(location: 0, length: string.utf16.count)
var tags = [String]()
var ranges = [NSRange]()
tagger.enumerateTags(in: range, scheme: .nameTypeOrLexicalClass, options: options) { (tag, tokenRange, _, _) in
let token = (self.string as NSString).substring(with: tokenRange)
tags.append(token)
ranges.append(tokenRange)
}
return (tags, ranges)
}
}
let beforeString = "The quick brown fox jumps over the lazy dog"
let afterString = "quick brown fax jumps over the dog hoge"
let p = NSAttributedString(string: beforeString, attributes: [
NSAttributedStringKey.foregroundColor: UIColor.white])
.patchAttributedString(with: afterString)
p.before
p.after
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment