@@ -795,42 +795,50 @@ fn extend_to_line_start(cx: &mut Context) {
795795}
796796
797797fn kill_to_line_start(cx: &mut Context) {
798− delete_by_selection_insert_mode(cx, move |text, range| {
799− let line = range.cursor_line(text);
800− let first_char = text.line_to_char(line);
801− let anchor = range.cursor(text);
802− let head = if anchor == first_char && line != 0 {
803− // select until previous line
804− line_end_char_index(&text, line - 1)
805− } else if let Some(pos) = find_first_non_whitespace_char(text.line(line)) {
806− if first_char + pos < anchor {
807− // select until first non-blank in line if cursor is after it
808− first_char + pos
798+ delete_by_selection_insert_mode(
799+ cx,
800+ move |text, range| {
801+ let line = range.cursor_line(text);
802+ let first_char = text.line_to_char(line);
803+ let anchor = range.cursor(text);
804+ let head = if anchor == first_char && line != 0 {
805+ // select until previous line
806+ line_end_char_index(&text, line - 1)
807+ } else if let Some(pos) = find_first_non_whitespace_char(text.line(line)) {
808+ if first_char + pos < anchor {
809+ // select until first non-blank in line if cursor is after it
810+ first_char + pos
811+ } else {
812+ // select until start of line
813+ first_char
814+ }
809815 } else {
810816 // select until start of line
811817 first_char
812− }
813− } else {
814− // select until start of line
815− first_char
816− };
817− (head, anchor)
818− });
818+ };
819+ (head, anchor)
820+ },
821+ Direction::Backward,
822+ );
819823}
820824
821825fn kill_to_line_end(cx: &mut Context) {
822− delete_by_selection_insert_mode(cx, |text, range| {
823− let line = range.cursor_line(text);
824− let line_end_pos = line_end_char_index(&text, line);
825− let pos = range.cursor(text);
826+ delete_by_selection_insert_mode(
827+ cx,
828+ |text, range| {
829+ let line = range.cursor_line(text);
830+ let line_end_pos = line_end_char_index(&text, line);
831+ let pos = range.cursor(text);
826832
827− // if the cursor is on the newline char delete that
828− if pos == line_end_pos {
829− (pos, text.line_to_char(line + 1))
830− } else {
831− (pos, line_end_pos)
832− }
833− });
833+ // if the cursor is on the newline char delete that
834+ if pos == line_end_pos {
835+ (pos, text.line_to_char(line + 1))
836+ } else {
837+ (pos, line_end_pos)
838+ }
839+ },
840+ Direction::Forward,
841+ );
834842}
835843
836844fn goto_first_nonwhitespace(cx: &mut Context) {
@@ -2322,13 +2330,44 @@ fn delete_selection_impl(cx: &mut Context, op: Operation) {
23222330fn delete_by_selection_insert_mode(
23232331 cx: &mut Context,
23242332 mut f: impl FnMut(RopeSlice, &Range) -> Deletion,
2333+ direction: Direction,
23252334) {
23262335 let (view, doc) = current!(cx.editor);
23272336 let text = doc.text().slice(..);
2328− let transaction =
2337+ let mut selection = SmallVec::new();
2338+ let mut insert_newline = false;
2339+ let text_len = text.len_chars();
2340+ let mut transaction =
23292341 Transaction::delete_by_selection(doc.text(), doc.selection(view.id), |range| {
2330− f(text, range)
2342+ let (start, end) = f(text, range);
2343+ if direction == Direction::Forward {
2344+ let mut range = *range;
2345+ if range.head > range.anchor {
2346+ insert_newline |= end == text_len;
2347+ // move the cursor to the right so that the selection
2348+ // doesn't shrink when deleting forward (so the text appears to
2349+ // move to left)
2350+ // += 1 is enough here as the range is normalized to grapheme boundaries
2351+ // later anyway
2352+ range.head += 1;
2353+ }
2354+ selection.push(range);
2355+ }
2356+ (start, end)
23312357 });
2358+
2359+ // in case we delete the last character and the cursor would be moved to the EOF char
2360+ // insert a newline, just like when entering append mode
2361+ if insert_newline {
2362+ transaction = transaction.insert_at_eof(doc.line_ending.as_str().into());
2363+ }
2364+
2365+ if direction == Direction::Forward {
2366+ doc.set_selection(
2367+ view.id,
2368+ Selection::new(selection, doc.selection(view.id).primary_index()),
2369+ );
2370+ }
23322371 doc.apply(&transaction, view.id);
23332372 lsp::signature_help_impl(cx, SignatureHelpInvoked::Automatic);
23342373}
@@ -3490,28 +3529,40 @@ pub mod insert {
34903529
34913530 pub fn delete_char_forward(cx: &mut Context) {
34923531 let count = cx.count();
3493− delete_by_selection_insert_mode(cx, |text, range| {
3494− let pos = range.cursor(text);
3495− (pos, graphemes::nth_next_grapheme_boundary(text, pos, count))
3496− })
3532+ delete_by_selection_insert_mode(
3533+ cx,
3534+ |text, range| {
3535+ let pos = range.cursor(text);
3536+ (pos, graphemes::nth_next_grapheme_boundary(text, pos, count))
3537+ },
3538+ Direction::Forward,
3539+ )
34973540 }
34983541
34993542 pub fn delete_word_backward(cx: &mut Context) {
35003543 let count = cx.count();
3501− delete_by_selection_insert_mode(cx, |text, range| {
3502− let anchor = movement::move_prev_word_start(text, *range, count).from();
3503− let next = Range::new(anchor, range.cursor(text));
3504− let range = exclude_cursor(text, next, *range);
3505− (range.from(), range.to())
3506− });
3544+ delete_by_selection_insert_mode(
3545+ cx,
3546+ |text, range| {
3547+ let anchor = movement::move_prev_word_start(text, *range, count).from();
3548+ let next = Range::new(anchor, range.cursor(text));
3549+ let range = exclude_cursor(text, next, *range);
3550+ (range.from(), range.to())
3551+ },
3552+ Direction::Backward,
3553+ );
35073554 }
35083555
35093556 pub fn delete_word_forward(cx: &mut Context) {
35103557 let count = cx.count();
3511− delete_by_selection_insert_mode(cx, |text, range| {
3512− let head = movement::move_next_word_end(text, *range, count).to();
3513− (range.cursor(text), head)
3514− });
3558+ delete_by_selection_insert_mode(
3559+ cx,
3560+ |text, range| {
3561+ let head = movement::move_next_word_end(text, *range, count).to();
3562+ (range.cursor(text), head)
3563+ },
3564+ Direction::Forward,
3565+ );
35153566 }
35163567}
35173568