예제 #1
0
        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}");
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        private static int GetOptionWidth(CliOption option)
        {
            var width = option.Name.Length;

            if (option.ShortName != null)
            {
                width += 4;
            }
            return(width);
        }
예제 #4
0
        //[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));
        }
예제 #5
0
 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);
     }
 }
예제 #6
0
        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()
            };
        }
예제 #7
0
        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);
        }
예제 #8
0
        // 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)"));
        }
예제 #9
0
        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();
                }
            }
        }
예제 #10
0
 private static T GetOption <TV, T>(TV cliValue, CliOption <T> option)
 {
     return(cliValue != null
         ? ConvertTo(cliValue, option)
         : option.DefaultValue);
 }
예제 #11
0
 public static bool IsMatch(this string subject, CliOption option)
 {
     return(option.Regex.IsMatch(subject));
 }
예제 #12
0
        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);
                    }
                }
            }
        }
예제 #13
0
 private static CommandOption CreateOption <T>(CommandLineApplication app, CliOption <T> option)
 {
     return(app.Option($"{option.ArgumentName} | {option.ArgumentShortName}",
                       option.ArgumentDescription,
                       option.ValueType));
 }