use ferroni::prelude::*;
const SCOPES: &[&str] = &["keyword", "string", "comment", "number", "identifier"];
fn main() -> Result<(), RegexError> {
let mut scanner = Scanner::new(&[
r"\b(?:const|let|var|function|return)\b",
r#""[^"]*""#,
r"//.*$",
r"\b\d+(?:\.\d+)?\b",
r"\b[A-Za-z_]\w*\b",
])?;
let line = r#"const label = "answer" + 42 // "not" a string"#;
let mut position = 0;
while let Some(m) = scanner.find_next_match(line, position, ScannerFindOptions::NONE) {
let whole = &m.captures()[0];
println!(
"{:>10} {:>3}..{:<3} {}",
SCOPES[m.index],
whole.start,
whole.end,
&line[whole.start..whole.end],
);
let next_boundary =
whole.start + line[whole.start..].chars().next().map_or(1, char::len_utf8);
position = whole.end.max(next_boundary);
}
let mut scanner = Scanner::new(&["world"])?;
let text = OnigString::new("hello 🌍 world");
let m = scanner
.find_next_match_utf16(&text, 0, ScannerFindOptions::NONE)
.expect("`world` is in the text");
println!(
"\nUTF-16 offsets: {}..{} (the emoji counts as two units)",
m.captures()[0].start,
m.captures()[0].end,
);
Ok(())
}