diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs index 130f77b8e..84aaa64c3 100644 --- a/helix-core/src/transaction.rs +++ b/helix-core/src/transaction.rs @@ -1,5 +1,9 @@ use crate::{Rope, Selection, SelectionRange, State, Tendril}; +// TODO: make Change enum internal and export this as the public Change type +/// (from, to, replacement) +type Change2 = (usize, usize, Option); + // TODO: divided into three different operations, I sort of like having just // Splice { extent, Option, distance } better. // insert: Splice { extent: 0, text: Some("a"), distance: 2 } @@ -342,15 +346,11 @@ impl Transaction { true } - pub fn change_by_selection(state: &State, f: F) -> Self - where - F: Fn(&SelectionRange) -> (usize, usize, Option), - { + /// Generate a transaction from a set of changes. + // TODO: take an owned iter instead of Vec + pub fn change(state: &State, changes: Vec) -> Self { let len = state.doc.len_chars(); - let ranges = state.selection.ranges(); - let mut acc = Vec::with_capacity(2 * ranges.len() + 1); - - let changes = ranges.iter().map(f); + let mut acc = Vec::with_capacity(2 * changes.len() + 1); // TODO: verify ranges are ordered and not overlapping. @@ -370,6 +370,14 @@ impl Transaction { Self::from(ChangeSet { changes: acc, len }) } + /// Generate a transaction with a change per selection range. + pub fn change_by_selection(state: &State, f: F) -> Self + where + F: Fn(&SelectionRange) -> Change2, + { + Self::change(state, state.selection.ranges.iter().map(f).collect()) + } + /// Insert text at each selection head. pub fn insert(state: &State, text: Tendril) -> Self { Self::change_by_selection(state, |range| (range.head, range.head, Some(text.clone())))