title_case/
lib.rs

1pub fn ignore(c: char) -> bool {
2  c.is_whitespace() || "`!?.;。".contains(c)
3}
4
5pub fn split(input: &str) -> Vec<String> {
6  let mut result = Vec::new();
7  let mut word = String::new();
8  let mut whitespace = String::new();
9
10  for c in input.chars() {
11    if ignore(c) {
12      if !word.is_empty() {
13        result.push(word.clone());
14        word.clear();
15      }
16      whitespace.push(c);
17    } else {
18      if !whitespace.is_empty() {
19        result.push(whitespace.clone());
20        whitespace.clear();
21      }
22      word.push(c);
23    }
24  }
25
26  if !word.is_empty() {
27    result.push(word);
28  } else if !whitespace.is_empty() {
29    result.push(whitespace);
30  }
31
32  result
33}
34
35pub fn title_case(now: impl AsRef<str>, pre: impl AsRef<str>) -> String {
36  let now = now.as_ref();
37  let pre = pre.as_ref();
38  let mut case = std::collections::HashMap::new();
39  for i in split(pre) {
40    if !ignore(i.chars().next().unwrap()) {
41      case.insert(i.to_lowercase(), i);
42    }
43  }
44
45  let now = titlecase::titlecase(now);
46  let li = split(&now);
47  let mut t = Vec::with_capacity(li.len());
48  for i in li {
49    if ignore(i.chars().next().unwrap()) {
50      t.push(i)
51    } else if let Some(i) = case.get(&i.to_lowercase()) {
52      t.push(i.clone());
53    } else {
54      t.push(i);
55    }
56  }
57
58  t.join("")
59}