aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/words.rs
blob: 7ecdacba3edd734fe9015a86921e8b5cb6abf9fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use crate::movement::{categorize, is_punctuation, is_word, skip_over_prev};
use ropey::RopeSlice;

#[must_use]
pub fn nth_prev_word_boundary(slice: RopeSlice, mut char_idx: usize, count: usize) -> usize {
    let mut with_end = false;

    for _ in 0..count {
        if char_idx == 0 {
            break;
        }

        // return if not skip while?
        skip_over_prev(slice, &mut char_idx, |ch| ch == '\n');

        with_end = skip_over_prev(slice, &mut char_idx, char::is_whitespace);

        // refetch
        let ch = slice.char(char_idx);

        if is_word(ch) {
            with_end = skip_over_prev(slice, &mut char_idx, is_word);
        } else if is_punctuation(ch) {
            with_end = skip_over_prev(slice, &mut char_idx, is_punctuation);
        }
    }

    if with_end || char_idx == 0 {
        char_idx
    } else {
        char_idx + 1
    }
}

#[test]
fn different_prev_word_boundary() {
    use ropey::Rope;
    let t = |x, y| {
        let text = Rope::from(x);
        let out = nth_prev_word_boundary(text.slice(..), text.len_chars().saturating_sub(1), 1);
        assert_eq!(text.slice(..out), y, r#"from "{}""#, x);
    };
    t("abcd\nefg\nwrs", "abcd\nefg\n");
    t("abcd\nefg\n", "abcd\n");
    t("abcd\n", "");
    t("hello, world!", "hello, world");
    t("hello, world", "hello, ");
    t("hello, ", "hello");
    t("hello", "");
    t(",", "");
    t("こんにちは、世界!", "こんにちは、世界");
    t("こんにちは、世界", "こんにちは、");
    t("こんにちは、", "こんにちは");
    t("こんにちは", "");
    t("この世界。", "この世界");
    t("この世界", "");
    t("お前はもう死んでいる", "");
    t("その300円です", ""); // TODO: should stop at 300
    t("唱k", ""); // TODO: should stop at 唱
    t(",", "");
    t("1 + 1 = 2", "1 + 1 = ");
    t("1 + 1 =", "1 + 1 ");
    t("1 + 1", "1 + ");
    t("1 + ", "1 ");
    t("1 ", "");
    t("1+1=2", "1+1=");
    t("", "");
}