stache/
name.rs

1extern crate regex;
2
3use regex::Regex;
4use std::fmt;
5
6/// An identifier name generator.
7#[derive(Debug)]
8pub struct Name {
9    pub base: String,
10    next: usize,
11}
12
13impl Name {
14    /// Initialize a name generator with a base name. A unique identifier may
15    /// then be generated with the `next` and `to_string` functions.
16    pub fn new(base: &str) -> Self {
17        Name {
18            base: String::from(base),
19            next: 0,
20        }
21    }
22
23    /// Advances the generator to the next unique identifier. When passing
24    /// a `Name` through recursive function calls, this can be called before
25    /// the next recursion to increment the depth of the generated
26    /// identifiers.
27    pub fn next(&mut self) -> &mut Self {
28        self.next = self.next + 1;
29        self
30    }
31}
32
33impl Name {
34    /// Creates a valid identifier from the template's short name to be used
35    /// in function or variable names generated from this template file:
36    /// `include/header -> include_header`.
37    pub fn id(&self) -> String {
38        let re = Regex::new(r"[^\w]").unwrap();
39        re.replace_all(&self.base, "_")
40    }
41}
42
43impl fmt::Display for Name {
44    /// Creates a unique identifier to be used as a variable or function name.
45    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46        write!(f, "{}{}", self.id(), self.next)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::Name;
53
54    #[test]
55    fn id() {
56        let name = Name::new("include/header");
57        assert_eq!("include_header", name.id());
58    }
59
60    #[test]
61    fn next() {
62        let mut name = Name::new("include/header");
63        assert_eq!("include_header0", name.to_string());
64
65        name.next();
66        assert_eq!("include_header1", name.to_string());
67
68        name.next();
69        assert_eq!("include_header2", name.to_string());
70    }
71}