@@ -253,6 +253,15 @@ pub struct DeleteToPreviousWordStart {
pub ignore_brackets: bool,
}
+/// Cuts from cursor to end of line.
+#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema, Action)]
+#[action(namespace = editor)]
+#[serde(deny_unknown_fields)]
+pub struct CutToEndOfLine {
+ #[serde(default)]
+ pub stop_at_newlines: bool,
+}
+
/// Folds all code blocks at the specified indentation level.
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema, Action)]
#[action(namespace = editor)]
@@ -412,8 +421,6 @@ actions!(
CopyPermalinkToLine,
/// Cuts selected text to the clipboard.
Cut,
- /// Cuts from cursor to end of line.
- CutToEndOfLine,
/// Deletes the character after the cursor.
Delete,
/// Deletes the current line.
@@ -12249,7 +12249,12 @@ impl Editor {
.update(cx, |buffer, cx| buffer.edit(edits, None, cx));
}
- pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
+ pub fn cut_common(
+ &mut self,
+ cut_no_selection_line: bool,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> ClipboardItem {
let mut text = String::new();
let buffer = self.buffer.read(cx).snapshot(cx);
let mut selections = self.selections.all::<Point>(cx);
@@ -12258,7 +12263,8 @@ impl Editor {
let max_point = buffer.max_point();
let mut is_first = true;
for selection in &mut selections {
- let is_entire_line = selection.is_empty() || self.selections.line_mode;
+ let is_entire_line =
+ (selection.is_empty() && cut_no_selection_line) || self.selections.line_mode;
if is_entire_line {
selection.start = Point::new(selection.start.row, 0);
if !selection.is_empty() && selection.end.column == 0 {
@@ -12299,7 +12305,7 @@ impl Editor {
pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
- let item = self.cut_common(window, cx);
+ let item = self.cut_common(true, window, cx);
cx.write_to_clipboard(item);
}
@@ -12308,11 +12314,14 @@ impl Editor {
self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
s.move_with(|snapshot, sel| {
if sel.is_empty() {
- sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
+ sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()));
+ }
+ if sel.is_empty() {
+ sel.end = DisplayPoint::new(sel.end.row() + 1_u32, 0);
}
});
});
- let item = self.cut_common(window, cx);
+ let item = self.cut_common(true, window, cx);
cx.set_global(KillRing(item))
}
@@ -13474,7 +13483,7 @@ impl Editor {
pub fn cut_to_end_of_line(
&mut self,
- _: &CutToEndOfLine,
+ action: &CutToEndOfLine,
window: &mut Window,
cx: &mut Context<Self>,
) {
@@ -13487,7 +13496,18 @@ impl Editor {
window,
cx,
);
- this.cut(&Cut, window, cx);
+ if !action.stop_at_newlines {
+ this.change_selections(Default::default(), window, cx, |s| {
+ s.move_with(|_, sel| {
+ if sel.is_empty() {
+ sel.end = DisplayPoint::new(sel.end.row() + 1_u32, 0);
+ }
+ });
+ });
+ }
+ this.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
+ let item = this.cut_common(false, window, cx);
+ cx.write_to_clipboard(item);
});
}
@@ -6730,6 +6730,58 @@ async fn test_hard_wrap(cx: &mut TestAppContext) {
));
}
+#[gpui::test]
+async fn test_cut_line_ends(cx: &mut TestAppContext) {
+ init_test(cx, |_| {});
+
+ let mut cx = EditorTestContext::new(cx).await;
+
+ cx.set_state(indoc! {"
+ The quick« brownˇ»
+ fox jumps overˇ
+ the lazy dog"});
+ cx.update_editor(|e, window, cx| e.cut(&Cut, window, cx));
+ cx.assert_editor_state(indoc! {"
+ The quickˇ
+ ˇthe lazy dog"});
+
+ cx.set_state(indoc! {"
+ The quick« brownˇ»
+ fox jumps overˇ
+ the lazy dog"});
+ cx.update_editor(|e, window, cx| e.cut_to_end_of_line(&CutToEndOfLine::default(), window, cx));
+ cx.assert_editor_state(indoc! {"
+ The quickˇ
+ fox jumps overˇthe lazy dog"});
+
+ cx.set_state(indoc! {"
+ The quick« brownˇ»
+ fox jumps overˇ
+ the lazy dog"});
+ cx.update_editor(|e, window, cx| {
+ e.cut_to_end_of_line(
+ &CutToEndOfLine {
+ stop_at_newlines: true,
+ },
+ window,
+ cx,
+ )
+ });
+ cx.assert_editor_state(indoc! {"
+ The quickˇ
+ fox jumps overˇ
+ the lazy dog"});
+
+ cx.set_state(indoc! {"
+ The quick« brownˇ»
+ fox jumps overˇ
+ the lazy dog"});
+ cx.update_editor(|e, window, cx| e.kill_ring_cut(&KillRingCut, window, cx));
+ cx.assert_editor_state(indoc! {"
+ The quickˇ
+ fox jumps overˇthe lazy dog"});
+}
+
#[gpui::test]
async fn test_clipboard(cx: &mut TestAppContext) {
init_test(cx, |_| {});