diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e1cdb25180..ad7870738d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3297,6 +3297,17 @@ impl Editor { } self.pause_cursor_blinking(cx); + let prev_newest_selection = self.selections.iter().max_by_key(|s| s.id); + let curr_newest_selection = selections.iter().max_by_key(|s| s.id); + if let Some((prev_selection, curr_selection)) = + prev_newest_selection.zip(curr_newest_selection) + { + if prev_selection.head().to_offset(&buffer) != curr_selection.head().to_offset(&buffer) + { + self.push_to_navigation_history(cx); + } + } + self.set_selections( Arc::from_iter(selections.into_iter().map(|selection| { let end_bias = if selection.end > selection.start { diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 13587495bc..54b9e19e2f 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -115,7 +115,9 @@ impl ItemView for Editor { }; drop(buffer); + let navigation = self.navigation.take(); self.select_ranges([offset..offset], Some(Autoscroll::Fit), cx); + self.navigation = navigation; } } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a93ebde051..614f8b3808 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -11,7 +11,13 @@ use gpui::{ }; use postage::watch; use project::ProjectPath; -use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; +use std::{ + any::Any, + cell::RefCell, + cmp, mem, + rc::Rc, + time::{Duration, Instant}, +}; use util::ResultExt; action!(Split, SplitDirection); @@ -104,6 +110,7 @@ impl Default for NavigationMode { struct NavigationEntry { item_view: Box, data: Option>, + insertion_time: Option, } impl Pane { @@ -551,9 +558,20 @@ impl Navigation { let mut state = self.0.borrow_mut(); match state.mode { NavigationMode::Normal => { + let mut insertion_time = Instant::now(); + if let Some(prev_insertion_time) = + state.backward_stack.last().and_then(|e| e.insertion_time) + { + if insertion_time.duration_since(prev_insertion_time) <= Duration::from_secs(2) + { + state.backward_stack.pop(); + insertion_time = prev_insertion_time; + } + } state.backward_stack.push(NavigationEntry { item_view: Box::new(cx.weak_handle()), data: data.map(|data| Box::new(data) as Box), + insertion_time: Some(insertion_time), }); state.forward_stack.clear(); } @@ -561,12 +579,14 @@ impl Navigation { state.forward_stack.push(NavigationEntry { item_view: Box::new(cx.weak_handle()), data: data.map(|data| Box::new(data) as Box), + insertion_time: None, }); } NavigationMode::GoingForward => { state.backward_stack.push(NavigationEntry { item_view: Box::new(cx.weak_handle()), data: data.map(|data| Box::new(data) as Box), + insertion_time: None, }); } } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 1c250661cf..2e1588790a 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -755,6 +755,14 @@ mod tests { (file3.clone(), DisplayPoint::new(0, 2)) ); + workspace + .update(&mut cx, |w, cx| Pane::go_back(w, cx)) + .await; + assert_eq!( + active_location(&workspace, &mut cx), + (file3.clone(), DisplayPoint::new(0, 0)) + ); + workspace .update(&mut cx, |w, cx| Pane::go_back(w, cx)) .await; @@ -771,10 +779,26 @@ mod tests { (file1.clone(), DisplayPoint::new(0, 1)) ); + workspace + .update(&mut cx, |w, cx| Pane::go_back(w, cx)) + .await; + assert_eq!( + active_location(&workspace, &mut cx), + (file1.clone(), DisplayPoint::new(0, 0)) + ); + // Go back one more time and ensure we don't navigate past the first item in the history. workspace .update(&mut cx, |w, cx| Pane::go_back(w, cx)) .await; + assert_eq!( + active_location(&workspace, &mut cx), + (file1.clone(), DisplayPoint::new(0, 0)) + ); + + workspace + .update(&mut cx, |w, cx| Pane::go_forward(w, cx)) + .await; assert_eq!( active_location(&workspace, &mut cx), (file1.clone(), DisplayPoint::new(0, 1)) @@ -801,7 +825,7 @@ mod tests { .await; assert_eq!( active_location(&workspace, &mut cx), - (file3.clone(), DisplayPoint::new(0, 2)) + (file3.clone(), DisplayPoint::new(0, 0)) ); // Go back to an item that has been closed and removed from disk, ensuring it gets skipped. @@ -822,6 +846,13 @@ mod tests { active_location(&workspace, &mut cx), (file1.clone(), DisplayPoint::new(0, 1)) ); + workspace + .update(&mut cx, |w, cx| Pane::go_forward(w, cx)) + .await; + assert_eq!( + active_location(&workspace, &mut cx), + (file3.clone(), DisplayPoint::new(0, 0)) + ); fn active_location( workspace: &ViewHandle,