fn glob_to_regex(scope: Scope, glob: &str) -> IResult<&str, String> {
        // pass escaped characters as-is:
        let p_escaped = map(tuple((tag(PATH_ESCAPE_CHAR), anychar)), |(_, c)| {
            escape(c.to_string().as_str())
        });

        fn mk_string(contents: Vec<String>, prefix: &str, sep: &str, suffix: &str) -> String {
            format!("{}{}{}", prefix, contents.join(sep), suffix)
        }

        // { glob1, glob2, ..., globN } -> ( regex1, regex2, ..., regexN )
        let p_alt = map(
            tuple((
                tag("{"),
                separated_list(tag(","), |g| Self::glob_to_regex(Scope::CurlyBrackets, g)),
                tag("}"),
            )),
            |(_, list, _)| mk_string(list, "(", "|", ")"),
        );

        let p_ext_glob = map(
            tuple((
                tag("("),
                separated_list(tag("|"), |g| Self::glob_to_regex(Scope::RoundBrackets, g)),
                tag(")"),
            )),
            |(_, list, _)| list,
        );

        let p_ext_optional = map(tuple((tag("?"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")?")
        });
        let p_ext_many = map(tuple((tag("*"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")*")
        });
        let p_ext_at_least_once = map(tuple((tag("+"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")+")
        });
        let p_ext_exactly_once = map(tuple((tag("@"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")")
        });
        let p_ext_never = map(tuple((tag("!"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(?!", "|", ")")
        });

        // ** -> .*
        let p_double_star = map(tag("**"), |_| ".*".to_string());

        let escaped_sep = escape(MAIN_SEPARATOR.to_string().as_str());

        // * -> [^/]*
        let p_single_star = map(tag("*"), |_| "[^".to_string() + &escaped_sep + "]*");

        // ? -> .
        let p_question_mark = map(tag("?"), |_| "[^".to_string() + &escaped_sep + "]");

        // [ characters ] -> [ characters ]
        let p_neg_character_set = map(
            tuple((tag("[!"), many0(none_of("]")), tag("]"))),
            |(_, characters, _)| {
                "[^".to_string() + &characters.into_iter().collect::<String>() + "]"
            },
        );

        // [ characters ] -> [ characters ]
        let p_character_set = map(
            tuple((tag("["), many0(none_of("]")), tag("]"))),
            |(_, characters, _)| {
                "[".to_string() + &characters.into_iter().collect::<String>() + "]"
            },
        );

        let p_separator = map(tag("/"), |_| escaped_sep.clone());

        // if we are nested, we can't just pass these through without interpretation
        let p_any_char = map(
            tuple((
                cond(scope == Scope::TopLevel, anychar),
                cond(scope == Scope::CurlyBrackets, none_of("{,}")),
                cond(scope == Scope::RoundBrackets, none_of("(|)")),
            )),
            |(a, b, c)| escape(a.or(b).or(c).unwrap().to_string().as_str()),
        );

        let p_token = alt((
            p_escaped,
            p_alt,
            p_ext_optional,
            p_ext_many,
            p_ext_at_least_once,
            p_ext_exactly_once,
            p_ext_never,
            p_double_star,
            p_single_star,
            p_question_mark,
            p_neg_character_set,
            p_character_set,
            p_separator,
            p_any_char,
        ));

        let parse_all = map(many0(p_token), |s| s.join(""));
        (parse_all)(glob)
    }
/// Parses a UNIX glob and converts it to a regular expression
Parses a UNIX glob and converts it to a regular expression
Parses a UNIX glob and converts it to a regular expression
fn glob_to_regex(scope: Scope, glob: &str) -> IResult<&str, String> {
        // pass escaped characters as-is:
        let p_escaped = map(tuple((tag(PATH_ESCAPE_CHAR), anychar)), |(_, c)| {
            escape(c.to_string().as_str())
        });
        fn mk_string(contents: Vec<String>, prefix: &str, sep: &str, suffix: &str) -> String {
            format!("{}{}{}", prefix, contents.join(sep), suffix)
        }
        // { glob1, glob2, ..., globN } -> ( regex1, regex2, ..., regexN )
        let p_alt = map(
            tuple((
                tag("{"),
                separated_list(tag(","), |g| Self::glob_to_regex(Scope::CurlyBrackets, g)),
                tag("}"),
            )),
            |(_, list, _)| mk_string(list, "(", "|", ")"),
        );
        let p_ext_glob = map(
            tuple((
                tag("("),
                separated_list(tag("|"), |g| Self::glob_to_regex(Scope::RoundBrackets, g)),
                tag(")"),
            )),
            |(_, list, _)| list,
        );
        let p_ext_optional = map(tuple((tag("?"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")?")
        });
        let p_ext_many = map(tuple((tag("*"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")*")
        });
        let p_ext_at_least_once = map(tuple((tag("+"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")+")
        });
        let p_ext_exactly_once = map(tuple((tag("@"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(", "|", ")")
        });
        let p_ext_never = map(tuple((tag("!"), |i| p_ext_glob(i))), |(_, g)| {
            mk_string(g, "(?!", "|", ")")
        });
        // ** -> .*
        let p_double_star = map(tag("**"), |_| ".*".to_string());
        let escaped_sep = escape(MAIN_SEPARATOR.to_string().as_str());
        // * -> [^/]*
        let p_single_star = map(tag("*"), |_| "[^".to_string() + &escaped_sep + "]*");
        // ? -> .
        let p_question_mark = map(tag("?"), |_| "[^".to_string() + &escaped_sep + "]");
        // [ characters ] -> [ characters ]
        let p_neg_character_set = map(
            tuple((tag("[!"), many0(none_of("]")), tag("]"))),
            |(_, characters, _)| {
                "[^".to_string() + &characters.into_iter().collect::<String>() + "]"
            },
        );
        // [ characters ] -> [ characters ]
        let p_character_set = map(
            tuple((tag("["), many0(none_of("]")), tag("]"))),
            |(_, characters, _)| {
                "[".to_string() + &characters.into_iter().collect::<String>() + "]"
            },
        );
        let p_separator = map(tag("/"), |_| escaped_sep.clone());
        // if we are nested, we can't just pass these through without interpretation
        let p_any_char = map(
            tuple((
                cond(scope == Scope::TopLevel, anychar),
                cond(scope == Scope::CurlyBrackets, none_of("{,}")),
                cond(scope == Scope::RoundBrackets, none_of("(|)")),
            )),
            |(a, b, c)| escape(a.or(b).or(c).unwrap().to_string().as_str()),
        );
        let p_token = alt((
            p_escaped,
            p_alt,
            p_ext_optional,
            p_ext_many,
            p_ext_at_least_once,
            p_ext_exactly_once,
            p_ext_never,
            p_double_star,
            p_single_star,
            p_question_mark,
            p_neg_character_set,
            p_character_set,
            p_separator,
            p_any_char,
        ));
        let parse_all = map(many0(p_token), |s| s.join(""));
        (parse_all)(glob)
    }
fn glob_to_regex ( scope : Scope , glob : & str ) -> IResult < & str , String > { // pass escaped characters as-is: let p_escaped = map ( tuple ( ( tag ( PATH_ESCAPE_CHAR ) , anychar ) ) , | ( _ , c ) | { escape ( c . to_string ( ) . as_str ( ) ) } ) ; fn mk_string ( contents : Vec < String > , prefix : & str , sep : & str , suffix : & str ) -> String { format ! ( " " prefix contents join ( sep ) suffix ) } // { glob1, glob2, ..., globN } -> ( regex1, regex2, ..., regexN ) let p_alt = map ( tuple ( ( tag ( " " ) , separated_list ( tag ( " " ) , | g | Self :: glob_to_regex ( Scope :: CurlyBrackets , g ) ) , tag ( " " ) , ) ) , | ( _ , list , _ ) | mk_string ( list , " " , " " , " " ) , ) ; let p_ext_glob = map ( tuple ( ( tag ( " " ) , separated_list ( tag ( " " ) , | g | Self :: glob_to_regex ( Scope :: RoundBrackets , g ) ) , tag ( " " ) , ) ) , | ( _ , list , _ ) | list , ) ; let p_ext_optional = map ( tuple ( ( tag ( " " ) , | i | p_ext_glob ( i ) ) ) , | ( _ , g ) | { mk_string ( g , " " , " " , " " ) } ) ; let p_ext_many = map ( tuple ( ( tag ( " " ) , | i | p_ext_glob ( i ) ) ) , | ( _ , g ) | { mk_string ( g , " " , " " , " " ) } ) ; let p_ext_at_least_once = map ( tuple ( ( tag ( " " ) , | i | p_ext_glob ( i ) ) ) , | ( _ , g ) | { mk_string ( g , " " , " " , " " ) } ) ; let p_ext_exactly_once = map ( tuple ( ( tag ( " " ) , | i | p_ext_glob ( i ) ) ) , | ( _ , g ) | { mk_string ( g , " " , " " , " " ) } ) ; let p_ext_never = map ( tuple ( ( tag ( " " ) , | i | p_ext_glob ( i ) ) ) , | ( _ , g ) | { mk_string ( g , " " , " " , " " ) } ) ; // ** -> .* let p_double_star = map ( tag ( " " ) , | _ | " " . to_string ( ) ) ; let escaped_sep = escape ( MAIN_SEPARATOR . to_string ( ) . as_str ( ) ) ; // * -> [^/]* let p_single_star = map ( tag ( " " ) , | _ | " " . to_string ( ) + & escaped_sep + " " ) ; // ? -> . let p_question_mark = map ( tag ( " " ) , | _ | " " . to_string ( ) + & escaped_sep + " " ) ; // [ characters ] -> [ characters ] let p_neg_character_set = map ( tuple ( ( tag ( " " ) , many0 ( none_of ( " " ) ) , tag ( " " ) ) ) , | ( _ , characters , _ ) | { " " . to_string ( ) + & characters . into_iter ( ) . collect :: < String > ( ) + " " } , ) ; // [ characters ] -> [ characters ] let p_character_set = map ( tuple ( ( tag ( " " ) , many0 ( none_of ( " " ) ) , tag ( " " ) ) ) , | ( _ , characters , _ ) | { " " . to_string ( ) + & characters . into_iter ( ) . collect :: < String > ( ) + " " } , ) ; let p_separator = map ( tag ( " " ) , | _ | escaped_sep . clone ( ) ) ; // if we are nested, we can't just pass these through without interpretation let p_any_char = map ( tuple ( ( cond ( scope == Scope :: TopLevel , anychar ) , cond ( scope == Scope :: CurlyBrackets , none_of ( " " ) ) , cond ( scope == Scope :: RoundBrackets , none_of ( " " ) ) , ) ) , | ( a , b , c ) | escape ( a . or ( b ) . or ( c ) . unwrap ( ) . to_string ( ) . as_str ( ) ) , ) ; let p_token = alt ( ( p_escaped , p_alt , p_ext_optional , p_ext_many , p_ext_at_least_once , p_ext_exactly_once , p_ext_never , p_double_star , p_single_star , p_question_mark , p_neg_character_set , p_character_set , p_separator , p_any_char , ) ) ; let parse_all = map ( many0 ( p_token ) , | s | s . join ( " " ) ) ; ( parse_all ) ( glob ) }
Parses a UNIX glob and converts it to a regular expression
Parses a UNIX glob and converts it to a regular expression
scope
Scope
glob
&str
scope
Scope
glob
&str