diff options
-rw-r--r-- | helix-core/src/movement.rs | 20 | ||||
-rw-r--r-- | helix-core/src/search.rs | 4 | ||||
-rw-r--r-- | helix-term/src/commands.rs | 11 | ||||
-rw-r--r-- | helix-term/src/keymap.rs | 2 |
4 files changed, 25 insertions, 12 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs index ba2e92b9..387b59b1 100644 --- a/helix-core/src/movement.rs +++ b/helix-core/src/movement.rs @@ -45,7 +45,7 @@ pub fn move_vertically( let new_line = match dir { Direction::Backward => row.saturating_sub(count), - Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 1), + Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 2), }; // convert to 0-indexed, subtract another 1 because len_chars() counts \n @@ -76,8 +76,9 @@ pub fn move_next_word_start(slice: RopeSlice, mut begin: usize, count: usize) -> begin += 1; } - // return if not skip while? - skip_over_next(slice, &mut begin, |ch| ch == '\n'); + if !skip_over_next(slice, &mut begin, |ch| ch == '\n') { + return None; + }; ch = slice.char(begin); end = begin + 1; @@ -134,7 +135,7 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O let mut end = begin; for _ in 0..count { - if begin + 1 == slice.len_chars() { + if begin + 2 >= slice.len_chars() { return None; } @@ -145,8 +146,9 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O begin += 1; } - // return if not skip while? - skip_over_next(slice, &mut begin, |ch| ch == '\n'); + if !skip_over_next(slice, &mut begin, |ch| ch == '\n') { + return None; + }; end = begin; @@ -199,18 +201,20 @@ fn categorize(ch: char) -> Category { } #[inline] -pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F) +/// Returns true if there are more characters left after the new position. +pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F) -> bool where F: Fn(char) -> bool, { let mut chars = slice.chars_at(*pos); - for ch in chars { + while let Some(ch) = chars.next() { if !fun(ch) { break; } *pos += 1; } + chars.next().is_some() } #[inline] diff --git a/helix-core/src/search.rs b/helix-core/src/search.rs index af754ab7..55f7bf1d 100644 --- a/helix-core/src/search.rs +++ b/helix-core/src/search.rs @@ -7,6 +7,10 @@ pub fn find_nth_next( n: usize, inclusive: bool, ) -> Option<usize> { + if pos >= text.len_chars() { + return None; + } + // start searching right after pos let mut chars = text.chars_at(pos + 1); diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 3dba9333..7b30168a 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -473,10 +473,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) { let last_line = view.last_line(doc); // clamp into viewport - let line = cursor.row.clamp( - view.first_line + scrolloff, - last_line.saturating_sub(scrolloff), - ); + let line = cursor + .row + .min(view.first_line + scrolloff) + .max(last_line.saturating_sub(scrolloff)); let text = doc.text().slice(..); let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end @@ -1031,6 +1031,9 @@ pub fn command_mode(cx: &mut Context) { } let parts = input.split_ascii_whitespace().collect::<Vec<&str>>(); + if parts.is_empty() { + return; + } if let Some(cmd) = cmd::COMMANDS.get(parts[0]) { (cmd.fun)(editor, &parts[1..], event); diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 044d97eb..fc7bb86e 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -240,10 +240,12 @@ pub fn default() -> Keymaps { code: KeyCode::PageUp, modifiers: KeyModifiers::NONE } => commands::page_up, + ctrl!('b') => commands::page_up, KeyEvent { code: KeyCode::PageDown, modifiers: KeyModifiers::NONE } => commands::page_down, + ctrl!('f') => commands::page_down, ctrl!('u') => commands::half_page_up, ctrl!('d') => commands::half_page_down, |