markdown_formatter/args/
split.rs

1pub fn split_into_lines(input: String, limit: usize) -> Vec<String> {
2    let mut output: Vec<String> = vec![];
3    let mut cur_line: Vec<char> = vec![];
4    let mut cur_line_len: usize = 0;
5    input.trim()
6        .replace("\n", " &#LF#&!")
7        .split(" ")
8        .for_each(|space_separated| {
9            let mut space_separated: String = space_separated.to_string();
10            if cur_line_len == limit || cur_line_len + 1 == limit {
11                // 长度足够一行,提交
12                output.push(cur_line.clone().into_iter().collect());
13                cur_line.clear();
14                cur_line_len = 0;
15            }
16            if space_separated.starts_with("&#LF#&!") {
17                if cur_line_len > 0 {
18                    output.push(cur_line.clone().into_iter().collect());
19                    cur_line.clear();
20                    cur_line_len = 0;
21                }else {
22                    output.push("".to_string());
23                }
24                space_separated = space_separated.replace("&#LF#&!", "");
25            }
26            let len_of_space_separated = len_of_chars(&space_separated);
27            if len_of_space_separated == 0 {
28                return;
29            }
30            if len_of_space_separated + cur_line_len < limit {
31                // 加入也不会超长,直接放入
32                if cur_line_len > 0 {
33                    // 当前已经记录的字符不为空时才需要空格
34                    cur_line.push(' ');
35                    cur_line_len += 1;
36                }
37                cur_line.extend(space_separated.chars());
38                cur_line_len += len_of_space_separated;
39            } else {
40                // 加入超长,需要判断
41                if cur_line_len < limit && cur_line_len > 0 {
42                    // 全部放入长度也没有超,先提交现有的
43                    output.push(cur_line.clone().into_iter().collect());
44                    cur_line.clear();
45                    cur_line_len = 0;
46                }
47
48                space_separated.chars().for_each(|ch| {
49                    match ch {
50                        '\u{4E00}'..='\u{9FCC}'
51                        | '\u{3400}'..='\u{4DB5}'
52                        | '\u{20000}'..='\u{2A6D6}'
53                        | '\u{2A700}'..='\u{2B734}'
54                        | '\u{2B740}'..='\u{2B81D}' => {
55                            // CJK,每个字符占两个位置
56                            cur_line_len += 2;
57                        }
58                        _ => {
59                            cur_line_len += 1;
60                        }
61                    }
62                    // 一个一个字符放入
63                    cur_line.push(ch);
64                    if cur_line_len == limit || cur_line_len == limit - 1 {
65                        // 长度足够一行,提交
66                        output.push(cur_line.clone().into_iter().collect());
67                        cur_line.clear();
68                        cur_line_len = 0;
69                    }
70                });
71            }
72        });
73
74    if cur_line_len > 0 {
75        output.push(cur_line.into_iter().collect());
76    }
77
78    output
79}
80
81pub fn len_of_chars(input: &str) -> usize {
82    let mut size = 0;
83    input.chars().for_each(|ch| {
84        match ch {
85            '\u{4E00}'..='\u{9FCC}'
86            | '\u{3400}'..='\u{4DB5}'
87            | '\u{20000}'..='\u{2A6D6}'
88            | '\u{2A700}'..='\u{2B734}'
89            | '\u{2B740}'..='\u{2B81D}' => {
90                // CJK,每个字符占两个位置
91                size += 2;
92            }
93            _ => {
94                size += 1;
95            }
96        }
97    });
98    size
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    fn test_split_into_lines() {
107        let input = String::from("This is a long line. ".repeat(10));
108        assert_eq!(split_into_lines(input, 80).len(), 3);
109
110        let input = String::from("这是一段很长的介绍\n".repeat(10));
111        println!("{:?}", split_into_lines(input, 71));
112        // assert_eq!(split_into_lines(input, 80).len(), 3);
113    }
114}