@@ -1005,6 +1005,8 @@ impl Editor {
10051005 return;
10061006 }
10071007
1008+ self.enter_normal_mode();
1009+
10081010 match action {
10091011 Action::Replace => {
10101012 let (view, doc) = current_ref!(self);
@@ -1025,6 +1027,9 @@ impl Editor {
10251027 let (view, doc) = current!(self);
10261028 let view_id = view.id;
10271029
1030+ // Append any outstanding changes to history in the old document.
1031+ doc.append_changes_to_history(view);
1032+
10281033 if remove_empty_scratch {
10291034 // Copy `doc.id` into a variable before calling `self.documents.remove`, which requires a mutable
10301035 // borrow, invalidating direct access to `doc.id`.
@@ -1262,7 +1267,7 @@ impl Editor {
12621267 // if leaving the view: mode should reset and the cursor should be
12631268 // within view
12641269 if prev_id != view_id {
1265− self.mode = Mode::Normal;
1270+ self.enter_normal_mode();
12661271 self.ensure_cursor_in_view(view_id);
12671272
12681273 // Update jumplist selections with new document changes.
@@ -1427,4 +1432,67 @@ impl Editor {
14271432
14281433 Ok(())
14291434 }
1435+
1436+ /// Switches the editor into normal mode.
1437+ pub fn enter_normal_mode(&mut self) {
1438+ use helix_core::{graphemes, Range};
1439+
1440+ if self.mode == Mode::Normal {
1441+ return;
1442+ }
1443+
1444+ self.mode = Mode::Normal;
1445+ let (view, doc) = current!(self);
1446+
1447+ try_restore_indent(doc, view);
1448+
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| {
1453+ Range::new(
1454+ range.from(),
1455+ graphemes::prev_grapheme_boundary(text, range.to()),
1456+ )
1457+ });
1458+
1459+ doc.set_selection(view.id, selection);
1460+ doc.restore_cursor = false;
1461+ }
1462+ }
1463+}
1464+
1465+fn try_restore_indent(doc: &mut Document, view: &mut View) {
1466+ use helix_core::{
1467+ chars::char_is_whitespace, line_ending::line_end_char_index, Operation, Transaction,
1468+ };
1469+
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(_)] =
1472+ changes
1473+ {
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
1478+ } else {
1479+ false
1480+ }
1481+ }
1482+
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));
1488+
1489+ if inserted_a_new_blank_line(doc_changes, pos, line_end_pos) {
1490+ // Removes tailing whitespaces.
1491+ let transaction =
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)
1495+ });
1496+ crate::apply_transaction(&transaction, doc, view);
1497+ }
14301498}