diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 6eaa89aa..e54c7497 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -959,7 +959,8 @@ impl Editor { fn _refresh(&mut self) { let config = self.config(); for (view, _) in self.tree.views_mut() { - let doc = &self.documents[&view.doc]; + let doc = doc_mut!(self, &view.doc); + view.sync_changes(doc); view.ensure_cursor_in_view(doc, config.scrolloff) } } @@ -971,6 +972,7 @@ impl Editor { let doc = doc_mut!(self, &doc_id); doc.ensure_view_init(view.id); + view.sync_changes(doc); align_view(doc, view, Align::Center); } @@ -1239,6 +1241,9 @@ impl Editor { // within view if prev_id != view_id { self.mode = Mode::Normal; + let view = view_mut!(self, view_id); + let doc = doc_mut!(self, &view.doc); + view.sync_changes(doc); self.ensure_cursor_in_view(view_id); } } diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index c917a1ab..845a5458 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -3,7 +3,10 @@ use helix_core::{ pos_at_visual_coords, visual_coords_at_pos, Position, RopeSlice, Selection, Transaction, }; -use std::{collections::VecDeque, fmt}; +use std::{ + collections::{HashMap, VecDeque}, + fmt, +}; const JUMP_LIST_CAPACITY: usize = 30; @@ -102,6 +105,11 @@ pub struct View { pub object_selections: Vec, /// GutterTypes used to fetch Gutter (constructor) and width for rendering gutters: Vec, + /// A mapping between documents and the last history revision the view was updated at. + /// Changes between documents and views are synced lazily when switching windows. This + /// mapping keeps track of the last applied history revision so that only new changes + /// are applied. + doc_revisions: HashMap, } impl fmt::Debug for View { @@ -126,6 +134,7 @@ impl View { last_modified_docs: [None, None], object_selections: Vec::new(), gutters: gutter_types, + doc_revisions: HashMap::new(), } } @@ -349,10 +358,33 @@ impl View { /// Applies a [`Transaction`] to the view. /// Instead of calling this function directly, use [crate::apply_transaction] /// which applies a transaction to the [`Document`] and view together. - pub fn apply(&mut self, transaction: &Transaction, doc: &Document) -> bool { + pub fn apply(&mut self, transaction: &Transaction, doc: &mut Document) { self.jumps.apply(transaction, doc); - // TODO: remove the boolean return. This is unused. - true + self.doc_revisions + .insert(doc.id(), doc.get_current_revision()); + } + + pub fn sync_changes(&mut self, doc: &mut Document) { + let latest_revision = doc.get_current_revision(); + let current_revision = *self + .doc_revisions + .entry(doc.id()) + .or_insert(latest_revision); + + if current_revision == latest_revision { + return; + } + + log::debug!( + "Syncing view {:?} between {} and {}", + self.id, + current_revision, + latest_revision + ); + + if let Some(transaction) = doc.history.get_mut().changes_since(current_revision) { + self.apply(&transaction, doc); + } } }