Esempio n. 1
0
        /// <summary>
        /// Prints help text for specific command.
        /// </summary>
        /// <param name="command">Command descriptor.</param>
        /// <param name="unknownArgs">List of unrecognized command-line arguments.</param>
        private void PrintCommandHelp(CliCommand command, IReadOnlyCollection <string> unknownArgs)
        {
            PrintHeader();

            PrintBadArgumentsError(unknownArgs);

            Console.Out.WriteLine();
            Console.Out.WriteLine("Usage:");
            Console.Out.WriteLine("        dotnet linq2db {0}{1}", command.Name, command.Template != string.Empty ? " " + command.Template : command.Template);

            Console.Out.WriteLine();
            Console.Out.WriteLine("Options:");

            // calculate column width for column layout
            var maxOptionNameWidth = 0;
            var maxOptionTypeWidth = 0;

            foreach (var option in command.GetOptionsWithoutCategory())
            {
                CalculateOptionSizes(option);
            }

            foreach (var category in command.Categories)
            {
                foreach (var option in command.GetCategoryOptions(category))
                {
                    CalculateOptionSizes(option);
                }
            }

            // print options help grouped by option category
            const string indent = "      ";

            foreach (var option in command.GetOptionsWithoutCategory())
            {
                WriteOptionHelp(command, maxOptionNameWidth, indent, null, option);
            }

            foreach (var category in command.Categories)
            {
                Console.Out.WriteLine();
                Console.Out.WriteLine("=== {0} : {1}", category.Name, category.Description);

                foreach (var option in command.GetCategoryOptions(category))
                {
                    WriteOptionHelp(command, maxOptionNameWidth, indent, category, option);
                }
            }

            // print command examples
            if (command.Examples.Count > 0)
            {
                Console.Out.WriteLine();
                Console.Out.WriteLine("Examples:");

                foreach (var example in command.Examples)
                {
                    Console.Out.WriteLine();
                    Console.Out.WriteLine("        {0}", example.Command);
                    Console.Out.WriteLine("                {0}", example.Help);
                }
            }

            void CalculateOptionSizes(CliOption option)
            {
                var optionWidth = GetOptionWidth(option);
                var typeWidth   = GetOptionTypeName(option).Length;

                if (optionWidth > maxOptionNameWidth)
                {
                    maxOptionNameWidth = optionWidth;
                }

                if (typeWidth > maxOptionTypeWidth)
                {
                    maxOptionTypeWidth = typeWidth;
                }
            }
        }
Esempio n. 2
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);
                    }
                }
            }
        }