editor: Fix DeleteToPreviousWordStart and DeleteToNextWordEnd interaction with newlines (#16848)
Closes #5285, #14389 Changes: - `DeleteToPreviousWordStart` now deletes '\n' separately from preceding words and whitespace. - `DeleteToNextWordEnd` now deletes '\n' and any following whitespace separately from subsequent words. - Added an `ignore_newlines` flag to both actions to optionally retain the old behavior. These modifications align the behavior more closely with other popular editors like VSCode and Sublime: - `DeleteToPreviousWordStart` now matches the default <Ctrl+Backspace> action in those editors. - `DeleteToNextWordEnd` becomes more intuitive and closely resembles the default <Ctrl+Delete> behavior in those editors. Release Notes: - Improved `DeleteToPreviousWordStart` and `DeleteToNextWordEnd` interactions around newlines. You can opt-in into the previous behavior by adding {"ignore_newlines": true} to either action's binds in your keymap. ([#5285](https://github.com/zed-industries/zed/issues/5285), [#14389](https://github.com/zed-industries/zed/issues/14389))
This commit is contained in:
parent
a3d8dcda36
commit
96b592f00d
4 changed files with 151 additions and 8 deletions
|
@ -2102,7 +2102,12 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
|
|||
DisplayPoint::new(DisplayRow(0), 9)..DisplayPoint::new(DisplayRow(0), 12),
|
||||
])
|
||||
});
|
||||
view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
|
||||
view.delete_to_previous_word_start(
|
||||
&DeleteToPreviousWordStart {
|
||||
ignore_newlines: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "e two te four");
|
||||
});
|
||||
|
||||
|
@ -2115,11 +2120,94 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
|
|||
DisplayPoint::new(DisplayRow(0), 9)..DisplayPoint::new(DisplayRow(0), 10),
|
||||
])
|
||||
});
|
||||
view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
|
||||
view.delete_to_next_word_end(
|
||||
&DeleteToNextWordEnd {
|
||||
ignore_newlines: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "e t te our");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_delete_to_previous_word_start_or_newline(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let view = cx.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple("one\n2\nthree\n4", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
});
|
||||
let del_to_prev_word_start = DeleteToPreviousWordStart {
|
||||
ignore_newlines: false,
|
||||
};
|
||||
let del_to_prev_word_start_ignore_newlines = DeleteToPreviousWordStart {
|
||||
ignore_newlines: true,
|
||||
};
|
||||
|
||||
_ = view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
DisplayPoint::new(DisplayRow(3), 1)..DisplayPoint::new(DisplayRow(3), 1)
|
||||
])
|
||||
});
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "one\n2\nthree\n");
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "one\n2\nthree");
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "one\n2\n");
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "one\n2");
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start_ignore_newlines, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "one\n");
|
||||
view.delete_to_previous_word_start(&del_to_prev_word_start_ignore_newlines, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_delete_to_next_word_end_or_newline(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let view = cx.add_window(|cx| {
|
||||
let buffer = MultiBuffer::build_simple("\none\n two\nthree\n four", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
});
|
||||
let del_to_next_word_end = DeleteToNextWordEnd {
|
||||
ignore_newlines: false,
|
||||
};
|
||||
let del_to_next_word_end_ignore_newlines = DeleteToNextWordEnd {
|
||||
ignore_newlines: true,
|
||||
};
|
||||
|
||||
_ = view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
DisplayPoint::new(DisplayRow(0), 0)..DisplayPoint::new(DisplayRow(0), 0)
|
||||
])
|
||||
});
|
||||
view.delete_to_next_word_end(&del_to_next_word_end, cx);
|
||||
assert_eq!(
|
||||
view.buffer.read(cx).read(cx).text(),
|
||||
"one\n two\nthree\n four"
|
||||
);
|
||||
view.delete_to_next_word_end(&del_to_next_word_end, cx);
|
||||
assert_eq!(
|
||||
view.buffer.read(cx).read(cx).text(),
|
||||
"\n two\nthree\n four"
|
||||
);
|
||||
view.delete_to_next_word_end(&del_to_next_word_end, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "two\nthree\n four");
|
||||
view.delete_to_next_word_end(&del_to_next_word_end, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "\nthree\n four");
|
||||
view.delete_to_next_word_end(&del_to_next_word_end_ignore_newlines, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "\n four");
|
||||
view.delete_to_next_word_end(&del_to_next_word_end_ignore_newlines, cx);
|
||||
assert_eq!(view.buffer.read(cx).read(cx).text(), "");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_newline(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue