Skip to content

Commit

Permalink
make sure to sync views when applying edits to unfocused views
Browse files Browse the repository at this point in the history
this fixes bugs when applying workspace edits with lsp to a view
where the most recent selection range is outside the current document
or when adding a newline/formatting during write all in the same situation
  • Loading branch information
gabydd committed Jan 7, 2024
1 parent bf7c4e1 commit 435a1d0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 34 deletions.
17 changes: 3 additions & 14 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,6 @@ pub fn apply_workspace_edit(
}
};

let current_view_id = view!(editor).id;
let doc_id = match editor.open(&path, Action::Load) {
Ok(doc_id) => doc_id,
Err(err) => {
Expand All @@ -897,7 +896,7 @@ pub fn apply_workspace_edit(
}
};

let doc = doc_mut!(editor, &doc_id);
let doc = doc!(editor, &doc_id);
if let Some(version) = version {
if version != doc.version() {
let err = format!("outdated workspace edit for {path:?}");
Expand All @@ -908,18 +907,8 @@ pub fn apply_workspace_edit(
}

// Need to determine a view for apply/append_changes_to_history
let selections = doc.selections();
let view_id = if selections.contains_key(&current_view_id) {
// use current if possible
current_view_id
} else {
// Hack: we take the first available view_id
selections
.keys()
.next()
.copied()
.expect("No view_id available")
};
let view_id = editor.get_synced_view_id(doc_id);
let doc = doc_mut!(editor, &doc_id);

let transaction = helix_lsp::util::generate_transaction_from_edits(
doc.text(),
Expand Down
29 changes: 9 additions & 20 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,13 +675,15 @@ pub fn write_all_impl(
let mut errors: Vec<&'static str> = Vec::new();
let config = cx.editor.config();
let jobs = &mut cx.jobs;
let current_view = view!(cx.editor);

let saves: Vec<_> = cx
.editor
.documents
.values_mut()
.filter_map(|doc| {
.keys()
.cloned()
.collect::<Vec<_>>()
.into_iter()
.filter_map(|id| {
let doc = doc!(cx.editor, &id);
if !doc.is_modified() {
return None;
}
Expand All @@ -692,22 +694,9 @@ pub fn write_all_impl(
return None;
}

// Look for a view to apply the formatting change to. If the document
// is in the current view, just use that. Otherwise, since we don't
// have any other metric available for better selection, just pick
// the first view arbitrarily so that we still commit the document
// state for undos. If somehow we have a document that has not been
// initialized with any view, initialize it with the current view.
let target_view = if doc.selections().contains_key(&current_view.id) {
current_view.id
} else if let Some(view) = doc.selections().keys().next() {
*view
} else {
doc.ensure_view_init(current_view.id);
current_view.id
};

Some((doc.id(), target_view))
// Look for a view to apply the formatting change to.
let target_view = cx.editor.get_synced_view_id(doc.id());
Some((id, target_view))
})
.collect();

Expand Down
24 changes: 24 additions & 0 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1827,6 +1827,30 @@ impl Editor {
.as_ref()
.and_then(|debugger| debugger.current_stack_frame())
}

/// Returns the id of a view that this doc contains a selection for,
/// making sure it is synced with the current changes
/// if possible or there are no selections returns current_view
/// otherwise uses an arbitrary view
pub fn get_synced_view_id(&mut self, id: DocumentId) -> ViewId {
let current_view = view_mut!(self);
let doc = self.documents.get_mut(&id).unwrap();
if doc.selections().contains_key(&current_view.id) {
// only need to sync current view if this is not the current doc
if current_view.doc != id {
current_view.sync_changes(doc);
}
current_view.id
} else if let Some(view_id) = doc.selections().keys().next() {
let view_id = *view_id;
let view = self.tree.get_mut(view_id);
view.sync_changes(doc);
view_id
} else {
doc.ensure_view_init(current_view.id);
current_view.id
}
}
}

fn try_restore_indent(doc: &mut Document, view: &mut View) {
Expand Down

0 comments on commit 435a1d0

Please sign in to comment.