Example #1
0
        ///<summary>Creates a new Minimatcher instance, parsing the pattern into a regex.</summary>
        public Minimatcher(string pattern, Options options = null)
        {
            if (pattern == null) throw new ArgumentNullException("pattern");
            this.options = options ?? new Options();
            this.pattern = pattern.Trim();
            if (this.options.AllowWindowsPaths)
                this.pattern = this.pattern.Replace('\\', '/');

            this.Make();
        }
Example #2
0
        static void TestCase(string pattern, IList<string> expected, Options options = null, IEnumerable<string> input = null)
        {
            input = input ?? files;

            Assert.Equal(
                String.Join(Environment.NewLine, expected.OrderBy(s => s)),
                String.Join(Environment.NewLine, Minimatcher.Filter(input, pattern, options).OrderBy(s => s))
            );

            var regex = Minimatcher.CreateRegex(pattern, options);
            actualRegexes.Add(Tuple.Create(pattern, regex == null ? "false" : "/" + regex.ToString() + "/" + (regex.Options == RegexOptions.IgnoreCase ? "i" : "")));
        }
Example #3
0
 public override string RegexSource(Options options)
 {
     return options.NoGlobStar ? star
     : options.Dot ? twoStarDot
     : twoStarNoDot;
 }
Example #4
0
 public override bool Match(string input, Options options)
 {
     throw new NotSupportedException();
 }
Example #5
0
        // Brace expansion:
        // a{b,c}d -> abd acd
        // a{b,}c -> abc ac
        // a{0..3}d -> a0d a1d a2d a3d
        // a{b,c{d,e}f}g -> abg acdfg acefg
        // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
        //
        // Invalid sets are not expanded.
        // a{2..}b -> a{2..}b
        // a{b}c -> a{b}c
        ///<summary>Expands all brace ranges in a pattern, returning a sequence containing every possible combination.</summary>
        public static IEnumerable<string> BraceExpand(string pattern, Options options)
        {
            if (options.NoBrace || !hasBraces.IsMatch(pattern))
            {
                // shortcut. no need to expand.
                return new[] { pattern };
            }
            bool escaping = false;
            int i;
            // examples and comments refer to this crazy pattern:
            // a{b,c{d,e},{f,g}h}x{y,z}
            // expected:
            // abxy
            // abxz
            // acdxy
            // acdxz
            // acexy
            // acexz
            // afhxy
            // afhxz
            // aghxy
            // aghxz

            // everything before the first \{ is just a prefix.
            // So, we pluck that off, and work with the rest,
            // and then prepend it to everything we find.
            if (pattern[0] != '{')
            {
                // console.error(pattern)
                string prefix = null;
                for (i = 0; i < pattern.Length; i++)
                {
                    var c = pattern[i];
                    // console.error(i, c)
                    if (c == '\\')
                    {
                        escaping = !escaping;
                    }
                    else if (c == '{' && !escaping)
                    {
                        prefix = pattern.Substring(0, i);
                        break;
                    }
                }

                // actually no sets, all { were escaped.
                if (prefix == null)
                {
                    // console.error("no sets")
                    return new[] { pattern };
                }

                return BraceExpand(pattern.Substring(i), options).Select(t => prefix + t);
            }

            // now we have something like:
            // {b,c{d,e},{f,g}h}x{y,z}
            // walk through the set, expanding each part, until
            // the set ends.  then, we'll expand the suffix.
            // If the set only has a single member, then'll put the {} back

            // first, handle numeric sets, since they're easier
            var numset = numericSet.Match(pattern);
            if (numset.Success)
            {
                // console.error("numset", numset[1], numset[2])
                var suf = BraceExpand(pattern.Substring(numset.Length), options).ToList();
                int start = int.Parse(numset.Groups[1].Value),
                end = int.Parse(numset.Groups[2].Value),
                inc = start > end ? -1 : 1;
                var retVal = new List<string>();
                for (var w = start; w != (end + inc); w += inc)
                {
                    // append all the suffixes
                    for (var ii = 0; ii < suf.Count; ii++)
                    {
                        retVal.Add(w.ToString() + suf[ii]);
                    }
                }
                return retVal;
            }

            // ok, walk through the set
            // We hope, somewhat optimistically, that there
            // will be a } at the end.
            // If the closing brace isn't found, then the pattern is
            // interpreted as braceExpand("\\" + pattern) so that
            // the leading \{ will be interpreted literally.
            i = 1; // skip the \{
            int depth = 1;
            var set = new List<string>();
            string member = "";

            for (i = 1; i < pattern.Length && depth > 0; i++)
            {
                var c = pattern[i];
                // console.error("", i, c)

                if (escaping)
                {
                    escaping = false;
                    member += "\\" + c;
                }
                else
                {
                    switch (c)
                    {
                        case '\\':
                            escaping = true;
                            continue;

                        case '{':
                            depth++;
                            member += "{";
                            continue;

                        case '}':
                            depth--;
                            // if this closes the actual set, then we're done
                            if (depth == 0)
                            {
                                set.Add(member);
                                member = "";
                                // pluck off the close-brace
                                break;
                            }
                            else
                            {
                                member += c;
                                continue;
                            }

                        case ',':
                            if (depth == 1)
                            {
                                set.Add(member);
                                member = "";
                            }
                            else
                            {
                                member += c;
                            }
                            continue;

                        default:
                            member += c;
                            continue;
                    } // switch
                } // else
            } // for

            // now we've either finished the set, and the suffix is
            // pattern.substr(i), or we have *not* closed the set,
            // and need to escape the leading brace
            if (depth != 0)
            {
                // console.error("didn't close", pattern)
                return BraceExpand("\\" + pattern, options);
            }

            // ["b", "c{d,e}","{f,g}h"] ->
            //   ["b", "cd", "ce", "fh", "gh"]
            var addBraces = set.Count == 1;

            set = set.SelectMany(p => BraceExpand(p, options)).ToList();

            if (addBraces)
                set = set.Select(s => "{" + s + "}").ToList();
            // now attach the suffixes.
            // x{y,z} -> ["xy", "xz"]
            // console.error("set", set)
            // console.error("suffix", pattern.substr(i))
            return BraceExpand(pattern.Substring(i), options).SelectMany(s1 => set.Select(s2 => s2 + s1));
        }
Example #6
0
 ///<summary>Compiles a pattern into a single regular expression.</summary>
 public static Regex CreateRegex(string pattern, Options options = null)
 {
     return new Minimatcher(pattern, options).MakeRegex();
 }
Example #7
0
 ///<summary>Filters a list of inputs against a single pattern.</summary>
 ///<remarks>This function reparses this input on each invocation.  For performance, avoid this function and reuse a Minimatcher instance instead.</remarks>
 public static IEnumerable<string> Filter(IEnumerable<string> list, string pattern, Options options = null)
 {
     var mm = new Minimatcher(pattern, options);
     list = list.Where(mm.IsMatch);
     if (options != null && options.NoNull)
         list = list.DefaultIfEmpty(pattern);
     return list;
 }
Example #8
0
        ///<summary>Tests a single input against a pattern.</summary>
        ///<remarks>This function reparses this input on each invocation.  For performance, avoid this function and reuse a Minimatcher instance instead.</remarks>
        public static bool Check(string input, string pattern, Options options = null)
        {
            if (input == null) throw new ArgumentNullException("input");
            if (pattern == null) throw new ArgumentNullException("pattern");

            // shortcut: comments match nothing.
            if (options != null && !options.NoComment && pattern[0] == '#')
            {
                return false;
            }

            // "" only matches ""
            if (String.IsNullOrWhiteSpace(pattern)) return input == "";

            return new Minimatcher(pattern, options).IsMatch(input);
        }
Example #9
0
        ///<summary>Creates a filter function that tests input against a pattern.</summary>
        public static Func<string, bool> CreateFilter(string pattern, Options options = null)
        {
            if (pattern == null) throw new ArgumentNullException("pattern");
            // "" only matches ""
            if (String.IsNullOrWhiteSpace(pattern)) return String.IsNullOrEmpty;

            var m = new Minimatcher(pattern, options);
            return m.IsMatch;
        }
Example #10
0
 public abstract bool Match(string input, Options options);
Example #11
0
 public abstract string RegexSource(Options options);
Example #12
0
 public override string RegexSource(Options options)
 {
     return Source;
 }
Example #13
0
 public override bool Match(string input, Options options)
 {
     return regex.Value.IsMatch(input);
 }
Example #14
0
 public MagicItem(string source, Options options)
 {
     Source = source;
     regex = new Lazy<Regex>(() => new Regex("^" + source + "$", options.RegexOptions));
 }
Example #15
0
 public override string RegexSource(Options options)
 {
     return Regex.Escape(Source);
 }
Example #16
0
 public override bool Match(string input, Options options)
 {
     return input.Equals(Source, options.NoCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
 }