@@ -3,7 +3,7 @@ use helix_core::{
3 regex::Regex,
3 regex::Regex,
5 state::{Direction, Granularity, Mode, State},
5 state::{Direction, Granularity, Mode, State},
6− Range, Selection, Tendril, Transaction,
6+ ChangeSet, Range, Selection, Tendril, Transaction,
8use once_cell::sync::Lazy;
8use once_cell::sync::Lazy;
@@ -253,14 +253,16 @@ pub fn collapse_selection(view: &mut View, _count: usize) {
253 .transform(|range| Range::new(range.head, range.head))
253 .transform(|range| Range::new(range.head, range.head))
256−// insert mode:
256+fn enter_insert_mode(view: &mut View) {
257−// first we calculate the correct cursors/selections
257+ view.state.mode = Mode::Insert;
258−// then we just append at each cursor
259−// lastly, if it was append mode we shift cursor by 1?
260+ view.state.changes = Some(ChangeSet::new(view.state.doc()));
261+ view.state.old_state = Some((view.state.doc().clone(), view.state.selection.clone()));
261// inserts at the start of each selection
263// inserts at the start of each selection
262pub fn insert_mode(view: &mut View, _count: usize) {
264pub fn insert_mode(view: &mut View, _count: usize) {
263− view.state.mode = Mode::Insert;
265+ enter_insert_mode(view);
265 view.state.selection = view
267 view.state.selection = view
@@ -270,7 +272,7 @@ pub fn insert_mode(view: &mut View, _count: usize) {
271// inserts at the end of each selection
273// inserts at the end of each selection
272pub fn append_mode(view: &mut View, _count: usize) {
274pub fn append_mode(view: &mut View, _count: usize) {
273− view.state.mode = Mode::Insert;
275+ enter_insert_mode(view);
274 view.state.restore_cursor = true;
276 view.state.restore_cursor = true;
276 // TODO: as transaction
278 // TODO: as transaction
@@ -303,21 +305,21 @@ fn selection_lines(state: &State) -> Vec<usize> {
304// I inserts at the start of each line with a selection
306// I inserts at the start of each line with a selection
305pub fn prepend_to_line(view: &mut View, count: usize) {
307pub fn prepend_to_line(view: &mut View, count: usize) {
306− view.state.mode = Mode::Insert;
308+ enter_insert_mode(view);
308 move_line_start(view, count);
310 move_line_start(view, count);
311// A inserts at the end of each line with a selection
313// A inserts at the end of each line with a selection
312pub fn append_to_line(view: &mut View, count: usize) {
314pub fn append_to_line(view: &mut View, count: usize) {
313− view.state.mode = Mode::Insert;
315+ enter_insert_mode(view);
315 move_line_end(view, count);
317 move_line_end(view, count);
318// o inserts a new line after each line with a selection
320// o inserts a new line after each line with a selection
319pub fn open_below(view: &mut View, _count: usize) {
321pub fn open_below(view: &mut View, _count: usize) {
320− view.state.mode = Mode::Insert;
322+ enter_insert_mode(view);
322 let lines = selection_lines(&view.state);
324 let lines = selection_lines(&view.state);
@@ -356,6 +358,18 @@ pub fn open_below(view: &mut View, _count: usize) {
356pub fn normal_mode(view: &mut View, _count: usize) {
358pub fn normal_mode(view: &mut View, _count: usize) {
357 view.state.mode = Mode::Normal;
359 view.state.mode = Mode::Normal;
361+ if let Some(changes) = view.state.changes.take() {
362+ // Instead of doing this messy merge we could always commit, and based on transaction
363+ // annotations either add a new layer or compose into the previous one.
364+ let transaction = Transaction::from(changes).with_selection(view.state.selection().clone());
365+ let (doc, selection) = view.state.old_state.take().unwrap();
366+ let mut old_state = State::new(doc);
367+ old_state.selection = selection;
369+ // TODO: take transaction by value?
370+ view.history.commit_revision(&transaction, &old_state);
359 // if leaving append mode, move cursor back by 1
373 // if leaving append mode, move cursor back by 1
360 if view.state.restore_cursor {
374 if view.state.restore_cursor {
361 let text = &view.state.doc.slice(..);
375 let text = &view.state.doc.slice(..);