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); }
[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); }
public static ICommandToken GetNextToken(ICommandUsage currentUsage, string text) { int currentIdx = Match(currentUsage.Tokens, text).Matches.Max(x => x.TokenIdx); if (currentIdx >= 0 && currentIdx < currentUsage.Tokens.Length - 1) { return(currentUsage.Tokens[currentIdx + 1]); } return(null); }
public void TestAdjacentTokens(string input, int?prevIdx, int?currentIdx, int?nextIdx) { 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(); ICommandToken currentToken = CommandParser.GetCurrentToken(usage, input); ICommandToken prevToken = CommandParser.GetPreviousToken(usage, input); ICommandToken nextToken = CommandParser.GetNextToken(usage, input); if (prevIdx.HasValue) { Assert.Same(tokens[prevIdx.Value], prevToken); } else { Assert.Null(prevToken); } if (currentIdx.HasValue) { Assert.Same(tokens[currentIdx.Value], currentToken); } else { Assert.Null(currentToken); } if (nextIdx.HasValue) { Assert.Same(tokens[nextIdx.Value], nextToken); } else { Assert.Null(nextToken); } }
public void WriteHelpItem(ICommandRoot root, ICommandUsage helpItem, int indent = 0) { string rootVerbs = string.Join(" ", root.CommonTokens.Select(x => x.Name.Preferred)); string usageArgs = string.Join(" ", helpItem.Tokens.Select(x => GetOptionalDisplayName(x))); ConsoleHelper.WriteWithIndent($"{rootVerbs} {usageArgs}", indent * IndentAmount); Console.WriteLine(); Console.WriteLine(); ConsoleHelper.WriteWithIndent("Options:", (indent - 1) * IndentAmount, ColorH1); Console.WriteLine(); Console.WriteLine(); int descriptionIndent = indent * IndentAmount + helpItem.Tokens.Max(x => x.DisplayName.Length); foreach (var token in helpItem.Tokens) { if (token.IsOptional) { ConsoleHelper.WriteWithIndent($"{token.DisplayName}", indent * IndentAmount); ConsoleHelper.WriteWithIndent(" # ", descriptionIndent, Color.Gray); ConsoleHelper.WriteWithIndent(helpItem.GetDescription(token), descriptionIndent + 4, Color.Gray); object defaultValue = helpItem.GetDefaultValue(token); if (defaultValue != null) { ConsoleHelper.WriteWithIndent($" [default: {defaultValue.ToString()}]", descriptionIndent + 4, Color.Gray); } if (token.PossibleValues != null && token.PossibleValues.Length > 0) { Console.WriteLine(); ConsoleHelper.WriteWithIndent($"Possible Values: {{{string.Join(", ", token.PossibleValues)}}}", descriptionIndent + 8); } Console.WriteLine(); } } Console.WriteLine(); ConsoleHelper.WriteWithIndent("Examples:", (indent - 1) * IndentAmount, ColorH1); Console.WriteLine(); Console.WriteLine(); foreach (var example in helpItem.Examples) { ConsoleHelper.WriteWithIndent(example, indent * IndentAmount); Console.WriteLine(); } }
[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); } }
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); }
[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); } }
public CommandUsageMatchData(ICommandRoot command, ICommandUsage usage, TokenMatchCollection matchCollection) { Command = command; Usage = usage; _matchCollection = matchCollection; }
public Builder WithUsage(ICommandUsage usage) { _usages.Add(usage); return(this); }