about summary refs log tree commit diff
path: root/src/text_diff.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-09-20 22:25:55 +0200
committerMel <einebeere@gmail.com>2021-09-20 22:25:55 +0200
commitc25d22681f9bc6ddba512895182af0ce0252731b (patch)
treeeadcdec7d0b4d26d59e77169bd89b8db13e22fb6 /src/text_diff.rs
parent8bcbf51cf4f7924600eae39db67ff653b48ad95d (diff)
downloadka-c25d22681f9bc6ddba512895182af0ce0252731b.tar.zst
ka-c25d22681f9bc6ddba512895182af0ce0252731b.zip
Split out common logic
Diffstat (limited to 'src/text_diff.rs')
-rw-r--r--src/text_diff.rs52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/text_diff.rs b/src/text_diff.rs
new file mode 100644
index 0000000..bab8799
--- /dev/null
+++ b/src/text_diff.rs
@@ -0,0 +1,52 @@
+use difference::{Changeset, Difference};
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug)]
+pub enum TextChange {
+    Inserted { at: usize, new_content: String },
+    Deleted { at: usize, upto: usize },
+}
+
+impl TextChange {
+    pub fn diff(old: &str, new: &str) -> Vec<Self> {
+        let change_set = Changeset::new(old, new, "");
+
+        let mut changes = Vec::new();
+        let mut at: usize = 0;
+
+        for diff in change_set.diffs.iter() {
+            match diff {
+                Difference::Add(new_content) => {
+                    let change = TextChange::Inserted {
+                        at,
+                        new_content: new_content.to_owned(),
+                    };
+                    at += new_content.len();
+                    changes.push(change);
+                }
+                Difference::Rem(removed_content) => {
+                    changes.push(TextChange::Deleted {
+                        at,
+                        upto: removed_content.len(),
+                    });
+                }
+                Difference::Same(same_content) => {
+                    at += same_content.len();
+                }
+            }
+        }
+
+        changes
+    }
+
+    pub fn apply(&self, buffer: &mut String) {
+        match self {
+            TextChange::Deleted { at, upto } => {
+                buffer.replace_range(at..upto, "");
+            }
+            TextChange::Inserted { at, new_content } => {
+                buffer.insert_str(*at, new_content);
+            }
+        }
+    }
+}