A rust macro that allows regular expression creation through independent files. Allows fully typed named groups.
added captures and captures iter
3 files changed, +51 -5
+1-0.cargo/config.toml
| @@ -3,3 +3,4 @@ e = "run --example" | ||
| 3 | 3 | b = "build" |
| 4 | 4 | t = "test --tests" |
| 5 | 5 | p = "publish" |
| 6 | +tn = "test --tests -- --nocapture" |
+28-5src/lib.rs
| @@ -118,12 +118,36 @@ pub fn load_regex_files(input: TokenStream) -> TokenStream { | ||
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | impl #ident { |
| 121 | + /// Gets the raw captures | |
| 122 | + pub fn captures(text:&str) -> Option<regex::Captures<'_>> { | |
| 123 | + let re = &RE.#ident; | |
| 124 | + re.captures(text) | |
| 125 | + } | |
| 126 | + | |
| 127 | + /// Gets the raw captures from the contents of a file | |
| 128 | + pub fn captures_from_file<'a>(buffer: &'a mut String, filename: &str) -> Result<Option<regex::Captures<'a>>, std::io::Error> { | |
| 129 | + buffer.clear(); | |
| 130 | + buffer.push_str(&std::fs::read_to_string(filename)?); | |
| 131 | + Ok(Self::captures(buffer)) | |
| 132 | + } | |
| 133 | + | |
| 134 | + /// Gets the raw captures iter | |
| 135 | + pub fn captures_iter(text: &str) -> impl Iterator<Item = regex::Captures<'_>> + '_ { | |
| 136 | + let re = &RE.#ident; | |
| 137 | + re.captures_iter(text) | |
| 138 | + } | |
| 139 | + | |
| 140 | + /// Gets the raw captures iter from the contents of a file | |
| 141 | + pub fn captures_iter_from_file<'a>(buffer: &'a mut String, filename: &str) -> Result<impl Iterator<Item = regex::Captures<'a>> + 'a, std::io::Error> { | |
| 142 | + buffer.clear(); | |
| 143 | + buffer.push_str(&std::fs::read_to_string(filename)?); | |
| 144 | + Ok(Self::captures_iter(buffer)) | |
| 145 | + } | |
| 146 | + | |
| 121 | 147 | /// Extracts the first regex match for the given string |
| 122 | 148 | /// This match contains `start_pos`, `end_pos`, and `val` |
| 123 | 149 | pub fn from_str(text: &str) -> Option<Self> { |
| 124 | - let re = &RE.#ident; | |
| 125 | - let captures = re.captures(text); | |
| 126 | - if let Some(captures) = captures { | |
| 150 | + if let Some(captures) = Self::captures(text) { | |
| 127 | 151 | Some(Self { |
| 128 | 152 | start_pos: captures.get(0).unwrap().start(), |
| 129 | 153 | end_pos: captures.get(0).unwrap().end(), |
| @@ -145,8 +169,7 @@ pub fn load_regex_files(input: TokenStream) -> TokenStream { | ||
| 145 | 169 | /// Extracts all regex matches for the given string |
| 146 | 170 | /// Each match contains a `start_pos`, `end_pos`, and each field for the given class contains `start_pos`, `end_pos`, and `val` |
| 147 | 171 | pub fn iter_from_str(text: &str) -> impl Iterator<Item = Self> + '_ { |
| 148 | - let re = &RE.#ident; | |
| 149 | - re.captures_iter(text) | |
| 172 | + Self::captures_iter(text) | |
| 150 | 173 | .map(|captures| { |
| 151 | 174 | Self { |
| 152 | 175 | start_pos: captures.get(0).unwrap().start(), |
+22-0tests/test.rs
| @@ -19,3 +19,25 @@ pub fn first_event() { | ||
| 19 | 19 | let event = EventRE::from_file("samples/events.txt").unwrap().unwrap(); |
| 20 | 20 | assert_eq!(event.val, "7:30–8:00 AM Wake up + hydrate + light stretch"); |
| 21 | 21 | } |
| 22 | + | |
| 23 | +#[test] | |
| 24 | +pub fn first_event_captures() { | |
| 25 | + let mut content = String::new(); | |
| 26 | + let captures = EventRE::captures_from_file(&mut content, "samples/events.txt") | |
| 27 | + .unwrap() | |
| 28 | + .unwrap(); | |
| 29 | + assert_eq!( | |
| 30 | + captures.get(0).unwrap().as_str(), | |
| 31 | + "7:30–8:00 AM Wake up + hydrate + light stretch" | |
| 32 | + ); | |
| 33 | + assert_eq!(captures.name("end").unwrap().as_str(), "8:00"); | |
| 34 | + assert_eq!(captures.name("end").unwrap().start(), 57); | |
| 35 | +} | |
| 36 | + | |
| 37 | +#[test] | |
| 38 | +pub fn event_captures_iter() { | |
| 39 | + let mut content = String::new(); | |
| 40 | + let captures_iter = | |
| 41 | + EventRE::captures_iter_from_file(&mut content, "samples/events.txt").unwrap(); | |
| 42 | + assert_eq!(captures_iter.count(), 13); | |
| 43 | +} |