Skip to content

Commit

Permalink
Jump to the next number on the line before incrementing
Browse files Browse the repository at this point in the history
Partially fix #1645
  • Loading branch information
antoyo committed Mar 9, 2022
1 parent bfa533f commit 82ead06
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 5 deletions.
49 changes: 49 additions & 0 deletions helix-core/src/search.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
use crate::RopeSlice;

// TODO: switch to std::str::Pattern when it is stable.
pub trait CharMatcher {
fn char_match(&self, ch: char) -> bool;
}

impl CharMatcher for char {
fn char_match(&self, ch: char) -> bool {
*self == ch
}
}

impl<F: Fn(&char) -> bool> CharMatcher for F {
fn char_match(&self, ch: char) -> bool {
(*self)(&ch)
}
}

pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
if pos >= text.len_chars() || n == 0 {
return None;
Expand All @@ -22,6 +39,38 @@ pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Opt
Some(pos - 1)
}

/// Like find_nth_next, but stops at the first newline character.
pub fn find_nth_next_until_newline<M: CharMatcher>(
text: RopeSlice,
char_matcher: M,
mut pos: usize,
n: usize,
) -> Option<usize> {
if pos >= text.len_chars() || n == 0 {
return None;
}

let mut chars = text.chars_at(pos);

for _ in 0..n {
loop {
let c = chars.next()?;

pos += 1;

if c == '\n' || c == '\r' {
return None;
}

if char_matcher.char_match(c) {
break;
}
}
}

Some(pos - 1)
}

pub fn find_nth_prev(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
if pos == 0 || n == 0 {
return None;
Expand Down
36 changes: 31 additions & 5 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use helix_core::{
movement::{self, Direction},
object, pos_at_coords,
regex::{self, Regex, RegexBuilder},
search, selection, shellwords, surround, textobject,
search::{self, CharMatcher},
selection, shellwords, surround, textobject,
tree_sitter::Node,
unicode::width::UnicodeWidthChar,
LineEnding, Position, Range, Rope, RopeGraphemes, RopeSlice, Selection, SmallVec, Tendril,
Expand Down Expand Up @@ -1072,15 +1073,15 @@ where
//

#[inline]
fn find_char_impl<F>(
fn find_char_impl<F, M: CharMatcher + Clone + Copy>(
editor: &mut Editor,
search_fn: &F,
inclusive: bool,
extend: bool,
ch: char,
char_matcher: M,
count: usize,
) where
F: Fn(RopeSlice, char, usize, usize, bool) -> Option<usize> + 'static,
F: Fn(RopeSlice, M, usize, usize, bool) -> Option<usize> + 'static,
{
let (view, doc) = current!(editor);
let text = doc.text().slice(..);
Expand All @@ -1095,7 +1096,7 @@ fn find_char_impl<F>(
range.head
};

search_fn(text, ch, search_start_pos, count, inclusive).map_or(range, |pos| {
search_fn(text, char_matcher, search_start_pos, count, inclusive).map_or(range, |pos| {
if extend {
range.put_cursor(text, pos, true)
} else {
Expand Down Expand Up @@ -4331,8 +4332,33 @@ fn decrement(cx: &mut Context) {
increment_impl(cx, -(cx.count() as i64));
}

/// This function differs from find_next_char_impl in that it stops searching at the newline, but also
/// starts searching at the current character, instead of the next.
/// It does not want to start at the next character because this function is used for incrementing
/// number and we don't want to move forward if we're already on a digit.
fn find_next_char_until_newline<M: CharMatcher>(
text: RopeSlice,
char_matcher: M,
pos: usize,
n: usize,
_inclusive: bool,
) -> Option<usize> {
search::find_nth_next_until_newline(text, char_matcher, pos, n)
}

/// Decrement object under cursor by `amount`.
fn increment_impl(cx: &mut Context, amount: i64) {
// TODO: when incrementing or decrementing a number that gets a new digit or lose one, the
// selection is updated improperly.
find_char_impl(
cx.editor,
&find_next_char_until_newline,
true,
true,
char::is_ascii_digit,
1,
);

let (view, doc) = current!(cx.editor);
let selection = doc.selection(view.id);
let text = doc.text().slice(..);
Expand Down

0 comments on commit 82ead06

Please sign in to comment.