aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/diff.rs56
-rw-r--r--helix-core/src/transaction.rs6
2 files changed, 31 insertions, 31 deletions
diff --git a/helix-core/src/diff.rs b/helix-core/src/diff.rs
index 9c1fc999..a83db333 100644
--- a/helix-core/src/diff.rs
+++ b/helix-core/src/diff.rs
@@ -1,6 +1,4 @@
-use ropey::Rope;
-
-use crate::{Change, Transaction};
+use crate::{Rope, Transaction};
/// Compares `old` and `new` to generate a [`Transaction`] describing
/// the steps required to get from `old` to `new`.
@@ -25,34 +23,34 @@ pub fn compare_ropes(old: &Rope, new: &Rope) -> Transaction {
// The current position of the change needs to be tracked to
// construct the `Change`s.
let mut pos = 0;
- let changes: Vec<Change> = diff
- .ops()
- .iter()
- .map(|op| op.as_tag_tuple())
- .filter_map(|(tag, old_range, new_range)| {
- // `old_pos..pos` is equivalent to `start..end` for where
- // the change should be applied.
- let old_pos = pos;
- pos += old_range.end - old_range.start;
+ Transaction::change(
+ old,
+ diff.ops()
+ .iter()
+ .map(|op| op.as_tag_tuple())
+ .filter_map(|(tag, old_range, new_range)| {
+ // `old_pos..pos` is equivalent to `start..end` for where
+ // the change should be applied.
+ let old_pos = pos;
+ pos += old_range.end - old_range.start;
- match tag {
- // Semantically, inserts and replacements are the same thing.
- similar::DiffTag::Insert | similar::DiffTag::Replace => {
- // This is the text from the `new` rope that should be
- // inserted into `old`.
- let text: &str = {
- let start = new.char_to_byte(new_range.start);
- let end = new.char_to_byte(new_range.end);
- &new_converted[start..end]
- };
- Some((old_pos, pos, Some(text.into())))
+ match tag {
+ // Semantically, inserts and replacements are the same thing.
+ similar::DiffTag::Insert | similar::DiffTag::Replace => {
+ // This is the text from the `new` rope that should be
+ // inserted into `old`.
+ let text: &str = {
+ let start = new.char_to_byte(new_range.start);
+ let end = new.char_to_byte(new_range.end);
+ &new_converted[start..end]
+ };
+ Some((old_pos, pos, Some(text.into())))
+ }
+ similar::DiffTag::Delete => Some((old_pos, pos, None)),
+ similar::DiffTag::Equal => None,
}
- similar::DiffTag::Delete => Some((old_pos, pos, None)),
- similar::DiffTag::Equal => None,
- }
- })
- .collect();
- Transaction::change(old, changes.into_iter())
+ }),
+ )
}
#[cfg(test)]
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index 048839b3..e20e550f 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -473,11 +473,13 @@ impl Transaction {
/// Generate a transaction from a set of changes.
pub fn change<I>(doc: &Rope, changes: I) -> Self
where
- I: IntoIterator<Item = Change> + ExactSizeIterator,
+ I: IntoIterator<Item = Change> + Iterator,
{
let len = doc.len_chars();
- let mut changeset = ChangeSet::with_capacity(2 * changes.len() + 1); // rough estimate
+ let (lower, upper) = changes.size_hint();
+ let size = upper.unwrap_or(lower);
+ let mut changeset = ChangeSet::with_capacity(2 * size + 1); // rough estimate
// TODO: verify ranges are ordered and not overlapping or change will panic.