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