Detailed changes
@@ -5258,6 +5258,7 @@ impl Editor {
this: &mut Editor,
snapshot: &DisplaySnapshot,
initial_point: Point,
+ is_wrapped: bool,
direction: Direction,
cx: &mut ViewContext<Editor>,
) -> bool {
@@ -5274,12 +5275,18 @@ impl Editor {
let display_point = initial_point.to_display_point(snapshot);
let mut hunks = hunks
.map(|hunk| diff_hunk_to_display(hunk, &snapshot))
- .skip_while(|hunk| hunk.display_row_range().contains(&display_point.row()))
+ .skip_while(|hunk| {
+ if is_wrapped {
+ false
+ } else {
+ hunk.contains_display_row(display_point.row())
+ }
+ })
.dedup();
if let Some(hunk) = hunks.next() {
this.change_selections(Some(Autoscroll::Center), cx, |s| {
- let row = hunk.display_row_range().start;
+ let row = hunk.start_display_row();
let point = DisplayPoint::new(row, 0);
s.select_display_ranges([point..point]);
});
@@ -5290,12 +5297,12 @@ impl Editor {
}
}
- if !seek_in_direction(self, &snapshot, selection.head(), direction, cx) {
+ if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
let wrapped_point = match direction {
Direction::Next => Point::zero(),
Direction::Prev => snapshot.buffer_snapshot.max_point(),
};
- seek_in_direction(self, &snapshot, wrapped_point, direction, cx);
+ seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
}
}
@@ -7,11 +7,11 @@ use unindent::Unindent;
use super::*;
use crate::test::{
- assert_text_with_selections, build_editor, editor_git_test_context::EditorGitTestContext,
- editor_lsp_test_context::EditorLspTestContext, editor_test_context::EditorTestContext,
- select_ranges,
+ assert_text_with_selections, build_editor, editor_lsp_test_context::EditorLspTestContext,
+ editor_test_context::EditorTestContext, select_ranges,
};
use gpui::{
+ executor::Deterministic,
geometry::rect::RectF,
platform::{WindowBounds, WindowOptions},
};
@@ -5081,8 +5081,108 @@ fn test_combine_syntax_and_fuzzy_match_highlights() {
}
#[gpui::test]
-fn go_to_hunk(cx: &mut gpui::TestAppContext) {
- let mut cx = EditorGitTestContext::new(cx);
+async fn go_to_hunk(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
+ let mut cx = EditorTestContext::new(cx);
+
+ let diff_base = r#"
+ use some::mod;
+
+ const A: u32 = 42;
+
+ fn main() {
+ println!("hello");
+
+ println!("world");
+ }
+ "#
+ .unindent();
+
+ // Edits are modified, removed, modified, added
+ cx.set_state(
+ &r#"
+ use some::modified;
+
+ ˇ
+ fn main() {
+ println!("hello there");
+
+ println!("around the");
+ println!("world");
+ }
+ "#
+ .unindent(),
+ );
+
+ cx.set_diff_base(Some(&diff_base));
+ deterministic.run_until_parked();
+
+ cx.update_editor(|editor, cx| {
+ //Wrap around the bottom of the buffer
+ for _ in 0..3 {
+ editor.go_to_hunk(&GoToHunk, cx);
+ }
+ });
+
+ cx.assert_editor_state(
+ &r#"
+ ˇuse some::modified;
+
+
+ fn main() {
+ println!("hello there");
+
+ println!("around the");
+ println!("world");
+ }
+ "#
+ .unindent(),
+ );
+
+ cx.update_editor(|editor, cx| {
+ //Wrap around the top of the buffer
+ for _ in 0..2 {
+ editor.go_to_prev_hunk(&GoToPrevHunk, cx);
+ }
+ });
+
+ cx.assert_editor_state(
+ &r#"
+ use some::modified;
+
+
+ fn main() {
+ ˇ println!("hello there");
+
+ println!("around the");
+ println!("world");
+ }
+ "#
+ .unindent(),
+ );
+
+ cx.update_editor(|editor, cx| {
+ editor.fold(&Fold, cx);
+
+ //Make sure that the fold only gets one hunk
+ for _ in 0..4 {
+ editor.go_to_hunk(&GoToHunk, cx);
+ }
+ });
+
+ cx.assert_editor_state(
+ &r#"
+ ˇuse some::modified;
+
+
+ fn main() {
+ println!("hello there");
+
+ println!("around the");
+ println!("world");
+ }
+ "#
+ .unindent(),
+ );
}
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
@@ -21,14 +21,32 @@ pub enum DisplayDiffHunk {
}
impl DisplayDiffHunk {
- pub fn display_row_range(&self) -> Range<u32> {
+ pub fn start_display_row(&self) -> u32 {
match self {
- &DisplayDiffHunk::Folded { display_row } => display_row..display_row + 1,
+ &DisplayDiffHunk::Folded { display_row } => display_row,
DisplayDiffHunk::Unfolded {
display_row_range, ..
- } => display_row_range.clone(),
+ } => display_row_range.start,
}
}
+
+ pub fn contains_display_row(&self, display_row: u32) -> bool {
+ let range = match self {
+ &DisplayDiffHunk::Folded { display_row } => display_row..=display_row,
+
+ DisplayDiffHunk::Unfolded {
+ display_row_range, ..
+ } => {
+ if display_row_range.len() == 0 {
+ display_row_range.start..=display_row_range.end
+ } else {
+ display_row_range.start..=display_row_range.end - 1
+ }
+ }
+ };
+
+ range.contains(&display_row)
+ }
}
pub fn diff_hunk_to_display(hunk: DiffHunk<u32>, snapshot: &DisplaySnapshot) -> DisplayDiffHunk {
@@ -1,4 +1,3 @@
-pub mod editor_git_test_context;
pub mod editor_lsp_test_context;
pub mod editor_test_context;
@@ -1,56 +0,0 @@
-use std::ops::{Deref, DerefMut};
-
-use gpui::ModelHandle;
-use language::Buffer;
-use settings::Settings;
-
-use crate::MultiBuffer;
-
-use super::{build_editor, editor_test_context::EditorTestContext};
-
-pub struct EditorGitTestContext<'a> {
- pub cx: EditorTestContext<'a>,
- pub buffer: ModelHandle<Buffer>,
-}
-
-impl<'a> EditorGitTestContext<'a> {
- pub async fn new(cx: &'a mut gpui::TestAppContext) -> EditorGitTestContext<'a> {
- let (window_id, buffer, editor) = cx.update(|cx| {
- cx.set_global(Settings::test(cx));
- crate::init(cx);
-
- let buffer = cx.add_model(|cx| Buffer::new(0, "", cx));
- let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
-
- let (window_id, editor) =
- cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
-
- editor.update(cx, |_, cx| cx.focus_self());
-
- (window_id, buffer, editor)
- });
-
- Self {
- cx: EditorTestContext {
- cx,
- window_id,
- editor,
- },
- buffer,
- }
- }
-}
-
-impl<'a> Deref for EditorGitTestContext<'a> {
- type Target = EditorTestContext<'a>;
-
- fn deref(&self) -> &Self::Target {
- &self.cx
- }
-}
-
-impl<'a> DerefMut for EditorGitTestContext<'a> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.cx
- }
-}
@@ -151,6 +151,11 @@ impl<'a> EditorTestContext<'a> {
snapshot.anchor_before(ranges[0].start)..snapshot.anchor_after(ranges[0].end)
}
+ pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
+ let diff_base = diff_base.map(String::from);
+ self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
+ }
+
/// Change the editor's text and selections using a string containing
/// embedded range markers that represent the ranges and directions of
/// each selection.
@@ -681,7 +681,7 @@ impl Buffer {
self.diff_base.as_deref()
}
- pub fn update_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
+ pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
self.diff_base = diff_base;
self.git_diff_recalc(cx);
}
@@ -4410,7 +4410,7 @@ impl Project {
.await;
let buffer_id = buffer.update(&mut cx, |buffer, cx| {
- buffer.update_diff_base(diff_base.clone(), cx);
+ buffer.set_diff_base(diff_base.clone(), cx);
buffer.remote_id()
});
@@ -4968,7 +4968,7 @@ impl Project {
.and_then(|b| b.upgrade(cx))
.ok_or_else(|| anyhow!("No such buffer {}", buffer_id))?;
- buffer.update(cx, |buffer, cx| buffer.update_diff_base(diff_base, cx));
+ buffer.update(cx, |buffer, cx| buffer.set_diff_base(diff_base, cx));
Ok(())
})