@@ -1,4 +1,4 @@
1−use crate::{Rope, Selection, Tendril};
1+use crate::{Rope, Selection, SelectionRange, State, Tendril};
22
33// TODO: divided into three different operations, I sort of like having just
44// Splice { extent, Option<text>, distance } better.
@@ -47,18 +47,6 @@ impl ChangeSet {
4747 }
4848 }
4949
50− pub fn insert(doc: &Rope, pos: usize, c: char) -> Self {
51− let len = doc.len_chars();
52− Self {
53− changes: vec![
54− Change::Retain(pos),
55− Change::Insert(Tendril::from_char(c)),
56− Change::Retain(len - pos),
57− ],
58− len,
59− }
60− }
61−
6250 // TODO: from iter
6351
6452 /// Combine two changesets together.
@@ -210,8 +198,11 @@ impl ChangeSet {
210198 unimplemented!()
211199 }
212200
213− pub fn apply(&self, text: &mut Rope) {
214− // TODO: validate text.chars() == self.len
201+ /// Returns true if applied successfully.
202+ pub fn apply(&self, text: &mut Rope) -> bool {
203+ if text.len_chars() != self.len {
204+ return false;
205+ }
215206
216207 let mut pos = 0;
217208
@@ -231,6 +222,7 @@ impl ChangeSet {
231222 }
232223 }
233224 }
225+ true
234226 }
235227
236228 /// `true` when the set is empty.
@@ -332,7 +324,60 @@ pub struct Transaction {
332324 // scroll_into_view
333325}
334326
335−impl Transaction {}
327+impl Transaction {
328+ /// Returns true if applied successfully.
329+ pub fn apply(&self, state: &mut State) -> bool {
330+ // apply changes to the document
331+ if !self.changes.apply(&mut state.doc) {
332+ return false;
333+ }
334+
335+ // update the selection: either take the selection specified in the transaction, or map the
336+ // current selection through changes.
337+ state.selection = self
338+ .selection
339+ .clone()
340+ .unwrap_or_else(|| state.selection.clone().map(&self.changes));
341+
342+ true
343+ }
344+
345+ pub fn insert(state: &State, text: Tendril) -> Self {
346+ let len = state.doc.len_chars();
347+ let ranges = state.selection.ranges();
348+ let mut changes = Vec::with_capacity(2 * ranges.len() + 1);
349+ let mut last = 0;
350+
351+ for range in state.selection.ranges() {
352+ let cur = range.head;
353+ changes.push(Change::Retain(cur));
354+ changes.push(Change::Insert(text.clone()));
355+ last = cur;
356+ }
357+ changes.push(Change::Retain(len - last));
358+
359+ Self::from(ChangeSet { changes, len })
360+ }
361+
362+ pub fn change_selection<F>(selection: Selection, f: F) -> Self
363+ where
364+ F: Fn(SelectionRange) -> ChangeSet,
365+ {
366+ selection.ranges().iter().map(|range| true);
367+ // TODO: most idiomatic would be to return a
368+ // Change { from: x, to: y, insert: "str" }
369+ unimplemented!()
370+ }
371+}
372+
373+impl From<ChangeSet> for Transaction {
374+ fn from(changes: ChangeSet) -> Self {
375+ Self {
376+ changes,
377+ selection: None,
378+ }
379+ }
380+}
336381
337382#[cfg(test)]
338383mod test {