/// <summary> /// Tries to retrieve the name of the given type associated with this /// argument. If no such name of that type exists, returns null. /// </summary> /// <param name="nameType">The type of name to retrieve.</param> /// <returns>The given name, or null if no such name exists.</returns> public string GetName(ArgumentNameType nameType) { switch (nameType) { case ArgumentNameType.ShortName: return(ShortName); case ArgumentNameType.LongName: return(LongName); default: throw new ArgumentOutOfRangeException(nameof(nameType)); } }
private IEnumerable <string> GetNamedArgumentCompletions(ArgumentNameType nameType, IReadOnlyList <string> tokens, int indexOfTokenToComplete, string namedArgumentAfterPrefix, object inProgressParsedObject) { Func <IEnumerable <string> > emptyCompletions = Enumerable.Empty <string>; var separatorIndex = namedArgumentAfterPrefix.IndexOfAny(ArgumentTerminatorsAndSeparators.ToArray()); if (separatorIndex < 0) { return(ArgumentSet.NamedArguments .Select(namedArg => namedArg.GetName(nameType)) .Where(argName => argName != null) .OrderBy(argName => argName, StringComparerToUse) .Where(candidateName => candidateName.StartsWith(namedArgumentAfterPrefix, StringComparisonToUse))); } var separator = namedArgumentAfterPrefix[separatorIndex]; if (!ArgumentSet.Attribute.ArgumentValueSeparators.Contains(separator)) { return(emptyCompletions()); } var name = namedArgumentAfterPrefix.Substring(0, separatorIndex); var value = namedArgumentAfterPrefix.Substring(separatorIndex + 1); if (!ArgumentSet.TryGetNamedArgument(nameType, name, out ArgumentDefinition arg)) { return(emptyCompletions()); } var parseState = new ArgumentParser(ArgumentSet, arg, _options, /*destination=*/ null); return(parseState .GetCompletions(tokens, indexOfTokenToComplete, value, inProgressParsedObject) .Select(completion => string.Concat(name, separator.ToString(), completion))); }
private IReadOnlyDictionary <string, ArgumentDefinition> GetNamedArgumentDictionary(ArgumentNameType nameType) { switch (nameType) { case ArgumentNameType.ShortName: return(_namedArgumentsByShortName); case ArgumentNameType.LongName: return(_namedArgumentsByLongName); default: throw new ArgumentOutOfRangeException(nameof(nameType)); } }
/// <summary> /// Try to look up a named argument by short or long name. /// </summary> /// <param name="nameType">Type of name to look up.</param> /// <param name="name">Name to look up.</param> /// <param name="arg">On success, receives the named argument.</param> /// <returns>True on success; false otherwise.</returns> public bool TryGetNamedArgument(ArgumentNameType nameType, string name, out ArgumentDefinition arg) { var dict = GetNamedArgumentDictionary(nameType); return(dict.TryGetValue(name, out arg)); }
/// <summary> /// Enumerates named arguments of the given type. /// </summary> /// <param name="nameType">Type of name to look up.</param> /// <returns>Enumeration.</returns> public IEnumerable <string> GetArgumentNames(ArgumentNameType nameType) { var dict = GetNamedArgumentDictionary(nameType); return(dict.Keys); }
private ArgumentSetParseResult TryParseNamedArgument( string argument, string argumentPrefix, ArgumentNameType namedArgType, out IReadOnlyList <ArgumentAndValue> parsedArgs) { var prefixLength = argumentPrefix.Length; Debug.Assert(argument.Length >= prefixLength); // Figure out where the argument name ends. var endIndex = argument.IndexOfAny(ArgumentSet.Attribute.ArgumentValueSeparators, prefixLength); // Special case: check for '+' and '-' for booleans. if (endIndex < 0 && argument.Length > argumentPrefix.Length) { var lastArgumentChar = argument[argument.Length - 1]; if (ArgumentNameTerminators.Any(t => lastArgumentChar.Equals(t))) { endIndex = argument.Length - 1; } } // If we don't have a separator or terminator, then consume the full string. if (endIndex < 0) { endIndex = argument.Length; } // Extract the argument name(s), separate from the prefix // or optional argument value. var options = argument.Substring(prefixLength, endIndex - prefixLength); // Extract the option argument (a.k.a. value), if there is one. string optionArgument = null; if (argument.Length > prefixLength + options.Length) { // If there's an argument value separator, then extract the value after the separator. if (ArgumentSet.Attribute.ArgumentValueSeparators.Any(sep => argument[prefixLength + options.Length] == sep)) { optionArgument = argument.Substring(prefixLength + options.Length + 1); } // Otherwise, it might be a terminator; extract the rest of the string. else { optionArgument = argument.Substring(prefixLength + options.Length); } } // Now try to figure out how many names are present. if (namedArgType == ArgumentNameType.ShortName && (ArgumentSet.Attribute.AllowMultipleShortNamesInOneToken || ArgumentSet.Attribute.AllowElidingSeparatorAfterShortName)) { Debug.Assert(ArgumentSet.Attribute.ShortNamesAreOneCharacterLong); // Since short names are one character long, we parse them one at a // time, preparing for multiple arguments in this one token. var args = new List <ArgumentAndValue>(); for (var index = 0; index < options.Length; ++index) { // Try parsing it as a short name; bail immediately if we find an invalid // one. var possibleShortName = new string(options[index], 1); if (!ArgumentSet.TryGetNamedArgument(ArgumentNameType.ShortName, possibleShortName, out ArgumentDefinition arg)) { parsedArgs = null; return(ArgumentSetParseResult.UnknownNamedArgument(namedArgType, possibleShortName)); } // If this parsed as a short name that takes a required option argument, // and we didn't see an option argument, and we allow mushing together // short names and their option arguments, then try parsing the rest of // this token as an option argument. var lastChar = index == options.Length - 1; if (arg.RequiresOptionArgumentEx(_options) && ArgumentSet.Attribute.AllowElidingSeparatorAfterShortName && optionArgument == null && !lastChar) { optionArgument = options.Substring(index + 1); index = options.Length - 1; lastChar = true; } if (!ArgumentSet.Attribute.AllowMultipleShortNamesInOneToken && args.Count > 0) { parsedArgs = null; return(ArgumentSetParseResult.UnknownNamedArgument()); } args.Add(new ArgumentAndValue { Arg = arg, Value = lastChar ? optionArgument : null }); } // Special case: if no arguments were found, return an error. if (args.Count == 0) { parsedArgs = null; return(ArgumentSetParseResult.FailedParsing); } parsedArgs = args; } else { // Try to look up the argument by name. if (!ArgumentSet.TryGetNamedArgument(namedArgType, options, out ArgumentDefinition arg)) { parsedArgs = null; return(ArgumentSetParseResult.UnknownNamedArgument(namedArgType, options)); } parsedArgs = new[] { new ArgumentAndValue { Arg = arg, Value = optionArgument } }; } var lastArg = parsedArgs.GetLastOrDefault(); var lastArgTakesRestOfLine = lastArg?.Arg.TakesRestOfLine ?? false; // If the last named argument we saw in this token required an // option argument to go with it, then yield that information // so it can be used by the caller (e.g. in completion generation). if (lastArg != null && lastArg.Arg.RequiresOptionArgumentEx(_options) && string.IsNullOrEmpty(lastArg.Value)) { return(ArgumentSetParseResult.RequiresOptionArgument(lastArg.Arg)); } return(ArgumentSetParseResult.Ready(lastArg?.Arg)); }