aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/movement.rs20
-rw-r--r--helix-core/src/search.rs4
-rw-r--r--helix-term/src/commands.rs11
-rw-r--r--helix-term/src/keymap.rs2
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,