/// <summary> /// Adds the specified CommandLineOption object to the list of supported command-line options. /// </summary> /// <param name="option">The option to add.</param> public void AddOption(CommandLineOption option) { CheckNameAvailable(option.Name); Options.Add(option); option.Parser = this; }
private string FormatOption(string format, CommandLineOption option) { return(String.Format( format, option.ShortSymbol, option.LongSymbol, option.IsRequired ? "required" : "optional", option.Description, option.DefaultValue != null ? " (\"" + option.DefaultValue + "\")" : "" )); }
/** * Accepts command line args in the form of a string array, and assigns the * given values to the object properties annotated by CommandLineOption attributes. * Any text output (e.g. usage, errors) is written to the given TextWriter. */ protected AbstractCommandLine(String[] args, TextWriter writer) { this.allOptions = new List <CommandLineOption>(); this.requiredOptions = new List <CommandLineOption>(); this.optionalOptions = new List <CommandLineOption>(); this.optionPropertyDict = new Dictionary <CommandLineOption, PropertyInfo>(); this.argValDict = new Dictionary <string, string>(); this.targetCommandLineOption = null; this.targetValue = null; this.lastArgKey = null; this.lastArgValue = null; this.missingRequiredCommandLineOptions = new List <CommandLineOption>(); this.ProcessOptions(args, writer); }
/** * Finds a CommandLineOption on this class that matches the given symbol (short or long). * Returns null if no such CommandLineOption exists. */ protected CommandLineOption FindCommandLineOption(string symbol) { CommandLineOption commandLineOption = null; foreach (CommandLineOption o in this.allOptions) { if (lastArgKey.Equals("" + o.ShortSymbol) || lastArgKey.Equals(o.LongSymbol)) { commandLineOption = o; break; } } return(commandLineOption); }
/** * As part of processing a command line, this method scans the (derived) class for all * CommandLineOption propertiess. */ protected void InitializeCommandLineOptions() { PropertyInfo[] properties = this.GetAllProperties(this.GetType()); foreach (PropertyInfo property in properties) { CommandLineOption commandLineOption = (CommandLineOption)this.GetPropertyAttribute(property, typeof(CommandLineOption)); if (commandLineOption != null) { // Remember the property so we can assign the value later. this.optionPropertyDict[commandLineOption] = property; // Capture the option this.allOptions.Add(commandLineOption); // Is it optional? if (!commandLineOption.IsTargetOption) { if (commandLineOption.IsRequired) { this.requiredOptions.Add(commandLineOption); } else { this.optionalOptions.Add(commandLineOption); } } // Make special note of the target option, if any if (commandLineOption.IsTargetOption) { if (this.targetCommandLineOption != null) { throw new CommandLineException("Too many target command line options. One is maximum."); } else { this.targetCommandLineOption = commandLineOption; } } } } // Move the target command line option to the end so it's considered last if (this.targetCommandLineOption != null) { this.allOptions.Remove(this.targetCommandLineOption); this.allOptions.Add(this.targetCommandLineOption); } }
/** * Checks the provided command line values for both long and short symbol versions * of the given CommandLineOption. */ protected string GetCommandLineOptionValue(CommandLineOption commandLineOption) { string value = null; if (commandLineOption.IsTargetOption) { value = this.targetValue; } else if (this.argValDict.ContainsKey(commandLineOption.ShortSymbol.ToString())) { value = this.argValDict[commandLineOption.ShortSymbol.ToString()]; } else if (this.argValDict.ContainsKey(commandLineOption.LongSymbol)) { value = this.argValDict[commandLineOption.LongSymbol]; } return(value); }
/** * Returns true if the given CommandLineOption was present on the actual command line. * We need this in addition to GetCommandLineOptionValue() because it returns null * for bool values, which is correct; this method, on the other hand, just checks for * keys. */ protected bool IsCommandLineOptionPresent(CommandLineOption commandLineOption) { bool present = false; // Is it the target? if (commandLineOption.IsTargetOption) { present = this.targetValue != null; } // If not the target, then it may have been provided as a keyed argument. // Check for both long and short symbols. else { present = this.argValDict.ContainsKey(commandLineOption.ShortSymbol.ToString()) || this.argValDict.ContainsKey(commandLineOption.LongSymbol); } return(present); }
/** * The final step in command line processing, this method will assign the incoming, indexed string arg * values to the CommandLineOption properties. A few notes: * * Boolean flags are either present or not. If present, they are assigned true. If missing, they are assigned false. * * Keyed values expect a value to follow immediately. * * Target values always appear last in the command line. There may be only one. * * There is a case handled here where a command line contains a target value with a boolean flag * immediately preceding it. In this case, the regex accepts the target as the value of the boolean * flag, which is incorrect. So, there's logic here to tease out the value from the boolean keyed * value and treat it as the target. Whew. */ protected void AssignCommandLineOptionValues() { foreach (CommandLineOption commandLineOption in this.allOptions) { PropertyInfo property = this.optionPropertyDict[commandLineOption]; // Is this a bool property? If so, its value is true if the arg is present, false if not. if (property.PropertyType == typeof(bool)) { property.SetValue(this, this.IsCommandLineOptionPresent(commandLineOption), null); } // Otherwise it's a target or keyed value. else { bool valueAssigned = false; // Is this the target option? if (commandLineOption.IsTargetOption) { // Assign the target value if we have one if (this.targetValue != null) { this.AssignPropertyValue(property, this.targetValue); valueAssigned = true; } // Target value not set; check the last keyed arg. If bool, the option's value is actually the target. // If the last arg is NOT a bool, then it's a legit keyed argument and the target is just missing. else if (this.lastArgKey != null) { CommandLineOption lastCommandLineOption = this.FindCommandLineOption(lastArgKey); if ( lastCommandLineOption != null && this.optionPropertyDict[lastCommandLineOption].PropertyType == typeof(bool) && lastArgValue != null ) { this.AssignPropertyValue(property, lastArgValue); valueAssigned = true; } } } // If it's a keyed option and it's present, assign it. else if (this.IsCommandLineOptionPresent(commandLineOption)) { string value = this.GetCommandLineOptionValue(commandLineOption); this.AssignPropertyValue(property, value); valueAssigned = true; } // A value wasn't assigned (either target or keyed). Deal with required/default values. if (!valueAssigned) { // Gather missing required args if (commandLineOption.IsRequired) { this.missingRequiredCommandLineOptions.Add(commandLineOption); } // Otherwise it's optional, so set the default value else { this.AssignPropertyValue(property, commandLineOption.DefaultValue); } } } } }
/// <summary> /// Initializes a new instance of the ParsingException class with the specified message and /// an instance of CommandLineOption that is invalid. /// </summary> /// <param name="message">The message of this exception.</param> /// <param name="option">The option that caused this exception.</param> public ParsingException(string message, CommandLineOption option) : base(message) { this.Option = option; }