@@ -1005,6 +1005,8 @@ impl Editor {
1008+ self.enter_normal_mode();
1008 match action {
1010 match action {
1009 Action::Replace => {
1011 Action::Replace => {
1010 let (view, doc) = current_ref!(self);
1012 let (view, doc) = current_ref!(self);
@@ -1025,6 +1027,9 @@ impl Editor {
1025 let (view, doc) = current!(self);
1027 let (view, doc) = current!(self);
1026 let view_id = view.id;
1028 let view_id = view.id;
1030+ // Append any outstanding changes to history in the old document.
1031+ doc.append_changes_to_history(view);
1028 if remove_empty_scratch {
1033 if remove_empty_scratch {
1029 // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
1034 // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
1030 // borrow, invalidating direct access to `doc.id`.
1035 // borrow, invalidating direct access to `doc.id`.
@@ -1262,7 +1267,7 @@ impl Editor {
1262 // if leaving the view: mode should reset and the cursor should be
1267 // if leaving the view: mode should reset and the cursor should be
1263 // within view
1268 // within view
1264 if prev_id != view_id {
1269 if prev_id != view_id {
1265− self.mode = Mode::Normal;
1270+ self.enter_normal_mode();
1266 self.ensure_cursor_in_view(view_id);
1271 self.ensure_cursor_in_view(view_id);
1268 // Update jumplist selections with new document changes.
1273 // Update jumplist selections with new document changes.
@@ -1427,4 +1432,67 @@ impl Editor {
1436+ /// Switches the editor into normal mode.
1437+ pub fn enter_normal_mode(&mut self) {
1438+ use helix_core::{graphemes, Range};
1440+ if self.mode == Mode::Normal {
1444+ self.mode = Mode::Normal;
1445+ let (view, doc) = current!(self);
1447+ try_restore_indent(doc, view);
1449+ // if leaving append mode, move cursor back by 1
1450+ if doc.restore_cursor {
1451+ let text = doc.text().slice(..);
1452+ let selection = doc.selection(view.id).clone().transform(|range| {
1455+ graphemes::prev_grapheme_boundary(text, range.to()),
1459+ doc.set_selection(view.id, selection);
1460+ doc.restore_cursor = false;
1465+fn try_restore_indent(doc: &mut Document, view: &mut View) {
1467+ chars::char_is_whitespace, line_ending::line_end_char_index, Operation, Transaction,
1470+ fn inserted_a_new_blank_line(changes: &[Operation], pos: usize, line_end_pos: usize) -> bool {
1471+ if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
1474+ move_pos + inserted_str.len() == pos
1475+ && inserted_str.starts_with('\n')
1476+ && inserted_str.chars().skip(1).all(char_is_whitespace)
1477+ && pos == line_end_pos // ensure no characters exists after current position
1483+ let doc_changes = doc.changes().changes();
1484+ let text = doc.text().slice(..);
1485+ let range = doc.selection(view.id).primary();
1486+ let pos = range.cursor(text);
1487+ let line_end_pos = line_end_char_index(&text, range.cursor_line(text));
1489+ if inserted_a_new_blank_line(doc_changes, pos, line_end_pos) {
1490+ // Removes tailing whitespaces.
1492+ Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
1493+ let line_start_pos = text.line_to_char(range.cursor_line(text));
1494+ (line_start_pos, pos, None)
1496+ crate::apply_transaction(&transaction, doc, view);