use eregex::{Regex, flags};
#[test]
fn readme_lookaround_conditional_not_yet_supported() {
let e = Regex::new(r"(?(?=\d)\d+|\w+)").unwrap_err();
assert!(e.to_string().contains("conditional"));
}
#[test]
fn readme_posix_matching_not_yet_supported() {
let e = Regex::new(r"(?p)Mr|Mrs").unwrap_err();
assert!(e.to_string().contains("flag"));
}
#[test]
fn readme_p_equals_name_backreference() {
let r = Regex::new(r"(?P<word>\w+)-(?P=word)").unwrap();
let m = r.find("go-go").unwrap();
assert_eq!(m.as_str(), "go-go");
}
#[test]
fn readme_star_in_substitution() {
let r = Regex::new(r".*").unwrap();
assert_eq!(r.replace_all("test", "x"), "xx");
}
#[test]
fn readme_capturesdict() {
let r = Regex::new(r"(?:(?P<word>\w+) (?P<digits>\d+)\n)+").unwrap();
let hay = "one 1\ntwo 2\nthree 3\n";
let m = r.find(hay).unwrap();
let gd = m.named_groups();
assert_eq!(gd.get("word").copied(), Some("three"));
assert_eq!(gd.get("digits").copied(), Some("3"));
assert_eq!(
m.captures_name("word"),
vec![Some("one"), Some("two"), Some("three")]
);
assert_eq!(
m.captures_name("digits"),
vec![Some("1"), Some("2"), Some("3")]
);
let cd = m.captures_dict();
assert_eq!(cd.get("word").unwrap(), &vec!["one", "two", "three"]);
assert_eq!(cd.get("digits").unwrap(), &vec!["1", "2", "3"]);
}
#[test]
fn readme_allcaptures_and_allspans() {
let r = Regex::new(r"(?:(?P<word>\w+) (?P<digits>\d+)\n)+").unwrap();
let hay = "one 1\ntwo 2\nthree 3\n";
let m = r.find(hay).unwrap();
let ac = m.all_captures();
assert_eq!(ac[0], vec!["one 1\ntwo 2\nthree 3\n"]);
assert_eq!(ac[1], vec!["one", "two", "three"]);
assert_eq!(ac[2], vec!["1", "2", "3"]);
let aspans = m.all_spans();
assert_eq!(aspans[2], vec![(4, 5), (10, 11), (18, 19)]);
}
#[test]
fn readme_duplicate_names_optional_both_capture() {
let r = Regex::new(r"(?P<item>\w+)? or (?P<item>\w+)?").unwrap();
let m = r.find("first or second").unwrap();
assert_eq!(m.name("item"), Some("second"));
assert_eq!(m.captures_name("item"), vec![Some("first"), Some("second")]);
}
#[test]
fn readme_duplicate_names_optional_second_only() {
let r = Regex::new(r"(?P<item>\w+)? or (?P<item>\w+)?").unwrap();
let m = r.find(" or second").unwrap();
assert_eq!(m.name("item"), Some("second"));
assert_eq!(m.captures_name("item"), vec![Some("second")]);
}
#[test]
fn readme_duplicate_names_optional_first_only() {
let r = Regex::new(r"(?P<item>\w+)? or (?P<item>\w+)?").unwrap();
let m = r.find("first or ").unwrap();
assert_eq!(m.name("item"), Some("first"));
assert_eq!(m.captures_name("item"), vec![Some("first")]);
}
#[test]
fn readme_duplicate_names_mandatory() {
let r = Regex::new(r"(?P<item>\w*) or (?P<item>\w*)").unwrap();
let m = r.find("first or second").unwrap();
assert_eq!(m.captures_name("item"), vec![Some("first"), Some("second")]);
}
#[test]
fn readme_fullmatch() {
let r = Regex::new(r"abc").unwrap();
assert_eq!(r.fullmatch("abc").unwrap().span(), (0, 3));
assert!(r.fullmatch("abcx").is_none());
let r = Regex::new(r"a.*?").unwrap();
assert_eq!(r.match_at_start("abcd").unwrap().as_str(), "a"); assert_eq!(r.fullmatch("abcd").unwrap().as_str(), "abcd"); }
#[test]
fn readme_full_casefolding_currently_simple_only() {
let r = Regex::new_with_flags(r"(?i)strasse", flags::VERSION1).unwrap();
assert_eq!(r.find("STRASSE").unwrap().as_str(), "STRASSE");
assert!(
Regex::new_with_flags(r"(?i)strasse", flags::VERSION1)
.unwrap()
.find("stra\u{DF}e")
.is_none()
);
}
#[test]
fn readme_m_M_word_anchors() {
let r = Regex::new(r"\mcat").unwrap();
let m = r.find("the cat sat").unwrap();
assert_eq!(m.as_str(), "cat");
assert!(Regex::new(r"\mcat").unwrap().find("concatenate").is_none());
let r = Regex::new(r"cat\M").unwrap();
assert!(r.find("the cat sat").is_some());
assert!(r.find("the category").is_none());
}
#[test]
fn readme_set_operators_rejected() {
for p in [r"[a-z&&[^aeiou]]", r"[a-z--qw]", r"[a||b]", r"[a~~b]"] {
let e = Regex::new(p).unwrap_err();
assert!(
e.to_string().contains("set operation"),
"{p:?} should be rejected as a set op, got: {e}"
);
}
}
#[test]
fn readme_escape_special_only_exact() {
use eregex::escape_special_only;
assert_eq!(escape_special_only("foo!?"), "foo!\\?");
}
#[test]
fn readme_escape_literal_spaces_exact() {
use eregex::escape_literal_spaces;
assert_eq!(escape_literal_spaces("foo bar!?"), "foo bar!\\?");
}
#[test]
fn readme_repeated_captures_starts_ends_spans() {
let r = Regex::new(r"(\w{3})+").unwrap();
let m = r.find("123456789").unwrap();
assert_eq!(m.group(1), Some("789"));
assert_eq!(m.captures(1), vec![Some("123"), Some("456"), Some("789")]);
assert_eq!(m.starts(1), vec![0, 3, 6]);
assert_eq!(m.ends(1), vec![3, 6, 9]);
assert_eq!(m.spans(1), vec![(0, 3), (3, 6), (6, 9)]);
}
#[test]
fn readme_atomic_grouping() {
let r = Regex::new(r"a(?>bc|b)c").unwrap();
assert!(r.find("abc").is_none()); assert_eq!(r.find("abcc").unwrap().as_str(), "abcc");
}
#[test]
fn readme_possessive_quantifiers() {
assert!(Regex::new(r"a++a").unwrap().find("aaa").is_none());
assert_eq!(
Regex::new(r"a++").unwrap().find("aaa").unwrap().as_str(),
"aaa"
);
assert!(
Regex::new(r"(?:ab){2,}+ab")
.unwrap()
.find("ababab")
.is_none()
);
assert!(
Regex::new(r"(?:ab){2,}ab")
.unwrap()
.find("ababab")
.is_some()
);
}
#[test]
fn readme_scoped_flags() {
let r = Regex::new(r"(?i-m:abc)def").unwrap();
assert_eq!(r.find("ABCdef").unwrap().as_str(), "ABCdef");
}
#[test]
fn readme_variable_length_lookbehind() {
let r = Regex::new(r"(?<=foo|foobar)X").unwrap();
assert_eq!(r.find("fooX").unwrap().as_str(), "X");
assert_eq!(r.find("foobarX").unwrap().as_str(), "X");
assert!(r.find("barX").is_none());
}
#[test]
fn readme_splititer() {
let r = Regex::new(r"\s+").unwrap();
let v: Vec<_> = r.split_iter("a b c").collect();
assert_eq!(v, vec!["a", "b", "c"]);
}
#[test]
fn readme_match_subscripting() {
let r = Regex::new(r"(?P<before>.*?)(?P<num>\d+)(?P<after>.*)").unwrap();
let m = r.find("pqr123stu").unwrap();
assert_eq!(&m["before"], "pqr");
assert_eq!(&m["num"], "123");
assert_eq!(&m["after"], "stu");
assert_eq!(m.len(), 4);
let all = m.all_groups();
assert_eq!(
all,
vec![Some("pqr123stu"), Some("pqr"), Some("123"), Some("stu")]
);
}
#[test]
fn readme_named_groups_angle_form() {
let r = Regex::new(r"(?<word>\w+)").unwrap();
let m = r.find("hello!").unwrap();
assert_eq!(m.name("word"), Some("hello"));
}
#[test]
fn readme_group_reference_g_name() {
let r = Regex::new(r"(\w+) \g<1>").unwrap();
assert_eq!(r.find("hi hi").unwrap().as_str(), "hi hi");
let r = Regex::new(r"(?P<x>\w+)-\g<x>").unwrap();
assert_eq!(r.find("go-go").unwrap().as_str(), "go-go");
}
#[test]
fn readme_unicode_property_forms() {
assert_eq!(
Regex::new(r"\p{L}+")
.unwrap()
.find("abc123")
.unwrap()
.as_str(),
"abc"
);
assert_eq!(
Regex::new(r"\p{N}+")
.unwrap()
.find("abc123")
.unwrap()
.as_str(),
"123"
);
assert_eq!(
Regex::new(r"\P{N}+")
.unwrap()
.find("123abc")
.unwrap()
.as_str(),
"abc"
);
assert_eq!(
Regex::new(r"\p{gc=nd}+")
.unwrap()
.find("abc123")
.unwrap()
.as_str(),
"123"
);
}
#[test]
fn readme_posix_character_classes() {
let r = Regex::new(r"[[:alpha:]]+").unwrap();
assert_eq!(r.find("123abc").unwrap().as_str(), "abc");
let r = Regex::new(r"[[:^alpha:]]+").unwrap();
assert_eq!(r.find("abc123").unwrap().as_str(), "123");
}
#[test]
fn readme_grapheme_x_approximated() {
let r = Regex::new(r"\X").unwrap();
let m = r.find("abc").unwrap();
assert_eq!(m.as_str(), "a");
}
#[test]
fn readme_define_rejected() {
let e = Regex::new(r"(?(DEFINE)(?P<q>\d+))").unwrap_err();
assert!(e.to_string().contains("conditional") || e.to_string().contains("DEFINE"));
}
#[test]
fn readme_backtracking_verbs_rejected() {
for p in [r"(*PRUNE)", r"(*SKIP)", r"(*FAIL)", r"(*F)"] {
let e = Regex::new(p).unwrap_err();
assert!(e.to_string().contains("verb"), "{p:?}: {e}");
}
}
#[test]
fn readme_keep_backslash_k_rejected() {
let e = Regex::new(r"\w\K\w").unwrap_err();
assert!(e.to_string().contains("\\K"));
}
#[test]
fn readme_recursive_patterns_rejected() {
for p in [r"(?R)", r"(?1)", r"(Tarzan|Jane) loves (?1)"] {
let e = Regex::new(p).unwrap_err();
let s = e.to_string();
assert!(
s.contains("recursive")
|| s.contains("subpattern")
|| s.contains("flag")
|| s.contains("conditional"),
"{p:?}: {s}"
);
}
}
#[test]
fn readme_fuzzy_matching_rejected() {
for p in [r"(?:foo){e<=1}", r"(dog){e}", r"(?:x){i<=1,s<=2}"] {
let e = Regex::new(p).unwrap_err();
assert!(e.to_string().contains("fuzzy"), "{p:?}: {e}");
}
}
#[test]
fn readme_named_lists_rejected() {
let e = Regex::new(r"\L<options>").unwrap_err();
assert!(e.to_string().contains("\\L"));
}
#[test]
fn readme_named_characters_rejected() {
let e = Regex::new(r"\N{SPACE}").unwrap_err();
assert!(e.to_string().contains("\\N"));
}
#[test]
fn readme_search_anchor_g_rejected() {
let e = Regex::new(r"\G\w{2}").unwrap_err();
assert!(e.to_string().contains("\\G"));
}
#[test]
fn readme_reverse_searching_rejected() {
let e = Regex::new(r"(?r).").unwrap_err();
assert!(e.to_string().contains("flag"));
}
#[test]
fn readme_branch_reset_rejected() {
let e = Regex::new(r"(?|(first)|(second))").unwrap_err();
assert!(e.to_string().contains("flag") || e.to_string().contains("|"));
}
#[test]
fn readme_word_flag_rejected() {
let r = Regex::new_with_flags(r"\bword\b", flags::WORD).unwrap();
assert!(r.find("a word here").is_some());
}
#[test]
fn readme_version_flags_recognized() {
assert!(Regex::new(r"(?V1)abc").is_ok());
assert!(Regex::new(r"(?V0)abc").is_ok());
assert!(Regex::new(r"(?V9)abc").is_err());
}
#[test]
fn readme_partial_matches_currently_absent() {
let r = Regex::new(r"\d{4}").unwrap();
assert!(r.fullmatch("123").is_none()); assert!(r.fullmatch("1234").is_some()); assert!(r.fullmatch("12345").is_none()); }