/// <summary> /// Formats a parsed set of arguments back into tokenized string form. /// </summary> /// <typeparam name="T">Type of the parsed arguments object.</typeparam> /// <param name="value">The parsed argument set.</param> /// <param name="options">Optionally provides parser options.</param> /// <returns>The tokenized string.</returns> public static IEnumerable <string> Format <T>(T value, CommandLineParserOptions options) { var argSet = AttributeBasedArgumentDefinitionFactory.CreateArgumentSet( typeof(T), attribute: null, serviceConfigurer: options?.ServiceConfigurer); // N.B. We intentionally convert the arguments enumeration to a list, // as we're expecting to mutate it in the loop. foreach (var arg in argSet.AllArguments.ToList()) { if (arg.GetValue(value) is IArgumentProvider argProvider) { var definingType = argProvider.GetTypeDefiningArguments(); if (definingType != null) { AttributeBasedArgumentDefinitionFactory.AddToArgumentSet(argSet, definingType, fixedDestination: argProvider.GetDestinationObject(), containingArgument: arg, serviceConfigurer: options?.ServiceConfigurer); } } } return(OrderArgumentsByContainer(argSet.AllArguments) .Select(arg => new { Argument = arg, Value = arg.GetValue(value) }) .Where(argAndValue => (argAndValue.Value != null) && !argAndValue.Value.Equals(argAndValue.Argument.DefaultValue)) .SelectMany(argAndValue => argAndValue.Argument.Format(argAndValue.Value)) .Where(formattedValue => !string.IsNullOrWhiteSpace(formattedValue))); }
/// <summary> /// Parses command-line arguments into a reference-type object. Use /// ArgumentAttributes to control parsing behavior. /// </summary> /// <typeparam name="T">Type of the parsed arguments object.</typeparam> /// <param name="arguments">The actual arguments.</param> /// <param name="destination">The resulting parsed arguments.</param> /// <param name="options">Optionally provides additional options /// controlling how parsing proceeds.</param> /// <returns>True if no errors were detected.</returns> public static bool Parse <T>(IEnumerable <string> arguments, T destination, CommandLineParserOptions options) where T : class { Debug.Assert(arguments != null); Debug.Assert(arguments.All(arg => arg != null)); Debug.Assert(destination != null, "destination cannot be null"); var engine = new CommandLineParserEngine(destination.GetType(), destination, options); return(engine.Parse(arguments, destination)); }
/// <summary> /// Generate possible completions for the specified set of command-line /// tokens. /// </summary> /// <param name="argSet">Argument set definition.</param> /// <param name="tokens">The tokens.</param> /// <param name="indexOfTokenToComplete">Index of the token to complete. /// </param> /// <param name="options">Parsing options.</param> /// <param name="destObjectFactory">If non-null, provides a factory /// function that can be used to create an object suitable to being /// filled out by this parser instance.</param> /// <returns>The candidate completions for the specified token. /// </returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="argSet"/> /// or <paramref name="tokens"/> is null.</exception> internal static IEnumerable <string> GetCompletions(ArgumentSetDefinition argSet, IEnumerable <string> tokens, int indexOfTokenToComplete, CommandLineParserOptions options, Func <object> destObjectFactory) { if (argSet == null) { throw new ArgumentNullException(nameof(argSet)); } if (tokens == null) { throw new ArgumentNullException(nameof(tokens)); } var parser = new ArgumentSetParser(argSet, options ?? CommandLineParserOptions.Quiet()); return(parser.GetCompletions(tokens, indexOfTokenToComplete, destObjectFactory)); }
/// <summary> /// Parses command-line arguments into a reference-type object. /// Displays usage message if invalid arguments are encountered. /// </summary> /// <typeparam name="T">Type of the parsed arguments object.</typeparam> /// <param name="arguments">The actual arguments.</param> /// <param name="destination">The resulting parsed arguments.</param> /// <param name="options">Optionally provides additional options /// controlling how parsing proceeds.</param> /// <param name="usageInfoOptions">Options for how to display usage /// information, in case it's presented.</param> /// <returns>True if no errors were detected.</returns> public static bool ParseWithUsage <T>(IEnumerable <string> arguments, T destination, CommandLineParserOptions options, UsageInfoOptions usageInfoOptions) where T : class { if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (destination == null) { throw new ArgumentNullException(nameof(destination)); } if (options == null) { options = new CommandLineParserOptions { Reporter = DefaultReporter }; } Debug.Assert(arguments.All(a => a != null)); // Check if the object inherits from HelpArgumentsBase. var helpDestination = destination as HelpArgumentsBase; // Parse! var engine = new CommandLineParserEngine(destination.GetType(), destination, options); if (!engine.Parse(arguments, destination)) { // An error was encountered in arguments. Display the usage // message. options.Reporter?.Invoke(ColoredMultistring.FromString(Environment.NewLine)); options.Reporter?.Invoke(GetUsageInfo(engine, null, null, usageInfoOptions, destination)); return(false); } // We parsed the arguments, but check if we were requested to // display the usage help message anyway. if ((helpDestination != null) && helpDestination.Help) { options.Reporter?.Invoke(GetUsageInfo(engine, null, null, usageInfoOptions, destination)); return(false); } return(true); }
/// <summary> /// Tries to parse the given string arguments into a new instance of <typeparamref name="T"/>. /// </summary> /// <typeparam name="T">Type of the destination object; this type should use /// appropriate NClap attributes to annotate and define options.</typeparam> /// <param name="arguments">The string arguments to parse.</param> /// <param name="options">Options describing how to parse.</param> /// <param name="result">On success, returns the constructed result object.</param> /// <returns>True on success; false otherwise.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="arguments"/> /// is null.</exception> public static bool TryParse <T>(IEnumerable <string> arguments, CommandLineParserOptions options, out T result) where T : class, new() { if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } var destination = new T(); var argSet = AttributeBasedArgumentDefinitionFactory.CreateArgumentSet( destination.GetType(), attribute: null, defaultValues: destination, serviceConfigurer: options?.ServiceConfigurer); if (!TryParse(argSet, arguments, options, destination)) { result = null; return(false); } result = destination; return(true); }
/// <summary> /// Parses command-line arguments into a reference-type object. /// Displays usage message if invalid arguments are encountered. /// </summary> /// <typeparam name="T">Type of the parsed arguments object.</typeparam> /// <param name="arguments">The actual arguments.</param> /// <param name="destination">The resulting parsed arguments.</param> /// <param name="options">Optionally provides additional options /// controlling how parsing proceeds.</param> /// <returns>True if no errors were detected.</returns> public static bool ParseWithUsage <T>(IEnumerable <string> arguments, T destination, CommandLineParserOptions options) where T : class => ParseWithUsage(arguments, destination, options, UsageInfoOptions.Default);
/// <summary> /// Generate possible completions for the specified set of command-line /// tokens. /// </summary> /// <param name="type">Type of the parsed arguments object.</param> /// <param name="tokens">The tokens.</param> /// <param name="indexOfTokenToComplete">Index of the token to complete. /// </param> /// <param name="options">Parsing options.</param> /// <param name="destObjectFactory">If non-null, provides a factory /// function that can be used to create an object suitable to being /// filled out by this parser instance.</param> /// <returns>The candidate completions for the specified token. /// </returns> public static IEnumerable <string> GetCompletions(Type type, IEnumerable <string> tokens, int indexOfTokenToComplete, CommandLineParserOptions options, Func <object> destObjectFactory) { if (type == null) { throw new ArgumentNullException(nameof(tokens)); } if (tokens == null) { throw new ArgumentNullException(nameof(tokens)); } var engine = new CommandLineParserEngine( type, null /* default values */, options); return(engine.GetCompletions(tokens, indexOfTokenToComplete, destObjectFactory)); }
/// <summary> /// Generate possible completions for the specified set of command-line /// tokens. /// </summary> /// <param name="type">Type of the parsed arguments object.</param> /// <param name="tokens">The tokens.</param> /// <param name="indexOfTokenToComplete">Index of the token to complete. /// </param> /// <param name="options">Parsing options.</param> /// <returns>The candidate completions for the specified token. /// </returns> public static IEnumerable <string> GetCompletions(Type type, IEnumerable <string> tokens, int indexOfTokenToComplete, CommandLineParserOptions options) => GetCompletions(type, tokens, indexOfTokenToComplete, options, null /* object factory */);
public static bool Parse <T>(IEnumerable <string> arguments, ref T destination, CommandLineParserOptions options) where T : struct { var boxedDestination = (object)destination; if (!Parse(arguments, boxedDestination, options)) { return(false); } destination = (T)boxedDestination; return(true); }
/// <summary> /// Construct a fluent builder from options. /// </summary> /// <param name="options">Options.</param> /// <returns>Fluent builder.</returns> public static FluentBuilder <CommandLineParserOptions> With(this CommandLineParserOptions options) => new FluentBuilder <CommandLineParserOptions>(options.DeepClone());
/// <summary> /// Tries to parse the given string arguments into a new instance of <typeparamref name="T"/>. /// </summary> /// <typeparam name="T">Type of the destination object; this type should use /// appropriate NClap attributes to annotate and define options.</typeparam> /// <param name="options">Options describing how to parse.</param> /// <param name="arguments">The string arguments to parse.</param> /// <param name="result">On success, returns the constructed result object.</param> /// <returns>True on success; false otherwise.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="arguments"/> /// is null.</exception> public static bool TryParse <T>(this CommandLineParserOptions options, IEnumerable <string> arguments, out T result) where T : class, new() => CommandLineParser.TryParse <T>(arguments, options, out result);
/// <summary> /// Tries to parse the given string arguments into the provided instance of <typeparamref name="T"/>. /// </summary> /// <typeparam name="T">Type of the destination object; this type should use /// appropriate NClap attributes to annotate and define options.</typeparam> /// <param name="arguments">The string arguments to parse.</param> /// <param name="destination">The object to parse into.</param> /// <param name="options">Options describing how to parse.</param> /// <returns>True on success; false otherwise.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="arguments"/> or /// <paramref name="destination" /> is null.</exception> public static bool TryParse <T>(IEnumerable <string> arguments, T destination, CommandLineParserOptions options) where T : class { if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (destination == null) { throw new ArgumentNullException(nameof(arguments)); } var argSet = AttributeBasedArgumentDefinitionFactory.CreateArgumentSet( destination.GetType(), attribute: null, defaultValues: destination, serviceConfigurer: options?.ServiceConfigurer); return(TryParse(argSet, arguments, options, destination)); }
/// <summary> /// Generate possible completions for the specified set of command-line /// tokens. /// </summary> /// <param name="type">Type of the parsed arguments object.</param> /// <param name="tokens">The tokens.</param> /// <param name="indexOfTokenToComplete">Index of the token to complete. /// </param> /// <param name="options">Parsing options.</param> /// <param name="destObjectFactory">If non-null, provides a factory /// function that can be used to create an object suitable to being /// filled out by this parser instance.</param> /// <returns>The candidate completions for the specified token. /// </returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="type"/> /// or <paramref name="tokens"/> is null.</exception> public static IEnumerable <string> GetCompletions(Type type, IEnumerable <string> tokens, int indexOfTokenToComplete, CommandLineParserOptions options, Func <object> destObjectFactory) { var argSet = AttributeBasedArgumentDefinitionFactory.CreateArgumentSet( type, attribute: null, serviceConfigurer: options?.ServiceConfigurer); return(GetCompletions(argSet, tokens, indexOfTokenToComplete, options, destObjectFactory)); }
/// <summary> /// Generate possible completions for the specified command line. /// </summary> /// <param name="type">Type of the parsed arguments object.</param> /// <param name="commandLineToComplete">The command line to complete. Both single and double quote /// characters are interpreted as denoting single tokens that may contain embedded whitespace.</param> /// <param name="charIndexOfCursor">Character index of the completion cursor. /// </param> /// <param name="tokensToSkip">Number of tokens to skip from start of command /// line.</param> /// <param name="options">Parsing options.</param> /// <returns>The candidate completions for the specified token. /// </returns> public static IEnumerable <string> GetCompletions(Type type, string commandLineToComplete, int charIndexOfCursor, int tokensToSkip, CommandLineParserOptions options) { const TokenizerOptions tokenizerOptions = TokenizerOptions.AllowPartialInput | TokenizerOptions.HandleDoubleQuoteAsTokenDelimiter | TokenizerOptions.HandleSingleQuoteAsTokenDelimiter; var tokens = StringUtilities.Tokenize(commandLineToComplete, tokenizerOptions).ToList(); int index; for (index = 0; index < tokens.Count; ++index) { var token = tokens[index]; if (charIndexOfCursor >= token.OuterStartingOffset && charIndexOfCursor <= token.OuterEndingOffset) { break; } } if (index < tokensToSkip) { return(Enumerable.Empty <string>()); } return(GetCompletions( type, tokens.Skip(tokensToSkip).Select(t => t.ToString()), index - tokensToSkip, options)); }
/// <summary> /// Tries to parse the given string arguments into the provided instance of <typeparamref name="T"/>. /// </summary> /// <typeparam name="T">Type of the destination object.</typeparam> /// <param name="argSet">Definition of the argument set to be parsing.</param> /// <param name="arguments">The string arguments to parse.</param> /// <param name="options">Options describing how to parse.</param> /// <param name="destination">The object to parse into.</param> /// <returns>True on success; false otherwise.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="arguments"/> or /// <paramref name="destination" /> is null.</exception> internal static bool TryParse <T>(ArgumentSetDefinition argSet, IEnumerable <string> arguments, CommandLineParserOptions options, T destination) { if (options == null) { options = new CommandLineParserOptions(); } // // Buffer output to the reporter; suppress it if we find afterwards // that the user just wanted to see help information. // var reportedLines = new List <ColoredMultistring>(); var actualReporter = options.Reporter; options = options.DeepClone(); options.Reporter = s => reportedLines.Add(s); // // Parse! // var parser = new ArgumentSetParser(argSet, options); var parseResult = parser.ParseArgumentList(arguments, destination).IsReady; var parserArgSet = parser.ArgumentSet; // // See if the user requested help output; if so, then suppress any errors. // if ((destination is IArgumentSetWithHelp helpArgs) && helpArgs.Help && actualReporter != null) { actualReporter(GetUsageInfo(parserArgSet, options.HelpOptions, destination)); return(false); } // // Okay, now flush any reported output. // if (actualReporter != null) { foreach (var line in reportedLines) { actualReporter.Invoke(line); } } // // If we failed to parse and if the caller requested it, then display usage information. // if (!parseResult && options.DisplayUsageInfoOnError && actualReporter != null) { actualReporter(ColoredMultistring.FromString(Environment.NewLine)); actualReporter(GetUsageInfo(parserArgSet, options.HelpOptions, destination)); } return(parseResult); }