pub fn split_into_lines(input: String, limit: usize) -> Vec<String> {
let mut output: Vec<String> = vec![];
let mut cur_line: Vec<char> = vec![];
let mut cur_line_len: usize = 0;
input.trim()
.replace("\n", " &#LF#&!")
.split(" ")
.for_each(|space_separated| {
let mut space_separated: String = space_separated.to_string();
if cur_line_len == limit || cur_line_len + 1 == limit {
output.push(cur_line.clone().into_iter().collect());
cur_line.clear();
cur_line_len = 0;
}
if space_separated.starts_with("&#LF#&!") {
if cur_line_len > 0 {
output.push(cur_line.clone().into_iter().collect());
cur_line.clear();
cur_line_len = 0;
}else {
output.push("".to_string());
}
space_separated = space_separated.replace("&#LF#&!", "");
}
let len_of_space_separated = len_of_chars(&space_separated);
if len_of_space_separated == 0 {
return;
}
if len_of_space_separated + cur_line_len < limit {
if cur_line_len > 0 {
cur_line.push(' ');
cur_line_len += 1;
}
cur_line.extend(space_separated.chars());
cur_line_len += len_of_space_separated;
} else {
if cur_line_len < limit && cur_line_len > 0 {
output.push(cur_line.clone().into_iter().collect());
cur_line.clear();
cur_line_len = 0;
}
space_separated.chars().for_each(|ch| {
match ch {
'\u{4E00}'..='\u{9FCC}'
| '\u{3400}'..='\u{4DB5}'
| '\u{20000}'..='\u{2A6D6}'
| '\u{2A700}'..='\u{2B734}'
| '\u{2B740}'..='\u{2B81D}' => {
cur_line_len += 2;
}
_ => {
cur_line_len += 1;
}
}
cur_line.push(ch);
if cur_line_len == limit || cur_line_len == limit - 1 {
output.push(cur_line.clone().into_iter().collect());
cur_line.clear();
cur_line_len = 0;
}
});
}
});
if cur_line_len > 0 {
output.push(cur_line.into_iter().collect());
}
output
}
pub fn len_of_chars(input: &str) -> usize {
let mut size = 0;
input.chars().for_each(|ch| {
match ch {
'\u{4E00}'..='\u{9FCC}'
| '\u{3400}'..='\u{4DB5}'
| '\u{20000}'..='\u{2A6D6}'
| '\u{2A700}'..='\u{2B734}'
| '\u{2B740}'..='\u{2B81D}' => {
size += 2;
}
_ => {
size += 1;
}
}
});
size
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_split_into_lines() {
let input = String::from("This is a long line. ".repeat(10));
assert_eq!(split_into_lines(input, 80).len(), 3);
let input = String::from("这是一段很长的介绍\n".repeat(10));
println!("{:?}", split_into_lines(input, 71));
}
}