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
pull/2308/head
Matouš Dzivjak 3 years ago committed by GitHub
parent a3c0b4db48
commit 52f5a4228a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2489,8 +2489,8 @@ fn goto_last_line(cx: &mut Context) {
} }
fn goto_last_accessed_file(cx: &mut Context) { fn goto_last_accessed_file(cx: &mut Context) {
let alternate_file = view!(cx.editor).last_accessed_doc; let view = view_mut!(cx.editor);
if let Some(alt) = alternate_file { if let Some(alt) = view.docs_access_history.pop() {
cx.editor.switch(alt, Action::Replace); cx.editor.switch(alt, Action::Replace);
} else { } else {
cx.editor.set_error("no last accessed buffer") cx.editor.set_error("no last accessed buffer")
@ -3796,10 +3796,6 @@ fn jump_backward(cx: &mut Context) {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) { 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; view.doc = *id;
let selection = selection.clone(); let selection = selection.clone();
let (view, doc) = current!(cx.editor); // refetch doc let (view, doc) = current!(cx.editor); // refetch doc

@ -667,7 +667,7 @@ impl Editor {
view.jumps.push(jump); view.jumps.push(jump);
// Set last accessed doc if it is a different document // Set last accessed doc if it is a different document
if doc.id != id { 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 // Set last modified doc if modified and last modified doc is different
if std::mem::take(&mut doc.modified_since_accessed) if std::mem::take(&mut doc.modified_since_accessed)
&& view.last_modified_docs[0] != Some(view.doc) && view.last_modified_docs[0] != Some(view.doc)
@ -785,21 +785,42 @@ impl Editor {
tokio::spawn(language_server.text_document_did_close(doc.identifier())); 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<Action> = self
.tree .tree
.views() .views_mut()
.filter_map(|(view, _focus)| { .filter_map(|(view, _focus)| {
// remove the document from jump list of all views
view.jumps.remove(&doc_id);
if view.doc == 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 { } else {
None None
} }
}) })
.collect::<Vec<_>>(); .collect();
for view_id in views_to_close { for action in actions {
match action {
Action::Close(view_id) => {
self.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); self.documents.remove(&doc_id);

@ -72,8 +72,8 @@ pub struct View {
pub area: Rect, pub area: Rect,
pub doc: DocumentId, pub doc: DocumentId,
pub jumps: JumpList, pub jumps: JumpList,
/// the last accessed file before the current one // documents accessed from this view from the oldest one to last viewed one
pub last_accessed_doc: Option<DocumentId>, pub docs_access_history: Vec<DocumentId>,
/// the last modified files before the current one /// the last modified files before the current one
/// ordered from most frequent to least frequent /// ordered from most frequent to least frequent
// uses two docs because we want to be able to swap between the // uses two docs because we want to be able to swap between the
@ -110,13 +110,20 @@ impl View {
offset: Position::new(0, 0), offset: Position::new(0, 0),
area: Rect::default(), // will get calculated upon inserting into tree area: Rect::default(), // will get calculated upon inserting into tree
jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel 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], last_modified_docs: [None, None],
object_selections: Vec::new(), object_selections: Vec::new(),
gutters, 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 { pub fn inner_area(&self) -> Rect {
// TODO: cache this // TODO: cache this
let offset = self let offset = self

Loading…
Cancel
Save