Add stop_at_indent for Editor::DeleteToBeginningOfLine (#25688)
Added test_beginning_of_line_stop_at_indent editor test - Follow-up to: https://github.com/zed-industries/zed/pull/25428 - Replaces: https://github.com/zed-industries/zed/pull/25346 This is all authored by @felixpackard in #25346 I just updated it to use `stop_at_indent` instead of `stop_at_first_char`. Release Notes: - Added support for `stop_at_indent` to `Editor::DeleteToBeginningOfLine` (thanks [@felixpackard](https://github.com/felixpackard)) Co-authored-by: Felix Packard <felix@rigr.gg>
This commit is contained in:
parent
d115cb1944
commit
aa1ab50656
3 changed files with 123 additions and 5 deletions
|
@ -35,6 +35,13 @@ pub struct SelectToBeginningOfLine {
|
||||||
pub stop_at_indent: bool,
|
pub stop_at_indent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct DeleteToBeginningOfLine {
|
||||||
|
#[serde(default)]
|
||||||
|
pub(super) stop_at_indent: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MovePageUp {
|
pub struct MovePageUp {
|
||||||
|
@ -226,6 +233,7 @@ impl_actions!(
|
||||||
ComposeCompletion,
|
ComposeCompletion,
|
||||||
ConfirmCodeAction,
|
ConfirmCodeAction,
|
||||||
ConfirmCompletion,
|
ConfirmCompletion,
|
||||||
|
DeleteToBeginningOfLine,
|
||||||
DeleteToNextWordEnd,
|
DeleteToNextWordEnd,
|
||||||
DeleteToPreviousWordStart,
|
DeleteToPreviousWordStart,
|
||||||
ExpandExcerpts,
|
ExpandExcerpts,
|
||||||
|
@ -292,7 +300,6 @@ gpui::actions!(
|
||||||
CutToEndOfLine,
|
CutToEndOfLine,
|
||||||
Delete,
|
Delete,
|
||||||
DeleteLine,
|
DeleteLine,
|
||||||
DeleteToBeginningOfLine,
|
|
||||||
DeleteToEndOfLine,
|
DeleteToEndOfLine,
|
||||||
DeleteToNextSubwordEnd,
|
DeleteToNextSubwordEnd,
|
||||||
DeleteToPreviousSubwordStart,
|
DeleteToPreviousSubwordStart,
|
||||||
|
|
|
@ -9516,7 +9516,7 @@ impl Editor {
|
||||||
|
|
||||||
pub fn delete_to_beginning_of_line(
|
pub fn delete_to_beginning_of_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &DeleteToBeginningOfLine,
|
action: &DeleteToBeginningOfLine,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
|
@ -9530,7 +9530,7 @@ impl Editor {
|
||||||
this.select_to_beginning_of_line(
|
this.select_to_beginning_of_line(
|
||||||
&SelectToBeginningOfLine {
|
&SelectToBeginningOfLine {
|
||||||
stop_at_soft_wraps: false,
|
stop_at_soft_wraps: false,
|
||||||
stop_at_indent: false,
|
stop_at_indent: action.stop_at_indent,
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -1514,6 +1514,10 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) {
|
||||||
stop_at_indent: true,
|
stop_at_indent: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let delete_to_beg = DeleteToBeginningOfLine {
|
||||||
|
stop_at_indent: false,
|
||||||
|
};
|
||||||
|
|
||||||
let move_to_end = MoveToEndOfLine {
|
let move_to_end = MoveToEndOfLine {
|
||||||
stop_at_soft_wraps: true,
|
stop_at_soft_wraps: true,
|
||||||
};
|
};
|
||||||
|
@ -1672,7 +1676,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
_ = editor.update(cx, |editor, window, cx| {
|
_ = editor.update(cx, |editor, window, cx| {
|
||||||
editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, window, cx);
|
editor.delete_to_beginning_of_line(&delete_to_beg, window, cx);
|
||||||
assert_eq!(editor.display_text(cx), "\n");
|
assert_eq!(editor.display_text(cx), "\n");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.selections.display_ranges(cx),
|
editor.selections.display_ranges(cx),
|
||||||
|
@ -1778,6 +1782,107 @@ fn test_beginning_end_of_line_ignore_soft_wrap(cx: &mut TestAppContext) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) {
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
|
let move_to_beg = MoveToBeginningOfLine {
|
||||||
|
stop_at_soft_wraps: true,
|
||||||
|
stop_at_indent: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let select_to_beg = SelectToBeginningOfLine {
|
||||||
|
stop_at_soft_wraps: true,
|
||||||
|
stop_at_indent: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let delete_to_beg = DeleteToBeginningOfLine {
|
||||||
|
stop_at_indent: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let move_to_end = MoveToEndOfLine {
|
||||||
|
stop_at_soft_wraps: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let editor = cx.add_window(|window, cx| {
|
||||||
|
let buffer = MultiBuffer::build_simple("abc\n def", cx);
|
||||||
|
build_editor(buffer, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = editor.update(cx, |editor, window, cx| {
|
||||||
|
editor.change_selections(None, window, cx, |s| {
|
||||||
|
s.select_display_ranges([
|
||||||
|
DisplayPoint::new(DisplayRow(0), 1)..DisplayPoint::new(DisplayRow(0), 1),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 4),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Moving to the beginning of the line should put the first cursor at the beginning of the line,
|
||||||
|
// and the second cursor at the first non-whitespace character in the line.
|
||||||
|
editor.move_to_beginning_of_line(&move_to_beg, window, cx);
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.display_ranges(cx),
|
||||||
|
&[
|
||||||
|
DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Moving to the beginning of the line again should be a no-op for the first cursor,
|
||||||
|
// and should move the second cursor to the beginning of the line.
|
||||||
|
editor.move_to_beginning_of_line(&move_to_beg, window, cx);
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.display_ranges(cx),
|
||||||
|
&[
|
||||||
|
DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 0)..DisplayPoint::new(DisplayRow(1), 0),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Moving to the beginning of the line again should still be a no-op for the first cursor,
|
||||||
|
// and should move the second cursor back to the first non-whitespace character in the line.
|
||||||
|
editor.move_to_beginning_of_line(&move_to_beg, window, cx);
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.display_ranges(cx),
|
||||||
|
&[
|
||||||
|
DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Selecting to the beginning of the line should select to the beginning of the line for the first cursor,
|
||||||
|
// and to the first non-whitespace character in the line for the second cursor.
|
||||||
|
editor.move_to_end_of_line(&move_to_end, window, cx);
|
||||||
|
editor.move_left(&MoveLeft, window, cx);
|
||||||
|
editor.select_to_beginning_of_line(&select_to_beg, window, cx);
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.display_ranges(cx),
|
||||||
|
&[
|
||||||
|
DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 2),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Selecting to the beginning of the line again should be a no-op for the first cursor,
|
||||||
|
// and should select to the beginning of the line for the second cursor.
|
||||||
|
editor.select_to_beginning_of_line(&select_to_beg, window, cx);
|
||||||
|
assert_eq!(
|
||||||
|
editor.selections.display_ranges(cx),
|
||||||
|
&[
|
||||||
|
DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 0),
|
||||||
|
DisplayPoint::new(DisplayRow(1), 4)..DisplayPoint::new(DisplayRow(1), 0),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Deleting to the beginning of the line should delete to the beginning of the line for the first cursor,
|
||||||
|
// and should delete to the first non-whitespace character in the line for the second cursor.
|
||||||
|
editor.move_to_end_of_line(&move_to_end, window, cx);
|
||||||
|
editor.move_left(&MoveLeft, window, cx);
|
||||||
|
editor.delete_to_beginning_of_line(&delete_to_beg, window, cx);
|
||||||
|
assert_eq!(editor.text(cx), "c\n f");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
|
fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
@ -2295,7 +2400,13 @@ async fn test_delete_to_beginning_of_line(cx: &mut TestAppContext) {
|
||||||
let mut cx = EditorTestContext::new(cx).await;
|
let mut cx = EditorTestContext::new(cx).await;
|
||||||
cx.set_state("one «two threeˇ» four");
|
cx.set_state("one «two threeˇ» four");
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, window, cx);
|
editor.delete_to_beginning_of_line(
|
||||||
|
&DeleteToBeginningOfLine {
|
||||||
|
stop_at_indent: false,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
assert_eq!(editor.text(cx), " four");
|
assert_eq!(editor.text(cx), " four");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue