Skip to main content

speccoder_core/
words.rs

1//! Lists and names in a sentence.
2
3/// `a`, `a and b`, `a, b and c`.
4#[must_use]
5pub fn listed<S: AsRef<str>>(items: &[S]) -> String {
6    match items {
7        [] => String::new(),
8        [one] => one.as_ref().to_owned(),
9        [rest @ .., last] => format!(
10            "{} and {}",
11            rest.iter()
12                .map(AsRef::as_ref)
13                .collect::<Vec<_>>()
14                .join(", "),
15            last.as_ref()
16        ),
17    }
18}
19
20/// A slug as a title: `empty-title` → `Empty title`.
21#[must_use]
22pub fn titled(slug: &str) -> String {
23    let words = slug.replace(['-', '_'], " ");
24    let mut c = words.chars();
25    c.next()
26        .map(|f| f.to_uppercase().chain(c).collect())
27        .unwrap_or_default()
28}
29
30#[cfg(test)]
31mod tests {
32    use super::{listed, titled};
33
34    #[test]
35    fn a_slug_reads_as_a_title() {
36        assert_eq!(titled("empty-title"), "Empty title");
37        assert_eq!(titled(""), "");
38    }
39
40    #[test]
41    fn lists_read_as_a_sentence() {
42        assert_eq!(listed::<&str>(&[]), "");
43        assert_eq!(listed(&["a"]), "a");
44        assert_eq!(listed(&["a", "b"]), "a and b");
45        assert_eq!(listed(&["a", "b", "c"]), "a, b and c");
46    }
47}