stylish_stringlike/text/
replaceable.rs1use super::{Expandable, Pushable, RawText, Sliceable};
2use regex::Regex;
3pub trait Replaceable<T> {
7 fn replace(&self, from: &str, replacer: T) -> Self;
17 fn replace_regex(&self, searcher: &Regex, replacer: T) -> Self;
29}
30
31impl<'a, T> Replaceable<&'a T> for T
32where
33 T: Default + RawText + Sliceable + Pushable<T> + Expandable,
34{
35 fn replace(&self, from: &str, replacer: &'a T) -> Self {
36 let mut result: T = Default::default();
37 let mut last_end = 0;
38 for (start, part) in self.raw_ref().match_indices(from) {
39 eprintln!("start: {}, part: {}", start, part);
40 match self.slice(last_end..start) {
41 Some(slice) if !slice.raw_ref().is_empty() => {
42 result.push(&slice);
43 }
44 _ => {}
45 }
46 result.push(replacer);
47 last_end = start + part.len();
48 }
49 match self.slice(last_end..) {
50 Some(slice) if !slice.raw_ref().is_empty() => {
51 result.push(&slice);
52 }
53 _ => {}
54 }
55 result
56 }
57 fn replace_regex(&self, searcher: &Regex, replacer: &'a T) -> Self {
58 let mut result: T = Default::default();
59 let mut last_end = 0;
60 let captures = searcher.captures_iter(self.raw_ref());
61 for capture in captures {
62 let mat = capture
63 .get(0)
64 .expect("Captures are always supposed to have at least one match");
65 if let Some(slice) = self.slice(last_end..mat.start()) {
66 result.push(&slice);
67 if let Some(_original) = self.slice(mat.start()..mat.end()) {
68 let expanded = replacer.expand(&capture);
69 result.push(&expanded);
70 }
71 }
72 last_end = mat.end();
73 }
74 if let Some(spans) = self.slice(last_end..) {
75 result.push(&spans);
76 }
77 result
78 }
79}
80
81#[cfg(test)]
82mod test {
83 use super::*;
84 #[test]
85 fn test_string_replace() {
86 let foo = String::from("foo");
87 let bar = Replaceable::<&String>::replace(&foo, "foo", &String::from("bar"));
88 eprintln!("bar: {}", bar);
89 assert_eq!(bar, String::from("bar"));
90 }
91 #[test]
92 fn test_string_regex_replace() {
93 let foooo = String::from("foooo");
94 let re = Regex::new("fo+").unwrap();
95 let bar = Replaceable::<&String>::replace_regex(&foooo, &re, &String::from("bar"));
96 assert_eq!(bar, String::from("bar"));
97 }
98}