diff --git a/src/prompt/readline/linebuf.rs b/src/prompt/readline/linebuf.rs index 30422df..86ac357 100644 --- a/src/prompt/readline/linebuf.rs +++ b/src/prompt/readline/linebuf.rs @@ -2055,9 +2055,10 @@ impl LineBuf { } MotionCmd(_, Motion::BeginningOfFirstWord) => { let start = self.start_of_line(); - let mut indices = self.directional_indices_iter_from(start, Direction::Forward); + self.update_graphemes_lazy(); + let indices = self.grapheme_indices().to_vec(); let mut first_graphical = None; - while let Some(idx) = indices.next() { + for &idx in indices.iter().skip(start) { let grapheme = self.grapheme_at(idx).unwrap(); if !is_whitespace(grapheme) { first_graphical = Some(idx); diff --git a/src/tests/readline.rs b/src/tests/readline.rs index 268e171..f2fdaa6 100644 --- a/src/tests/readline.rs +++ b/src/tests/readline.rs @@ -174,6 +174,10 @@ impl LineWriter for TestWriter { fn flush_write(&mut self, _buf: &str) -> libsh::error::ShResult<()> { Ok(()) } + + fn send_bell(&mut self) -> ShResult<()> { + Ok(()) + } } // NOTE: FernVi structure has changed significantly and readline() method no @@ -598,6 +602,50 @@ fn editor_delete_line_up() { ) } +#[test] +fn editor_insert_at_line_start() { + // I should move cursor to position 0 when line starts with non-whitespace + assert_eq!( + normal_cmd("I", "hello world", 5), + ("hello world".into(), 0) + ); + // I should skip leading whitespace + assert_eq!( + normal_cmd("I", " hello world", 8), + (" hello world".into(), 2) + ); + // I should move to the first non-whitespace on the current line in a multiline buffer + assert_eq!( + normal_cmd("I", "first line\nsecond line", 14), + ("first line\nsecond line".into(), 11) + ); + // I should land on position 0 when cursor is already at 0 + assert_eq!( + normal_cmd("I", "hello", 0), + ("hello".into(), 0) + ); +} + +#[test] +fn editor_f_char_from_position_zero() { + // f at position 0 should skip the cursor and find the next occurrence + // Regression: previously at pos 0, f would match the char under the cursor itself + assert_eq!( + normal_cmd("fa", "abcaef", 0), + ("abcaef".into(), 3) // should find second 'a', not the 'a' at position 0 + ); + // f from position 0 finding a char that only appears later + assert_eq!( + normal_cmd("fo", "hello world", 0), + ("hello world".into(), 4) + ); + // f from middle of buffer + assert_eq!( + normal_cmd("fd", "hello world", 5), + ("hello world".into(), 10) + ); +} + // NOTE: These tests disabled because fernvi_test() helper is commented out /* #[test]