Beispiel #1
0
        public void TestMatchArgValuesWithOptionalTokens()
        {
            ArgumentToken arg1 = new ArgumentToken <int> .Builder().Name("arg1").IsOptional(false).Parser(int.TryParse).Build();

            ArgumentToken arg2 = new ArgumentToken <double> .Builder().Name("arg2").IsOptional(false).Parser(double.TryParse).Build();

            var tokens = new ICommandToken[]
            {
                new VerbToken(new Name("verb0")),
                new OptionWithArgumentToken.Builder().Name("-o2", "--option2").WithArgument(arg1).WithArgument(arg2).Build(),
            };

            var builder = new CommandUsage.Builder().Description("test usage");

            foreach (var token in tokens)
            {
                builder.WithToken(token);
            }

            ICommandUsage usage = builder.Build();

            TokenMatchCollection matchCollection = CommandParser.Match(usage.Tokens, "verb0 -o2 1 2.34");

            int  arg1Value;
            bool arg1Exists = matchCollection.TryGetArgValue(arg1, out arg1Value);

            double arg2Value;
            bool   arg2Exists = matchCollection.TryGetArgValue(arg2, out arg2Value);

            Assert.True(arg1Exists);
            Assert.True(arg2Exists);
            Assert.Equal(1, arg1Value);
            Assert.Equal(2.34, arg2Value);
        }
Beispiel #2
0
        public void TestOptionWithQuotedStringNotFullMatch(string input)
        {
            ICommandArgumentToken <string> .ValueParser trivialStringParser = (string i, out string v) => { v = i; return(true); };

            ArgumentToken arg1 = new ArgumentToken <string> .Builder().Name("arg1").Parser(trivialStringParser).Build();

            ArgumentToken arg2 = new ArgumentToken <string> .Builder().Name("arg2").Parser(trivialStringParser).Build();

            ArgumentToken arg3 = new ArgumentToken <string> .Builder().Name("arg3").Parser(trivialStringParser).Build();

            var token = new OptionWithArgumentToken.Builder()
                        .Name("option", "alt1", "alt2")
                        .WithArgument(arg1)
                        .WithArgument(arg2)
                        .WithArgument(arg3)
                        .Build();

            ICommandUsage usage = new CommandUsage.Builder().WithToken(token).Build();

            TokenMatchCollection matchCollection = CommandParser.Match(usage.Tokens, input);

            Assert.True(matchCollection.Matches.Count() == 1);
            ParserTokenMatch match = matchCollection.Matches.First();

            Assert.False(match.IsFullMatch, input);
        }
Beispiel #3
0
        [InlineData("-o2 1", false)]      //partial match
        public void TestTokenIsFullMatch(string input, bool expIsFullMatch)
        {
            ArgumentToken arg1 = new ArgumentToken <int> .Builder().Name("arg1").IsOptional(false).Parser(int.TryParse).Build();

            ArgumentToken arg2 = new ArgumentToken <double> .Builder().Name("arg2").IsOptional(false).Parser(double.TryParse).Build();

            var tokens = new ICommandToken[]
            {
                new OptionWithArgumentToken.Builder().Name("-o2", "--option2").WithArgument(arg1).WithArgument(arg2).Build()
            };
            var builder = new CommandUsage.Builder()
                          .Description("test usage");

            foreach (var token in tokens)
            {
                builder.WithToken(token);
            }

            ICommandUsage usage = builder.Build();

            TokenMatchCollection matchCollection = CommandParser.Match(usage.Tokens, input);

            Assert.Same(usage.Tokens, matchCollection.MatchableTokens);
            Assert.NotEmpty(matchCollection.Matches);

            Assert.Equal(1, matchCollection.Matches.Count());
            ParserTokenMatch match = matchCollection.Matches.First();

            Assert.Equal(expIsFullMatch, match.IsFullMatch);
        }
Beispiel #4
0
        public Dictionary <ICommandRoot, float> GetCommandSuggestions(string text)
        {
            Dictionary <ICommandRoot, float> suggestions = new Dictionary <ICommandRoot, float>();

            foreach (var c in _commands)
            {
                TokenMatchCollection match = CommandParser.Match(c.CommonTokens, text);
                suggestions.Add(c, match.MatchQuality);
            }

            return(suggestions);
        }
Beispiel #5
0
        public bool TryGetCommand(string text, out ICommandRoot command)
        {
            float bestMatchQuality = 0;

            command = null;

            foreach (var c in _commands)
            {
                TokenMatchCollection match = CommandParser.Match(c.CommonTokens, text);
                if (match.MatchQuality > bestMatchQuality)
                {
                    bestMatchQuality = match.MatchQuality;
                    command          = c;
                }
            }

            return(bestMatchQuality > 0);
        }
Beispiel #6
0
        [InlineData("verb0 verb4 -o1 -o2 1 2.34 -o3", 0, 4)]                    //All tokens present, wrong order
        public void TestMatchWithOptionalTokensWithArgs(string input, params int[] expectedMatchingIndexes)
        {
            ArgumentToken arg1 = new ArgumentToken <int> .Builder().Name("arg1").IsOptional(false).Parser(int.TryParse).Build();

            ArgumentToken arg2 = new ArgumentToken <double> .Builder().Name("arg2").IsOptional(false).Parser(double.TryParse).Build();

            var tokens = new ICommandToken[]
            {
                new VerbToken(new Name("verb0")),
                new StandAloneOptionToken(new Name("-o1", "--option1")),
                new OptionWithArgumentToken.Builder().Name("-o2", "--option2").WithArgument(arg1).WithArgument(arg2).Build(),
                new StandAloneOptionToken(new Name("-o3", "--option3")),
                new VerbToken(new Name("verb4")),
            };
            var builder = new CommandUsage.Builder()
                          .Description("test usage");

            foreach (var token in tokens)
            {
                builder.WithToken(token);
            }

            ICommandUsage usage = builder.Build();

            TokenMatchCollection matchCollection = CommandParser.Match(usage.Tokens, input);

            Assert.Same(usage.Tokens, matchCollection.MatchableTokens);
            if (expectedMatchingIndexes.Length > 0)
            {
                Assert.NotEmpty(matchCollection.Matches);

                Assert.Equal(expectedMatchingIndexes.Length, matchCollection.Matches.Count());

                //Ensure all that are expected are there
                foreach (var expectedMatchingIndex in expectedMatchingIndexes)
                {
                    Assert.True(matchCollection.Matches.Any(x => x.TokenIdx == expectedMatchingIndex));
                }
            }
            else
            {
                Assert.Empty(matchCollection.Matches);
            }
        }
Beispiel #7
0
        public CommandUsageMatchData Parse(string text)
        {
            CommandUsageMatchData bestMatchData = null;
            float bestMatchQuality = float.NegativeInfinity;

            foreach (var command in _commands)
            {
                Dictionary <ICommandUsage, TokenMatchCollection> matchDict = CommandParser.GetUsageMatchResults(command, text);
                foreach (var kvp in matchDict)
                {
                    ICommandUsage        usage           = kvp.Key;
                    TokenMatchCollection matchCollection = kvp.Value;

                    if (matchCollection.IsFullMatch && matchCollection.MatchQuality > bestMatchQuality)
                    {
                        bestMatchQuality = matchCollection.MatchQuality;
                        bestMatchData    = new CommandUsageMatchData(command, usage, matchCollection);
                    }
                }
            }
            return(bestMatchData);
        }
Beispiel #8
0
        public static Dictionary <ICommandUsage, TokenMatchCollection> GetUsageMatchResults(ICommandRoot currentRoot, string text)
        {
            Dictionary <ICommandUsage, TokenMatchCollection> usageMatchData = new Dictionary <ICommandUsage, TokenMatchCollection>();

            if (currentRoot.Usages.Any())
            {
                foreach (var usage in currentRoot.Usages)
                {
                    ICommandToken[]      tokens          = currentRoot.CommonTokens.Concat(usage.Tokens).ToArray();
                    TokenMatchCollection matchCollection = Match(tokens, text);
                    usageMatchData.Add(usage, matchCollection);
                }
            }
            else
            {
                ICommandToken[]      tokens          = currentRoot.CommonTokens.ToArray();
                TokenMatchCollection matchCollection = Match(tokens, text);
                usageMatchData.Add(new CommandRootUsage(currentRoot), matchCollection);
            }

            return(usageMatchData);
        }
Beispiel #9
0
        [InlineData("1234 verb1 verb2 verb3 verb4", 3)] //Too many tokens
        public void TestMatch(string input, int?expectedMatchIdx)
        {
            var tokens = new ICommandToken[]
            {
                new ArgumentToken <int> .Builder()
                .Name("name")
                .Parser(int.TryParse)
                .IsOptional(false)
                .Build(),
                new VerbToken(new Name("verb1", "alt1")),
                new VerbToken(new Name("verb2", "alt2")),
                new VerbToken(new Name("verb3", "alt3"))
            };
            var builder = new CommandUsage.Builder()
                          .Description("test usage");

            foreach (var token in tokens)
            {
                builder.WithToken(token);
            }

            ICommandUsage usage = builder.Build();

            TokenMatchCollection matchCollection = CommandParser.Match(usage.Tokens, input);

            Assert.Same(usage.Tokens, matchCollection.MatchableTokens);
            if (expectedMatchIdx.HasValue)
            {
                Assert.NotEmpty(matchCollection.Matches);
                Assert.Same(tokens[expectedMatchIdx.Value], matchCollection.Matches.Last(x => x.MatchOutcome == Enums.MatchOutcome.Full).Token);
                Assert.Equal(expectedMatchIdx, matchCollection.Matches.Where(x => x.MatchOutcome == Enums.MatchOutcome.Full).Max(x => x.TokenIdx));
            }
            else
            {
                Assert.Empty(matchCollection.Matches);
            }
        }
Beispiel #10
0
        public static TokenMatchCollection Match(ICommandToken[] commandTokens, string input)
        {
            string[]   inputTokens           = Tokenize(input);
            int        inputTokenIdx         = 0;
            int        commandTokensIdx      = 0;
            List <int> matchableTokenIndexes = new List <int>();

            TokenMatchCollection matchCollection = new TokenMatchCollection(input, commandTokens);

            while (inputTokenIdx < inputTokens.Length)
            {
                //Take another token from the usage to consider
                if (commandTokensIdx < commandTokens.Length)
                {
                    matchableTokenIndexes.Add(commandTokensIdx);
                    commandTokensIdx++;
                }

                bool areAllTokensOptional = true;
                //Find the next token match. Greedy search prefers tokens with lowest index
                TokenMatchResult bestMatch = TokenMatchResult.None;
                int bestMatchIdx           = -1;
                foreach (var tokenIdx in matchableTokenIndexes)
                {
                    ICommandToken token = commandTokens[tokenIdx];
                    areAllTokensOptional &= token.IsOptional;
                    TokenMatchResult matchResult = token.Matches(inputTokens, inputTokenIdx);
                    int tokenMatchLength         = matchResult.TokensMatched;

                    if (matchResult.IsBetterMatchThan(bestMatch))
                    {
                        bestMatch    = matchResult;
                        bestMatchIdx = tokenIdx;
                    }

                    if (matchResult.MatchOutcome == MatchOutcome.Full)
                    {
                        //match!
                        List <string> matchedTokensStrs = inputTokens.Skip(inputTokenIdx).Take(tokenMatchLength).ToList();
                        string        matchText         = string.Join(" ", matchedTokensStrs);
                        matchCollection.With(new ParserTokenMatch(tokenIdx, matchResult));

                        matchCollection.AddAllArgumentValues(matchResult);

                        matchableTokenIndexes.Remove(tokenIdx);
                        inputTokenIdx += tokenMatchLength;

                        if (!token.IsOptional)
                        {
                            //All optional tokens until this required one are no longer viable
                            matchableTokenIndexes.Clear();
                        }

                        break;
                    }
                }

                if (bestMatch.MatchOutcome < MatchOutcome.Full)
                {
                    //No match found!
                    if (!areAllTokensOptional || commandTokensIdx == commandTokens.Length)
                    {
                        //We couldn't match a required token OR
                        //considering all tokens, no more matches could be found
                        //...so that's the end of the match

                        if (bestMatch.MatchOutcome != MatchOutcome.None)
                        {
                            //Add a partial match for whatever last failed to match
                            matchCollection.With(new ParserTokenMatch(bestMatchIdx, bestMatch));
                        }
                        return(matchCollection);
                    }
                }
            }

            return(matchCollection);
        }