private static T ConvertTo <TV, T>(TV optionValue, CliOption <T> option) { try { if (typeof(IEnumerable).IsAssignableFrom(typeof(T)) && typeof(T) != typeof(string)) { var list = JsonConvert.DeserializeObject <T>(optionValue as string); return(list); } if (typeof(T) == typeof(bool)) { if (optionValue.ToString() == "on") { return((T)Convert.ChangeType(true, typeof(T))); } } return((T)Convert.ChangeType(optionValue, typeof(T))); } catch (Exception ex) { throw new MuTestInputException("A optionValue passed to an option was not valid.", $@"The option {option.ArgumentName} with optionValue {optionValue} is not valid. Hint: {ex.Message}"); } }
public static Options Parse(string[] args) { var options = new Options(); bool inputSpecified = false; CliOption[] cliOptions = GetCliOptions(); for (int i = 0; i < args.Length; i++) { string arg; if (args[i].Length == 2 && (args[i][0] == '-' || args[i][0] == '/')) { arg = args[i][1].ToString().ToLower(); } else if (args[i].Length > 2 && args[i].Substring(0, 2) == "--") { arg = args[i].Substring(2).ToLower(); } else { if (inputSpecified) { PrintWithUsage($"Unable to parse option {args[i]}"); return(null); } options.InFile = args[i]; inputSpecified = true; continue; } CliOption option = cliOptions.FirstOrDefault(x => x.Long == arg || x.Short == arg); if (option == null) { PrintWithUsage($"Unknown option {args[i]}"); return(null); } if (i + option.ArgsNeeded >= args.Length) { PrintWithUsage($"Need {option.ArgsNeeded} parameter{(option.ArgsNeeded == 1 ? "" : "s")} after {args[i]}"); return(null); } var optionArgs = new string[option.ArgsNeeded]; Array.Copy(args, i + 1, optionArgs, 0, option.ArgsNeeded); option.Assigner(options, optionArgs); i += option.ArgsNeeded; } if (!inputSpecified && options.InFileType != FileType.Keygen && options.InFileType != FileType.Bench && !options.RunCustom) { PrintWithUsage("Input file must be specified"); return(null); } return(options); }
private static int GetOptionWidth(CliOption option) { var width = option.Name.Length; if (option.ShortName != null) { width += 4; } return(width); }
//[Category(Cat_Tools)] //[Description("Run NUnit test runner")] //public static readonly CLOption NUnit = new CLOption("nunit"); #endregion static PFCOptions() { Debug.DotNetCompiler = true; Debug.PlusMinus = true; Optimize.DotNetCompiler = true; Optimize.PlusMinus = true; ExceptionBreak.PlusMinus = true; Compressed.PlusMinus = true; CliOption.Init(typeof(PFCOptions)); }
private void ParseArg(string arg, ref CliOption newOption, ref CliInput inputObject) { if (arg.Trim() == "-") { return; // - indicates std out } if (arg.Trim().StartsWith("-", StringComparison.Ordinal) || arg.Trim().StartsWith("--", StringComparison.Ordinal)) { CreateNewOption(arg, ref newOption, ref inputObject); } else // Possibly dealing with previous option values { AddCompletedOption(arg, ref newOption, ref inputObject); } }
private void CreateNewOption(string arg, ref CliOption newOption, ref CliInput inputObject) { if (!Constants.GetValidCommands().Contains(arg.Trim())) { throw new ArgumentException(string.Format("Argument {0} is not valid.", arg.Trim())); } if (newOption != null) // Previous command has been constructed { inputObject.options.Add(newOption); } newOption = new CliOption { Name = arg.Trim() }; }
public CliInput ParseArgs() { var inputObject = new CliInput(); CliOption newOption = null; foreach (var arg in args) { ParseArg(arg, ref newOption, ref inputObject); } if (newOption != null) { inputObject.options.Add(newOption); } ValidateInputObject(inputObject); return(inputObject); }
// generate option type name: // <base_type>[ list] <(optional)|(required)> private static string GetOptionTypeName(CliOption option) { string type; switch (option.Type) { case OptionType.Boolean: type = "bool"; break; case OptionType.String: case OptionType.StringEnum: case OptionType.JSONImport: type = "string"; break; case OptionType.DatabaseObjectFilter: type = "(string | object)"; break; case OptionType.Naming: type = "object"; break; case OptionType.StringDictionary: type = "[string]: string"; break; default: throw new NotImplementedException($"Option type {option.Type} not implemented"); } if (option.AllowMultiple && option.Type != OptionType.StringDictionary) { type += " list"; } return(type + (option.Required ? " (required)" : " (optional)")); }
private void AddCompletedOption(string arg, ref CliOption newOption, ref CliInput inputObject) { if (newOption != null && newOption.ShouldHaveValue()) { newOption.Value = arg; inputObject.options.Add(newOption); newOption = null; } else { // Not a option value, so check if this is a file newOption = null; if (String.IsNullOrWhiteSpace(inputObject.InFile) && (!Console.IsInputRedirected || (Console.IsInputRedirected && Console.In.Peek() == -1))) { inputObject.InFile = arg.Trim(); } else { inputObject.OutFile = arg.Trim(); } } }
private static T GetOption <TV, T>(TV cliValue, CliOption <T> option) { return(cliValue != null ? ConvertTo(cliValue, option) : option.DefaultValue); }
public static bool IsMatch(this string subject, CliOption option) { return(option.Regex.IsMatch(subject)); }
private void WriteOptionHelp(CliCommand command, int maxOptionNameWidth, string indent, OptionCategory?category, CliOption option) { // workaround for https://github.com/linq2db/linq2db/issues/3612 var consoleWidth = 80; try { consoleWidth = Console.BufferWidth; } catch { }; Console.Out.WriteLine(); Console.Out.Write(" "); var optionNameWidth = GetOptionWidth(option); var type = GetOptionTypeName(option); if (option.AllowInCli) { // -x, --x-option : <help> if (option.ShortName != null) { Console.Out.Write("-{0}, ", option.ShortName.Value); } Console.Out.Write("--{0}", option.Name); Console.Out.Write(new string(' ', maxOptionNameWidth - optionNameWidth + 2)); Console.Out.WriteLine(" : {0}", option.Help); } else if (command.SupportsJSON) { // json-option : (allowed only in JSON) <help> Console.Out.Write(" {0}", option.Name); Console.Out.Write(new string(' ', maxOptionNameWidth - optionNameWidth + 2)); Console.Out.WriteLine(" : (allowed only in JSON) {0}", option.Help); } // option data type Console.Out.Write("{0} type: ", indent); Console.Out.WriteLine(type); // display options, that cannot be used together with current option var incompatibleWith = command.GetIncompatibleOptions(option); if (incompatibleWith != null) { Console.Out.WriteLine("{0} cannot use with: {1}", indent, string.Join(", ", incompatibleWith.Select(o => $"--{o.Name}"))); } if (command.SupportsJSON) { // option property path in json or "not allowed" text if not supported Console.Out.Write("{0} json: ", indent); if (option.AllowInJson) { if (category != null) { Console.Out.WriteLine("{0}.{1}", category.JsonProperty, option.Name); } else { Console.Out.WriteLine("{0}", option.Name); } } else { Console.Out.WriteLine("not allowed"); } } // print default value (if set) for non-required option if (!option.Required) { if (option is BooleanCliOption booleanOption) { Console.Out.WriteLine("{0} default: {1}", indent, booleanOption.Default ? "true" : "false"); Console.Out.WriteLine("{0} default (T4 mode): {1}", indent, booleanOption.T4Default ? "true" : "false"); } if (option is StringCliOption stringOption) { if (stringOption.Default != null) { if (!stringOption.AllowMultiple) { Console.Out.WriteLine("{0} default: {1}", indent, stringOption.Default[0]); } else { Console.Out.WriteLine("{0} default: {1}", indent, string.Join(",", stringOption.Default)); } } if (stringOption.T4Default != null) { if (!stringOption.AllowMultiple) { Console.Out.WriteLine("{0} default (T4 mode): {1}", indent, stringOption.T4Default[0]); } else { Console.Out.WriteLine("{0} default (T4 mode): {1}", indent, string.Join(",", stringOption.T4Default)); } } } else if (option is StringEnumCliOption enumOption) { var defaults = enumOption.Values.Where(o => o.Default).Select(o => o.Value).ToArray(); if (defaults.Length > 0) { Console.Out.WriteLine("{0} default: {1}", indent, string.Join(", ", defaults)); } defaults = enumOption.Values.Where(o => o.T4Default).Select(o => o.Value).ToArray(); if (defaults.Length > 0) { Console.Out.WriteLine("{0} default (T4 mode): {1}", indent, string.Join(", ", defaults)); } } else if (option is NamingCliOption namingOption) { if (namingOption.Default != null) { PrintNamingOptionDefaults(indent, "default", namingOption.Default); } if (namingOption.T4Default != null) { PrintNamingOptionDefaults(indent, "default (T4 mode)", namingOption.T4Default); } } } // for enum-typed option print list of supported values with description if (option is StringEnumCliOption enumStringOption) { Console.Out.WriteLine("{0} supported values:", indent); var maxValueWidth = enumStringOption.Values.Select(_ => _.Value.Length).Max(); foreach (var value in enumStringOption.Values) { Console.Out.WriteLine("{0}{0} {1}{3} : {2}", indent, value.Value, value.Help, new string(' ', maxValueWidth - value.Value.Length)); } } // print option CLI and JSON examples if provided if (option.Examples != null) { Console.Out.WriteLine("{0} examples:", indent); foreach (var example in option.Examples) { Console.Out.WriteLine("{0}{0} {1}", indent, example); } } if (option.JsonExamples != null) { Console.Out.WriteLine("{0} JSON examples:", indent); foreach (var example in option.JsonExamples) { Console.Out.WriteLine("{0}{0} {1}", indent, example); } } // print detailed option help if provided if (option.DetailedHelp != null) { Console.Out.WriteLine(); // split long text into lines manually and prepend each line with help indent for nicer formatting // TODO: dunno wether it works on linux/macos, not tested yet var lines = option.DetailedHelp.Split("\r\n"); for (var i = 0; i < lines.Length; i++) { var line = lines[i]; var lineWidth = consoleWidth - indent.Length - 1; var incompleteLineLength = line.Length % lineWidth; var partsCount = line.Length / lineWidth + (incompleteLineLength > 0 ? 1 : 0); for (var j = 0; j < partsCount; j++) { var part = line.Substring( j * lineWidth, j == partsCount - 1 && incompleteLineLength > 0 ? incompleteLineLength : lineWidth); Console.Out.Write(indent); Console.Out.WriteLine(part); } } } }
private static CommandOption CreateOption <T>(CommandLineApplication app, CliOption <T> option) { return(app.Option($"{option.ArgumentName} | {option.ArgumentShortName}", option.ArgumentDescription, option.ValueType)); }