on master help sign in
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

commit52f5a4228aef2d31cf20aeee2bed317ba1767c18 authorMatouš Dzivjak <matousdzivjak@gmail.com> dateWed 27 Apr 2022, 18:14 (5 years ago) parenta3c0b4d
3 files changed+40−16
helix-term/src/commands.rs+2−6 helix-view/src/editor.rs+28−7 helix-view/src/view.rs+10−3
helix-term/src/commands.rs+2−6
@@ -2489,8 +2489,8 @@ fn goto_last_line(cx: &mut Context) {
24892489}
24902490
24912491fn goto_last_accessed_file(cx: &mut Context) {
2492− let alternate_file = view!(cx.editor).last_accessed_doc;
2493− if let Some(alt) = alternate_file {
2492+ let view = view_mut!(cx.editor);
2493+ if let Some(alt) = view.docs_access_history.pop() {
24942494 cx.editor.switch(alt, Action::Replace);
24952495 } else {
24962496 cx.editor.set_error("no last accessed buffer")
@@ -3796,10 +3796,6 @@ fn jump_backward(cx: &mut Context) {
37963796 let (view, doc) = current!(cx.editor);
37973797
37983798 if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) {
3799− // manually set the alternate_file as we cannot use the Editor::switch function here.
3800− if view.doc != *id {
3801− view.last_accessed_doc = Some(view.doc)
3802− }
38033799 view.doc = *id;
38043800 let selection = selection.clone();
38053801 let (view, doc) = current!(cx.editor); // refetch doc
helix-view/src/editor.rs+28−7
@@ -667,7 +667,7 @@ impl Editor {
667667 view.jumps.push(jump);
668668 // Set last accessed doc if it is a different document
669669 if doc.id != id {
670− view.last_accessed_doc = Some(view.doc);
670+ view.add_to_history(view.doc);
671671 // Set last modified doc if modified and last modified doc is different
672672 if std::mem::take(&mut doc.modified_since_accessed)
673673 && view.last_modified_docs[0] != Some(view.doc)
@@ -785,20 +785,41 @@ impl Editor {
785785 tokio::spawn(language_server.text_document_did_close(doc.identifier()));
786786 }
787787
788− let views_to_close = self
788+ enum Action {
789+ Close(ViewId),
790+ ReplaceDoc(ViewId, DocumentId),
791+ }
792+
793+ let actions: Vec<Action> = self
789794 .tree
790− .views()
795+ .views_mut()
791796 .filter_map(|(view, _focus)| {
797+ // remove the document from jump list of all views
798+ view.jumps.remove(&doc_id);
799+
792800 if view.doc == doc_id {
793− Some(view.id)
801+ // something was previously open in the view, switch to previous doc
802+ if let Some(prev_doc) = view.docs_access_history.pop() {
803+ Some(Action::ReplaceDoc(view.id, prev_doc))
804+ } else {
805+ // only the document that is being closed was in the view, close it
806+ Some(Action::Close(view.id))
807+ }
794808 } else {
795809 None
796810 }
797811 })
798− .collect::<Vec<_>>();
812+ .collect();
799813
800− for view_id in views_to_close {
801− self.close(view_id);
814+ for action in actions {
815+ match action {
816+ Action::Close(view_id) => {
817+ self.close(view_id);
818+ }
819+ Action::ReplaceDoc(view_id, doc_id) => {
820+ self.replace_document_in_view(view_id, doc_id);
821+ }
822+ }
802823 }
803824
804825 self.documents.remove(&doc_id);
helix-view/src/view.rs+10−3
@@ -72,8 +72,8 @@ pub struct View {
7272 pub area: Rect,
7373 pub doc: DocumentId,
7474 pub jumps: JumpList,
75− /// the last accessed file before the current one
76− pub last_accessed_doc: Option<DocumentId>,
75+ // documents accessed from this view from the oldest one to last viewed one
76+ pub docs_access_history: Vec<DocumentId>,
7777 /// the last modified files before the current one
7878 /// ordered from most frequent to least frequent
7979 // uses two docs because we want to be able to swap between the
@@ -110,13 +110,20 @@ impl View {
110110 offset: Position::new(0, 0),
111111 area: Rect::default(), // will get calculated upon inserting into tree
112112 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
113− last_accessed_doc: None,
113+ docs_access_history: Vec::new(),
114114 last_modified_docs: [None, None],
115115 object_selections: Vec::new(),
116116 gutters,
117117 }
118118 }
119119
120+ pub fn add_to_history(&mut self, id: DocumentId) {
121+ if let Some(pos) = self.docs_access_history.iter().position(|&doc| doc == id) {
122+ self.docs_access_history.remove(pos);
123+ }
124+ self.docs_access_history.push(id);
125+ }
126+
120127 pub fn inner_area(&self) -> Rect {
121128 // TODO: cache this
122129 let offset = self