on master help sign in
feat(commands): better handling of buffer-close (#1397)
52f5a42Matouš Dzivjak
helix-term/src/commands.rs+2−6
@@ -2489,8 +2489,8 @@ fn goto_last_line(cx: &mut Context) {
2489}
2489}
2490
2490
2491fn goto_last_accessed_file(cx: &mut Context) {
2491fn goto_last_accessed_file(cx: &mut Context) {
2492− let alternate_file = view!(cx.editor).last_accessed_doc;
2492+ let view = view_mut!(cx.editor);
2493− if let Some(alt) = alternate_file {
2493+ if let Some(alt) = view.docs_access_history.pop() {
2494 cx.editor.switch(alt, Action::Replace);
2494 cx.editor.switch(alt, Action::Replace);
2495 } else {
2495 } else {
2496 cx.editor.set_error("no last accessed buffer")
2496 cx.editor.set_error("no last accessed buffer")
@@ -3796,10 +3796,6 @@ fn jump_backward(cx: &mut Context) {
3796 let (view, doc) = current!(cx.editor);
3796 let (view, doc) = current!(cx.editor);
3797
3797
3798 if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) {
3798 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− }
3803 view.doc = *id;
3799 view.doc = *id;
3804 let selection = selection.clone();
3800 let selection = selection.clone();
3805 let (view, doc) = current!(cx.editor); // refetch doc
3801 let (view, doc) = current!(cx.editor); // refetch doc
helix-view/src/editor.rs+28−7
@@ -667,7 +667,7 @@ impl Editor {
667 view.jumps.push(jump);
667 view.jumps.push(jump);
668 // Set last accessed doc if it is a different document
668 // Set last accessed doc if it is a different document
669 if doc.id != id {
669 if doc.id != id {
670− view.last_accessed_doc = Some(view.doc);
670+ view.add_to_history(view.doc);
671 // Set last modified doc if modified and last modified doc is different
671 // Set last modified doc if modified and last modified doc is different
672 if std::mem::take(&mut doc.modified_since_accessed)
672 if std::mem::take(&mut doc.modified_since_accessed)
673 && view.last_modified_docs[0] != Some(view.doc)
673 && view.last_modified_docs[0] != Some(view.doc)
@@ -785,20 +785,41 @@ impl Editor {
785 tokio::spawn(language_server.text_document_did_close(doc.identifier()));
785 tokio::spawn(language_server.text_document_did_close(doc.identifier()));
786 }
786 }
787
787
788− let views_to_close = self
788+ enum Action {
789+ Close(ViewId),
790+ ReplaceDoc(ViewId, DocumentId),
791+ }
792+
793+ let actions: Vec<Action> = self
789 .tree
794 .tree
790− .views()
795+ .views_mut()
791 .filter_map(|(view, _focus)| {
796 .filter_map(|(view, _focus)| {
797+ // remove the document from jump list of all views
798+ view.jumps.remove(&doc_id);
799+
792 if view.doc == doc_id {
800 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+ }
794 } else {
808 } else {
795 None
809 None
796 }
810 }
797 })
811 })
798− .collect::<Vec<_>>();
812+ .collect();
799
813
800− for view_id in views_to_close {
814+ for action in actions {
815+ match action {
816+ Action::Close(view_id) => {
801− self.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+ }
802 }
823 }
803
824
804 self.documents.remove(&doc_id);
825 self.documents.remove(&doc_id);
helix-view/src/view.rs+10−3
@@ -72,8 +72,8 @@ pub struct View {
72 pub area: Rect,
72 pub area: Rect,
73 pub doc: DocumentId,
73 pub doc: DocumentId,
74 pub jumps: JumpList,
74 pub jumps: JumpList,
75− /// the last accessed file before the current one
75+ // documents accessed from this view from the oldest one to last viewed one
76− pub last_accessed_doc: Option<DocumentId>,
76+ pub docs_access_history: Vec<DocumentId>,
77 /// the last modified files before the current one
77 /// the last modified files before the current one
78 /// ordered from most frequent to least frequent
78 /// ordered from most frequent to least frequent
79 // uses two docs because we want to be able to swap between the
79 // uses two docs because we want to be able to swap between the
@@ -110,13 +110,20 @@ impl View {
110 offset: Position::new(0, 0),
110 offset: Position::new(0, 0),
111 area: Rect::default(), // will get calculated upon inserting into tree
111 area: Rect::default(), // will get calculated upon inserting into tree
112 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
112 jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
113− last_accessed_doc: None,
113+ docs_access_history: Vec::new(),
114 last_modified_docs: [None, None],
114 last_modified_docs: [None, None],
115 object_selections: Vec::new(),
115 object_selections: Vec::new(),
116 gutters,
116 gutters,
117 }
117 }
118 }
118 }
119
119
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+
120 pub fn inner_area(&self) -> Rect {
127 pub fn inner_area(&self) -> Rect {
121 // TODO: cache this
128 // TODO: cache this
122 let offset = self
129 let offset = self