Repository: helix-editor/helix
File: helix-view/src/document.rs (Rust)

Code before:
                    .map_pos(view_data.view_position.anchor, Assoc::Before);
            }

            // if specified, the current selection should instead be replaced by transaction.selection
            if let Some(selection) = transaction.selection() {
                self.selections.insert(
                    view_id,
                    selection.clone().ensure_invariants(self.text.slice(..)),
                );
                helix_event::dispatch(SelectionDidChange {
                    doc: self,
                    view: view_id,
                });
            }

            self.modified_since_accessed = true;
        }

        if !transaction.changes().is_empty() {
            self.version += 1;
            // start computing the diff in parallel
            if let Some(diff_handle) = &self.diff_handle {
                diff_handle.update_document(self.text.clone(), false);
            }

            // generate revert to savepoint
            if !self.savepoints.is_empty() {
                let revert = transaction.invert(&old_doc);
                self.savepoints
                    .retain_mut(|save_point| match save_point.upgrade() {
                        Some(savepoint) => {
                            let mut revert_to_savepoint = savepoint.revert.lock();
                            *revert_to_savepoint =
                                revert.clone().compose(mem::take(&mut revert_to_savepoint));
                            true
                        }
                        None => false,
                    })
            }

            // update tree-sitter syntax tree
            if let Some(syntax) = &mut self.syntax {
                // TODO: no unwrap
                let res = syntax.update(
                    old_doc.slice(..),
                    self.text.slice(..),
                    transaction.changes(),
                );
                if res.is_err() {
                    log::error!("TS parser failed, disabling TS for the current buffer: {res:?}");
                    self.syntax = None;

Review comment (suggestion):
I do wonder if we should be using `Assoc::After` here instead. I don't have any opinion here. I will try with before and see if it annoys me. It sprobably doesn't make too much difference due to `ensure_cursor_in_view` keeping the view position somewhat fixed in extreme cases. In thsose cases it probably makes more sense to keep the cursor at the top so before is probably right

Code after:
        let old_doc = self.text().clone();

        let success = transaction.changes().apply(&mut self.text);

        if success {
            if emit_lsp_notification {
                helix_event::dispatch(DocumentDidChange {
                    doc: self,
                    view: view_id,
                    old_text: &old_doc,
                });
            }

            for selection in self.selections.values_mut() {
                *selection = selection
                    .clone()
                    // Map through changes
                    .map(transaction.changes())
                    // Ensure all selections across all views still adhere to invariants.
                    .ensure_invariants(self.text.slice(..));
            }

            for view_data in self.view_data.values_mut() {
                view_data.view_position.anchor = transaction
                    .changes()
                    .map_pos(view_data.view_position.anchor, Assoc::Before);
            }

            // if specified, the current selection should instead be replaced by transaction.selection
            if let Some(selection) = transaction.selection() {
                self.selections.insert(
                    view_id,
                    selection.clone().ensure_invariants(self.text.slice(..)),
                );
                helix_event::dispatch(SelectionDidChange {
                    doc: self,
                    view: view_id,
                });
            }

            self.modified_since_accessed = true;
        }

        if !transaction.changes().is_empty() {
            self.version += 1;
            // start computing the diff in parallel
            if let Some(diff_handle) = &self.diff_handle {
                diff_handle.update_document(self.text.clone(), false);
            }

            // generate revert to savepoint