From 1d2eaf210a15bc6c67de60696caaf08f4be9c1c6 Mon Sep 17 00:00:00 2001 From: smit Date: Thu, 14 Aug 2025 02:48:20 +0530 Subject: [PATCH] editor: Fix first `cmd-left` target for cursor in leading whitespace (#36145) Closes #35805 If the cursor is between column 0 and the indent size, pressing `cmd-left` jumps to the indent. Pressing it again moves to the true column 0. Further presses toggle between indent and column 0. This PR changes the first `cmd-left` to go to column 0 instead of indent. Toggling between is unaffected. Release Notes: - Fixed issue where pressing `cmd-left` with the cursor in the leading spaces moved to the start of the text first. It now goes to the beginning of the line first, then the start of the text. --- crates/editor/src/editor_tests.rs | 45 +++++++++++++++++++++++++++++++ crates/editor/src/movement.rs | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 0d2ecec8f2..4421869703 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -1901,6 +1901,51 @@ fn test_beginning_of_line_stop_at_indent(cx: &mut TestAppContext) { }); } +#[gpui::test] +fn test_beginning_of_line_with_cursor_between_line_start_and_indent(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let move_to_beg = MoveToBeginningOfLine { + stop_at_soft_wraps: true, + stop_at_indent: true, + }; + + let editor = cx.add_window(|window, cx| { + let buffer = MultiBuffer::build_simple(" hello\nworld", cx); + build_editor(buffer, window, cx) + }); + + _ = editor.update(cx, |editor, window, cx| { + // test cursor between line_start and indent_start + editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { + s.select_display_ranges([ + DisplayPoint::new(DisplayRow(0), 3)..DisplayPoint::new(DisplayRow(0), 3) + ]); + }); + + // cursor should move to line_start + 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)] + ); + + // cursor should move to indent_start + editor.move_to_beginning_of_line(&move_to_beg, window, cx); + assert_eq!( + editor.selections.display_ranges(cx), + &[DisplayPoint::new(DisplayRow(0), 4)..DisplayPoint::new(DisplayRow(0), 4)] + ); + + // cursor should move to back to line_start + 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)] + ); + }); +} + #[gpui::test] fn test_prev_next_word_boundary(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index a8850984a1..fdda0e82bc 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -230,7 +230,7 @@ pub fn indented_line_beginning( if stop_at_soft_boundaries && soft_line_start > indent_start && display_point != soft_line_start { soft_line_start - } else if stop_at_indent && display_point != indent_start { + } else if stop_at_indent && (display_point > indent_start || display_point == line_start) { indent_start } else { line_start