SwiftDiff is a (partial) port of the Google Diff, Match and Patch Library (google-diff-match-patch) to Swift. The Google Diff, Match and Patch Library was originally written by Neil Fraser.
So far only the diff algorithm has been ported. It allows comparing two blocks of plain text and efficiently returning a list of their differences. It supports detecting in-line text differences.
SwiftDiff is licensed under the Apache License 2.0 – see the LICENSE
file for details.
The original Google Diff, Match and Patch Library is also licensed under the same license and Copyright (c) 2006 Google Inc.
diff(text1: "The quick brown fox jumps over the lazy dog.",
text2: "That quick brown fox jumped over a lazy dog.")
Returns an array of Diff
objects:
[
Diff(operation: .equal, text: "Th"),
Diff(operation: .delete, text: "e"),
Diff(operation: .insert, text: "at"),
Diff(operation: .equal, text: " quick brown fox jump"),
Diff(operation: .delete, text: "s"),
Diff(operation: .insert, text: "ed"),
Diff(operation: .equal, text: " over "),
Diff(operation: .delete, text: "the"),
Diff(operation: .insert, text: "a"),
Diff(operation: .equal, text: " lazy dog.")
]
The diffWithIndices
function returns IndexedDiff
objects that include the exact positions where each diff operation occurs:
let text1 = "Hello World"
let text2 = "Hello Swift"
let diffs = diffWithIndices(text1: text1, text2: text2)
// Returns array of IndexedDiff objects:
// [
// IndexedDiff(operation: .equal, text: "Hello ", startIndex: <index>, endIndex: <index>),
// IndexedDiff(operation: .delete, text: "World", startIndex: <index>, endIndex: <index>),
// IndexedDiff(operation: .insert, text: "Swift", startIndex: <index>, endIndex: <index>)
// ]
// For each IndexedDiff:
// - Equal and Delete operations: startIndex and endIndex refer to positions in text1
// - Insert operations: startIndex and endIndex (same value) refer to the position in text2
// Basic diff result without indices
struct Diff {
let operation: Operation
let text: String
}
// Diff result with string indices
struct IndexedDiff {
let operation: Diff.Operation
let text: String
let startIndex: String.Index
let endIndex: String.Index
}
// Diff operations
enum Operation {
case equal
case insert
case delete
}
// Basic Diff convenience methods
let equalDiff = Diff.equal("text")
let insertDiff = Diff.insert("new text")
let deleteDiff = Diff.delete("old text")
// IndexedDiff convenience methods
let indexedEqual = IndexedDiff.equal("text", startIndex: start, endIndex: end)
let indexedInsert = IndexedDiff.insert("new text", at: insertionPoint)
let indexedDelete = IndexedDiff.delete("old text", startIndex: start, endIndex: end)
SwiftDiff correctly handles Unicode text including emoji, combining characters, and various scripts:
// Chinese
let diffs = diffWithIndices(text1: "你好世界", text2: "你好宇宙")
// Japanese
let diffs = diffWithIndices(text1: "こんにちは世界", text2: "こんばんは世界")
// Arabic (RTL)
let diffs = diffWithIndices(text1: "مرحبا بالعالم", text2: "مرحبا بالكون")
// Emoji and mixed scripts
let diffs = diffWithIndices(text1: "Hello 👋 World 🌍", text2: "Hello 👋 Swift 🚀")