Repository: helix-editor/helix
File: helix-term/src/commands.rs (Rust)

Code before:
    let decrease_by = -get_increase_by_value(cx);
    increment_impl(cx, -(cx.count() as i64), decrease_by);
}

/// 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,
    _count: usize,
    _inclusive: bool,
) -> Option<usize> {
    // Since we send the current line to find_nth_next instead of the whole text, we need to adjust
    // the position we send to this function so that it's relative to that line and its returned
    // position since it's expected this function returns a global position.
    let line_index = text.char_to_line(pos);
    let pos_delta = text.line_to_char(line_index);
    let pos = pos - pos_delta;
    search::find_nth_next(text.line(line_index), char_matcher, pos, 1).map(|pos| pos + pos_delta)
}

/// Decrement object under cursor by `amount`.
fn increment_impl(cx: &mut Context, amount: i64, increase_by: 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(..);

    let mut amount = amount;
    let changes: Vec<_> = selection
        .ranges()
        .iter()
        .filter_map(|range| {
            let incrementor: Box<dyn Increment> =
                if let Some(incrementor) = DateTimeIncrementor::from_range(text, *range) {
                    Box::new(incrementor)
                } else if let Some(incrementor) = NumberIncrementor::from_range(text, *range) {
                    Box::new(incrementor)

Review comment (suggestion):
Instead of passing amounts to `increase_impl`, we can create an enum

```rust
enum IncrementDirection {
    Increase,
    Decrease,
}
```

And pass that to `increment_impl`, then check the `cx.count` and `cx.register` in the body of `increment_impl` and then decide whether to use a positive or negative amount based on the passed direction.

Code after:
    text: RopeSlice,
    char_matcher: M,
    pos: usize,
    _count: usize,
    _inclusive: bool,
) -> Option<usize> {
    // Since we send the current line to find_nth_next instead of the whole text, we need to adjust
    // the position we send to this function so that it's relative to that line and its returned
    // position since it's expected this function returns a global position.
    let line_index = text.char_to_line(pos);
    let pos_delta = text.line_to_char(line_index);
    let pos = pos - pos_delta;
    search::find_nth_next(text.line(line_index), char_matcher, pos, 1).map(|pos| pos + pos_delta)
}

/// Decrement object under cursor by `amount`.
fn increment_impl(cx: &mut Context, increment_direction: IncrementDirection) {
    // 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,
    );

    // Increase by 1 if `IncrementDirection` is `Increase`
    // Decrease by 1 if `IncrementDirection` is `Decrease`
    let sign = match increment_direction {
        IncrementDirection::Increase => 1,
        IncrementDirection::Decrease => -1,
    };
    let mut amount = sign * cx.count() as i64;

    // If the register is `#` then increase or decrease the `amount` by 1 per element
    let increase_by = if cx.register == Some('#') { sign } else { 0 };

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

    let changes: Vec<_> = selection
        .ranges()
        .iter()
        .filter_map(|range| {
            let incrementor: Box<dyn Increment> =
                if let Some(incrementor) = DateTimeIncrementor::from_range(text, *range) {
                    Box::new(incrementor)
                } else if let Some(incrementor) = NumberIncrementor::from_range(text, *range) {