diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ad7870738d..6b6bc68f50 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -53,6 +53,7 @@ use workspace::{Navigation, PathOpener, Workspace}; const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); const MAX_LINE_LEN: usize = 1024; +const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10; action!(Cancel); action!(Backspace); @@ -809,6 +810,8 @@ impl Editor { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; + let newest_selection = self.newest_selection_internal().unwrap().clone(); + let start; let end; let mode; @@ -843,6 +846,8 @@ impl Editor { } } + self.push_to_navigation_history(newest_selection.head(), Some(end.to_point(&buffer)), cx); + let selection = Selection { id: post_inc(&mut self.next_selection_id), start, @@ -855,7 +860,6 @@ impl Editor { self.update_selections::(Vec::new(), None, cx); } else if click_count > 1 { // Remove the newest selection since it was only added as part of this multi-click. - let newest_selection = self.newest_selection::(buffer); let mut selections = self.local_selections(cx); selections.retain(|selection| selection.id != newest_selection.id); self.update_selections::(selections, None, cx) @@ -2404,8 +2408,6 @@ impl Editor { return; } - self.push_to_navigation_history(cx); - let selection = Selection { id: post_inc(&mut self.next_selection_id), start: 0, @@ -2428,8 +2430,6 @@ impl Editor { return; } - self.push_to_navigation_history(cx); - let cursor = self.buffer.read(cx).read(cx).len(); let selection = Selection { id: post_inc(&mut self.next_selection_id), @@ -2441,15 +2441,32 @@ impl Editor { self.update_selections(vec![selection], Some(Autoscroll::Fit), cx); } - fn push_to_navigation_history(&self, cx: &mut ViewContext) { + fn push_to_navigation_history( + &self, + position: Anchor, + new_position: Option, + cx: &mut ViewContext, + ) { if let Some(navigation) = &self.navigation { let buffer = self.buffer.read(cx).read(cx); - if let Some(last_selection) = self.selections.iter().max_by_key(|s| s.id) { - let anchor = last_selection.head(); - let offset = anchor.to_offset(&buffer); - drop(buffer); - navigation.push(Some(NavigationData { anchor, offset }), cx); + let offset = position.to_offset(&buffer); + let point = position.to_point(&buffer); + drop(buffer); + + if let Some(new_position) = new_position { + let row_delta = (new_position.row as i64 - point.row as i64).abs(); + if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA { + return; + } } + + navigation.push( + Some(NavigationData { + anchor: position, + offset, + }), + cx, + ); } } @@ -3230,14 +3247,14 @@ impl Editor { &self, snapshot: &MultiBufferSnapshot, ) -> Selection { - self.pending_selection(snapshot) - .or_else(|| { - self.selections - .iter() - .max_by_key(|s| s.id) - .map(|selection| self.resolve_selection(selection, snapshot)) - }) - .unwrap() + self.resolve_selection(self.newest_selection_internal().unwrap(), snapshot) + } + + pub fn newest_selection_internal(&self) -> Option<&Selection> { + self.pending_selection + .as_ref() + .map(|s| &s.selection) + .or_else(|| self.selections.iter().max_by_key(|s| s.id)) } pub fn update_selections( @@ -3248,10 +3265,11 @@ impl Editor { ) where T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug, { + let buffer = self.buffer.read(cx).snapshot(cx); + let old_cursor_position = self.newest_selection_internal().map(|s| s.head()); selections.sort_unstable_by_key(|s| s.start); // Merge overlapping selections. - let buffer = self.buffer.read(cx).snapshot(cx); let mut i = 1; while i < selections.len() { if selections[i - 1].end >= selections[i].start { @@ -3292,22 +3310,21 @@ impl Editor { } } + if let Some(old_cursor_position) = old_cursor_position { + let new_cursor_position = selections + .iter() + .max_by_key(|s| s.id) + .map(|s| s.head().to_point(&buffer)); + if new_cursor_position.is_some() { + self.push_to_navigation_history(old_cursor_position, new_cursor_position, cx); + } + } + if let Some(autoscroll) = autoscroll { self.request_autoscroll(autoscroll, cx); } 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 54b9e19e2f..147622c8d4 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -149,7 +149,9 @@ impl ItemView for Editor { } fn deactivated(&mut self, cx: &mut ViewContext) { - self.push_to_navigation_history(cx); + if let Some(selection) = self.newest_selection_internal() { + self.push_to_navigation_history(selection.head(), None, cx); + } } fn is_dirty(&self, cx: &AppContext) -> bool { diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 614f8b3808..a93ebde051 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -11,13 +11,7 @@ use gpui::{ }; use postage::watch; use project::ProjectPath; -use std::{ - any::Any, - cell::RefCell, - cmp, mem, - rc::Rc, - time::{Duration, Instant}, -}; +use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; use util::ResultExt; action!(Split, SplitDirection); @@ -110,7 +104,6 @@ impl Default for NavigationMode { struct NavigationEntry { item_view: Box, data: Option>, - insertion_time: Option, } impl Pane { @@ -558,20 +551,9 @@ 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(); } @@ -579,14 +561,12 @@ 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 2e1588790a..f5aeec861a 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -701,9 +701,9 @@ mod tests { "/root", json!({ "a": { - "file1": "contents 1", - "file2": "contents 2", - "file3": "contents 3", + "file1": "contents 1\n".repeat(20), + "file2": "contents 2\n".repeat(20), + "file3": "contents 3\n".repeat(20), }, }), ) @@ -731,7 +731,7 @@ mod tests { .downcast::() .unwrap(); editor1.update(&mut cx, |editor, cx| { - editor.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx); + editor.select_display_ranges(&[DisplayPoint::new(10, 0)..DisplayPoint::new(10, 0)], cx); }); let editor2 = workspace .update(&mut cx, |w, cx| w.open_path(file2.clone(), cx)) @@ -748,11 +748,11 @@ mod tests { .downcast::() .unwrap(); editor3.update(&mut cx, |editor, cx| { - editor.select_display_ranges(&[DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)], cx); + editor.select_display_ranges(&[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)], cx); }); assert_eq!( active_location(&workspace, &mut cx), - (file3.clone(), DisplayPoint::new(0, 2)) + (file3.clone(), DisplayPoint::new(15, 0)) ); workspace @@ -776,7 +776,7 @@ mod tests { .await; assert_eq!( active_location(&workspace, &mut cx), - (file1.clone(), DisplayPoint::new(0, 1)) + (file1.clone(), DisplayPoint::new(10, 0)) ); workspace @@ -801,7 +801,7 @@ mod tests { .await; assert_eq!( active_location(&workspace, &mut cx), - (file1.clone(), DisplayPoint::new(0, 1)) + (file1.clone(), DisplayPoint::new(10, 0)) ); workspace @@ -844,7 +844,7 @@ mod tests { .await; assert_eq!( active_location(&workspace, &mut cx), - (file1.clone(), DisplayPoint::new(0, 1)) + (file1.clone(), DisplayPoint::new(10, 0)) ); workspace .update(&mut cx, |w, cx| Pane::go_forward(w, cx))