1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use std::fmt::Write; pub mod repl; #[derive(Debug, Clone)] pub struct MessageTemplate { text: String } impl MessageTemplate { pub fn new<T: Into<String>>(text: T) -> MessageTemplate { MessageTemplate { text: text.into() } } pub fn from_format(s: &str, names: &[&str]) -> MessageTemplate { let mut template = "".to_owned(); let mut next_name = 0; let mut first = true; for literal in s.split("{}") { if !first { if names.len() > next_name { write!(&mut template, "{{{}}}", names[next_name]).is_ok(); } else { write!(&mut template, "{{{}}}", next_name).is_ok(); } next_name += 1; } template.push_str(literal); first = false; } Self::new(template) } pub fn text(&self) -> &String { &self.text } pub fn parse<'a>(&'a self) -> repl::MessageTemplateRepl<'a> { repl::MessageTemplateRepl::new(&self.text) } } #[cfg(test)] mod tests { use templates::MessageTemplate; #[test] fn templates_without_parameters_are_built() { let names: Vec<&str> = vec![]; let s = "Hello, world!"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), s); } #[test] fn templates_with_parameters_are_built() { let names = vec!["A", "B"]; let s = "C {} D {} E"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), "C {A} D {B} E"); } #[test] fn additional_names_are_ignored() { let names = vec!["A", "B"]; let s = "C {} D"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), "C {A} D"); } #[test] fn additional_holes_are_indexed() { let names = vec!["A"]; let s = "C {} D {} E"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), "C {A} D {1} E"); } #[test] fn leading_holes_are_handled() { let names = vec!["A"]; let s = "{} D"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), "{A} D"); } #[test] fn trailing_holes_are_handled() { let names = vec!["A"]; let s = "C {}"; let built = MessageTemplate::from_format(s, &names); assert_eq!(built.text(), "C {A}"); } }