espanso/espanso-modulo/src/form/parser/split.rs

55 lines
1.3 KiB
Rust

// Taken from: https://github.com/rust-lang/regex/issues/330#issuecomment-274058261
use regex::{CaptureMatches, Captures, Regex};
pub struct SplitCaptures<'r, 't> {
finder: CaptureMatches<'r, 't>,
text: &'t str,
last: usize,
caps: Option<Captures<'t>>,
}
impl<'r, 't> SplitCaptures<'r, 't> {
pub fn new(re: &'r Regex, text: &'t str) -> SplitCaptures<'r, 't> {
SplitCaptures {
finder: re.captures_iter(text),
text,
last: 0,
caps: None,
}
}
}
#[derive(Debug)]
pub enum SplitState<'t> {
Unmatched(&'t str),
Captured(Captures<'t>),
}
impl<'r, 't> Iterator for SplitCaptures<'r, 't> {
type Item = SplitState<'t>;
fn next(&mut self) -> Option<SplitState<'t>> {
if let Some(caps) = self.caps.take() {
return Some(SplitState::Captured(caps));
}
match self.finder.next() {
None => {
if self.last >= self.text.len() {
None
} else {
let s = &self.text[self.last..];
self.last = self.text.len();
Some(SplitState::Unmatched(s))
}
}
Some(caps) => {
let m = caps.get(0).unwrap();
let unmatched = &self.text[self.last..m.start()];
self.last = m.end();
self.caps = Some(caps);
Some(SplitState::Unmatched(unmatched))
}
}
}
}