Unnamed repository; edit this file 'description' to name the repository.
Commit an undo checkpoint before each write (#11062)
This fixes the modification indicator when saving from insert mode with a config such as [keys.insert] C-s = ":write" Previously the modification indicator would be stuck showing modified even if the buffer contents matched the disk contents when writing after some changes in insert mode with this binding. In insert mode we do not eagerly write undo checkpoints so that all changes made become one checkpoint as you exit insert mode. When saving, `Document`s `changes` `ChangeSet` would be non-empty and when there are changes we show the buffer as modified. Then switching to normal mode would append the changes to history, bumping the current revision past what it was when last saved. Since the last saved revision and current revision were then unsynced, the modification indicator would always show modified. This matches [Kakoune's behavior]. Kakoune has a different architecture for writes but a very similar system for history, transactions and undo checkpoints (what it calls "undo groups"). Upon saving Kakoune creates an undo checkpoint if there are any uncommitted changes. It does this after the write has gone through since its writing system is different. For our writing system it's cleaner to make the undo checkpoint before performing the save so that the history revision increments before we send the save event. [Kakoune's behavior]: https://github.com/mawww/kakoune/blob/80fcfebca8c62ace6cf2af9487784486af07d2d5/src/buffer.cc#L565-L566
Michael Davis 2024-07-14
parent 35f1c2a · commit 44d2fc2
-rw-r--r--helix-term/src/commands/typed.rs16
1 files changed, 11 insertions, 5 deletions
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 032f016f..ed1547f1 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -340,9 +340,12 @@ fn write_impl(
let path = path.map(AsRef::as_ref);
if config.insert_final_newline {
- insert_final_newline(doc, view);
+ insert_final_newline(doc, view.id);
}
+ // Save an undo checkpoint for any outstanding changes.
+ doc.append_changes_to_history(view);
+
let fmt = if config.auto_format {
doc.auto_format().map(|fmt| {
let callback = make_format_callback(
@@ -367,13 +370,12 @@ fn write_impl(
Ok(())
}
-fn insert_final_newline(doc: &mut Document, view: &mut View) {
+fn insert_final_newline(doc: &mut Document, view_id: ViewId) {
let text = doc.text();
if line_ending::get_line_ending(&text.slice(..)).is_none() {
let eof = Selection::point(text.len_chars());
let insert = Transaction::insert(text, &eof, doc.line_ending.as_str().into());
- doc.apply(&insert, view.id);
- doc.append_changes_to_history(view);
+ doc.apply(&insert, view_id);
}
}
@@ -704,11 +706,15 @@ pub fn write_all_impl(
for (doc_id, target_view) in saves {
let doc = doc_mut!(cx.editor, &doc_id);
+ let view = view_mut!(cx.editor, target_view);
if config.insert_final_newline {
- insert_final_newline(doc, view_mut!(cx.editor, target_view));
+ insert_final_newline(doc, target_view);
}
+ // Save an undo checkpoint for any outstanding changes.
+ doc.append_changes_to_history(view);
+
let fmt = if config.auto_format {
doc.auto_format().map(|fmt| {
let callback = make_format_callback(