From 52f5a4228aef2d31cf20aeee2bed317ba1767c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matou=C5=A1=20Dzivjak?= Date: Wed, 27 Apr 2022 18:14:46 +0200 Subject: [PATCH] feat(commands): better handling of buffer-close (#1397) * feat(commands): better handling of buffer-close Previously, when closing buffer, you would loose cursor position in other docs. Also, all splits where the buffer was open would be closed. This PR changes the behavior, if the view has also other buffer previously viewed it switches back to the last one instead of the view being closed. As a side effect, since the views are persisted, the cursor history is persisted as well. Fixes: https://github.com/helix-editor/helix/issues/1186 * Adjust buffer close behavior * Remove closed documents from jump history * Fix after rebase --- helix-term/src/commands.rs | 8 ++------ helix-view/src/editor.rs | 35 ++++++++++++++++++++++++++++------- helix-view/src/view.rs | 13 ++++++++++--- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index fb0940fd9..8a0313efe 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2489,8 +2489,8 @@ fn goto_last_line(cx: &mut Context) { } fn goto_last_accessed_file(cx: &mut Context) { - let alternate_file = view!(cx.editor).last_accessed_doc; - if let Some(alt) = alternate_file { + let view = view_mut!(cx.editor); + if let Some(alt) = view.docs_access_history.pop() { cx.editor.switch(alt, Action::Replace); } else { cx.editor.set_error("no last accessed buffer") @@ -3796,10 +3796,6 @@ fn jump_backward(cx: &mut Context) { let (view, doc) = current!(cx.editor); if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) { - // manually set the alternate_file as we cannot use the Editor::switch function here. - if view.doc != *id { - view.last_accessed_doc = Some(view.doc) - } view.doc = *id; let selection = selection.clone(); let (view, doc) = current!(cx.editor); // refetch doc diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 79775c897..38826f4bf 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -667,7 +667,7 @@ impl Editor { view.jumps.push(jump); // Set last accessed doc if it is a different document if doc.id != id { - view.last_accessed_doc = Some(view.doc); + view.add_to_history(view.doc); // Set last modified doc if modified and last modified doc is different if std::mem::take(&mut doc.modified_since_accessed) && view.last_modified_docs[0] != Some(view.doc) @@ -785,20 +785,41 @@ impl Editor { tokio::spawn(language_server.text_document_did_close(doc.identifier())); } - let views_to_close = self + enum Action { + Close(ViewId), + ReplaceDoc(ViewId, DocumentId), + } + + let actions: Vec = self .tree - .views() + .views_mut() .filter_map(|(view, _focus)| { + // remove the document from jump list of all views + view.jumps.remove(&doc_id); + if view.doc == doc_id { - Some(view.id) + // something was previously open in the view, switch to previous doc + if let Some(prev_doc) = view.docs_access_history.pop() { + Some(Action::ReplaceDoc(view.id, prev_doc)) + } else { + // only the document that is being closed was in the view, close it + Some(Action::Close(view.id)) + } } else { None } }) - .collect::>(); + .collect(); - for view_id in views_to_close { - self.close(view_id); + for action in actions { + match action { + Action::Close(view_id) => { + self.close(view_id); + } + Action::ReplaceDoc(view_id, doc_id) => { + self.replace_document_in_view(view_id, doc_id); + } + } } self.documents.remove(&doc_id); diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs index 7cf88c2e1..3450da9b3 100644 --- a/helix-view/src/view.rs +++ b/helix-view/src/view.rs @@ -72,8 +72,8 @@ pub struct View { pub area: Rect, pub doc: DocumentId, pub jumps: JumpList, - /// the last accessed file before the current one - pub last_accessed_doc: Option, + // documents accessed from this view from the oldest one to last viewed one + pub docs_access_history: Vec, /// the last modified files before the current one /// ordered from most frequent to least frequent // uses two docs because we want to be able to swap between the @@ -110,13 +110,20 @@ impl View { offset: Position::new(0, 0), area: Rect::default(), // will get calculated upon inserting into tree jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel - last_accessed_doc: None, + docs_access_history: Vec::new(), last_modified_docs: [None, None], object_selections: Vec::new(), gutters, } } + pub fn add_to_history(&mut self, id: DocumentId) { + if let Some(pos) = self.docs_access_history.iter().position(|&doc| doc == id) { + self.docs_access_history.remove(pos); + } + self.docs_access_history.push(id); + } + pub fn inner_area(&self) -> Rect { // TODO: cache this let offset = self