diff --git a/src/Neo.ConsoleService/ConsoleServiceBase.cs b/src/Neo.ConsoleService/ConsoleServiceBase.cs index 6a4ae14df5..720cbeba08 100644 --- a/src/Neo.ConsoleService/ConsoleServiceBase.cs +++ b/src/Neo.ConsoleService/ConsoleServiceBase.cs @@ -49,9 +49,9 @@ public abstract class ConsoleServiceBase /// For example, if a method defined as `void Method(string arg1, int arg2, bool arg3)`, /// the arguments will be parsed as `"arg1" 2 true`. /// - /// Method - /// Arguments - /// Arguments + /// the MethodInfo of the called method + /// the raw arguments + /// the parsed arguments /// Missing argument internal object?[] ParseSequentialArguments(MethodInfo method, IList args) { @@ -78,8 +78,9 @@ public abstract class ConsoleServiceBase /// For example, if a method defined as `void Method(string arg1, int arg2, bool arg3)`, /// the arguments will be parsed as `Method --arg1 "arg1" --arg2 2 --arg3`. /// - /// Method - /// Arguments + /// the MethodInfo of the called method + /// the raw arguments + /// the parsed arguments internal object?[] ParseIndicatorArguments(MethodInfo method, IList args) { var parameters = method.GetParameters(); @@ -199,6 +200,18 @@ private bool TryProcessValue(Type parameterType, IList args, bool #region Commands + private static string ParameterGuide(ParameterInfo info) + { + if (info.HasDefaultValue) + { + var defaultValue = info.DefaultValue?.ToString(); + return string.IsNullOrEmpty(defaultValue) ? + $"[ --{info.Name} {info.ParameterType.Name} ]" : + $"[ --{info.Name} {info.ParameterType.Name}({defaultValue}) ]"; + } + return $"--{info.Name} {info.ParameterType.Name}"; + } + /// /// Process "help" command /// @@ -229,17 +242,10 @@ protected void OnHelpCommand(string key = "") // Sort and show withHelp.Sort((a, b) => { - var cate = string.Compare(a.HelpCategory, b.HelpCategory, StringComparison.Ordinal); - if (cate == 0) - { - cate = string.Compare(a.Key, b.Key, StringComparison.Ordinal); - } - return cate; + var category = string.Compare(a.HelpCategory, b.HelpCategory, StringComparison.Ordinal); + return category == 0 ? string.Compare(a.Key, b.Key, StringComparison.Ordinal) : category; }); - var guide = (ParameterInfo parameterInfo) => parameterInfo.HasDefaultValue - ? $"[ --{parameterInfo.Name} {parameterInfo.DefaultValue?.ToString() ?? ""}]" - : $"--{parameterInfo.Name}"; if (string.IsNullOrEmpty(key) || key.Equals("help", StringComparison.InvariantCultureIgnoreCase)) { string? last = null; @@ -252,40 +258,94 @@ protected void OnHelpCommand(string key = "") } Console.Write($"\t{command.Key}"); - Console.WriteLine(" " + string.Join(' ', command.Method.GetParameters().Select(guide))); + Console.WriteLine(" " + string.Join(' ', command.Method.GetParameters().Select(ParameterGuide))); } } else { - // Show help for this specific command - string? last = null; - string? lastKey = null; - bool found = false; + ShowHelpForCommand(key, withHelp); + } + } - foreach (var command in withHelp.Where(u => u.Key == key)) + /// + /// Show help for a specific command + /// + /// Command key + /// List of commands + private void ShowHelpForCommand(string key, List withHelp) + { + bool found = false; + string helpMessage = string.Empty; + string lastKey = string.Empty; + foreach (var command in withHelp.Where(u => u.Key == key)) + { + found = true; + if (helpMessage != command.HelpMessage) { - found = true; - if (last != command.HelpMessage) - { - Console.WriteLine($"{command.HelpMessage}"); - last = command.HelpMessage; - } - - if (lastKey != command.Key) - { - Console.WriteLine("You can call this command like this:"); - lastKey = command.Key; - } + Console.WriteLine($"{command.HelpMessage}"); + helpMessage = command.HelpMessage; + } - Console.Write($"\t{command.Key}"); - Console.WriteLine(" " + string.Join(' ', command.Method.GetParameters().Select(guide))); + if (lastKey != command.Key) + { + Console.WriteLine("You can call this command like this:"); + lastKey = command.Key; } - if (!found) + Console.Write($"\t{command.Key}"); + Console.WriteLine(" " + string.Join(' ', command.Method.GetParameters().Select(ParameterGuide))); + + var parameters = command.Method.GetParameters(); + if (parameters.Length > 0) // Show parameter info for this command { - throw new ArgumentException($"Command '{key}' not found. Use 'help' to see available commands."); + Console.WriteLine($"Parameters for command `{command.Key}`:"); + foreach (var item in parameters) + { + var info = item.HasDefaultValue ? $"(optional, default: {item.DefaultValue?.ToString() ?? "null"})" : "(required)"; + Console.WriteLine($"\t{item.Name}: {item.ParameterType.Name} {info}"); + } } } + + if (!found) + throw new ArgumentException($"Command '{key}' not found. Use 'help' to see available commands."); + + Console.WriteLine(); + Console.WriteLine("You can also use 'how to input' to see how to input arguments."); + } + + /// + /// Show `how to input` guide + /// + [ConsoleCommand("how to input", Category = "Base Commands")] + internal void OnHowToInput() + { + Console.WriteLine(""" + 1. Sequential Arguments (Positional) + Arguments are provided in the order they appear in the method signature. + Usage: + > create wallet "path/to/wallet" + > create wallet "path/to/wallet" "wif-or-file" "wallet-name" + + Note: String values can be quoted or unquoted. Use quotes for values with spaces. + + 2. Indicator Arguments (Named Parameters) + Arguments are provided with parameter names prefixed with "--", and parameter order doesn't matter. + Usage: + > create wallet --path "path/to/wallet" + > create wallet --path "path/to/wallet" --wifOrFile "wif-or-file" --walletName "wallet-name" + + 3. Tips: + - String: Can be quoted or unquoted, use quotes for spaces. It's recommended to use quotes for complex values. + - String[]: Use comma-separated or space-separated values, If space separated, it must be the last argument. + - UInt160, UInt256: Specified in hex format, for example: 0x1234567890abcdef1234567890abcdef12345678 + - Numeric: Standard number parsing + - Boolean: Can be specified without a value (defaults to true), true/false, 1/0, yes/no, y/n + - Enum: Case-insensitive enum value names + - JSON: Input as JSON string + - Escape characters: \\, \", \', \n, \r, \t, \v, \b, \f, \a, \e, \0, \ (whitespace). + If want to input without escape, quote the value with backtick(`). + """); } ///