@@ -322,17 +322,23 @@ pub fn select_line(cx: &mut Context) {
322322 cx.view.doc.set_selection(Selection::single(start, end));
323323}
324324
325−pub fn delete_selection(cx: &mut Context) {
325+// heuristic: append changes to history after each command, unless we're in insert mode
326+
327+fn _delete_selection(cx: &mut Context) {
326328 let transaction = Transaction::change_by_selection(&cx.view.doc.state, |range| {
327329 (range.from(), range.to() + 1, None)
328330 });
329331 cx.view.doc.apply(&transaction);
332+}
333+
334+pub fn delete_selection(cx: &mut Context) {
335+ _delete_selection(cx);
330336
331337 append_changes_to_history(cx);
332338}
333339
334340pub fn change_selection(cx: &mut Context) {
335− delete_selection(cx);
341+ _delete_selection(cx);
336342 insert_mode(cx);
337343}
338344
@@ -359,8 +365,9 @@ pub fn flip_selections(cx: &mut Context) {
359365fn enter_insert_mode(cx: &mut Context) {
360366 cx.view.doc.mode = Mode::Insert;
361367
362− append_changes_to_history(cx);
368+ // TODO: store selection for undo
363369}
370+
364371// inserts at the start of each selection
365372pub fn insert_mode(cx: &mut Context) {
366373 enter_insert_mode(cx);
@@ -535,6 +542,8 @@ fn append_changes_to_history(cx: &mut Context) {
535542 return;
536543 }
537544
545+ // TODO: change -> change -> undo -> change -> change fails, probably old_state needs reset
546+
538547 let new_changeset = ChangeSet::new(cx.view.doc.text());
539548 let changes = std::mem::replace(&mut cx.view.doc.changes, new_changeset);
540549 // Instead of doing this messy merge we could always commit, and based on transaction
@@ -548,7 +557,13 @@ fn append_changes_to_history(cx: &mut Context) {
548557 // TODO: trigger lsp/documentDidChange with changes
549558
550559 // HAXX: we need to reconstruct the state as it was before the changes..
551− let old_state = std::mem::replace(&mut cx.view.doc.old_state, cx.view.doc.state.clone());
560+ let old_state = cx
561+ .view
562+ .doc
563+ .old_state
564+ .take()
565+ .expect("no old_state available");
566+
552567 // TODO: take transaction by value?
553568 cx.view
554569 .doc
@@ -649,6 +664,7 @@ pub fn undo(cx: &mut Context) {
649664 if let Some(revert) = cx.view.doc.history.undo() {
650665 cx.view.doc.version += 1;
651666 cx.view.doc.apply(&revert);
667+ // TODO: undo/redo needs to avoid storing in self.changes/self.old_state
652668 }
653669
654670 // TODO: each command could simply return a Option<transaction>, then the higher level handles storing it?