Sync changes between doc and view on switch

This commit is contained in:
Michael Davis 2022-11-27 10:45:17 -06:00 committed by Blaž Hrastnik
parent 4d1f5389f9
commit 056a19a003
2 changed files with 42 additions and 5 deletions

View file

@ -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);
}
}

View file

@ -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<Selection>,
/// GutterTypes used to fetch Gutter (constructor) and width for rendering
gutters: Vec<GutterType>,
/// 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<DocumentId, usize>,
}
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);
}
}
}