diff --git a/Commander.NET/Command.cs b/Commander.NET/Command.cs new file mode 100644 index 0000000..a60daf7 --- /dev/null +++ b/Commander.NET/Command.cs @@ -0,0 +1,126 @@ +using System.Text; + +namespace Commander_Net; + +public class Command +{ + public string[] Identifiers { get; init; } + public Func Method { get; init; } + public HelpText HelpText { get; init; } + + internal readonly List subCommands = new(); + + internal Command(Func method, HelpText description, string[] identifiers) + { + Method = method; + HelpText = description; + Identifiers = identifiers; + } + + public Command() + { + Identifiers = Array.Empty(); + HelpText = string.Empty; + Method = new Func((_) => CommandResult.Success); + } + + public Command Register(Action method, params string[] identifiers) + { + return Register(method, new HelpText(), identifiers); + } + + public Command Register(Func method, params string[] identifiers) + { + return Register(method, new HelpText(), identifiers); + } + + public Command Register(Action method, HelpText description, params string[] identifiers) + { + Func commandMethod = (input) => + { + method(input); + return new CommandResult(ResultType.Success); + }; + + return Register(commandMethod, description, identifiers); + } + + public Command Register(Func method, HelpText description, params string[] identifiers) + { + Command command = new Command(method, description, identifiers); + Register(command); + return command; + } + + public Command Register(Command command) + { + subCommands.Add(command); + return command; + } + + internal List ExecuteMultible(string input, List? commandResults = null) + { + string[] inputParts = input.Split(' '); + bool found = false; + + commandResults ??= new List(); + + foreach (Command? command in subCommands.Where(command => command.Identifiers.Contains(inputParts[0]))) + { + command.ExecuteMultible(string.Join(' ', inputParts.Skip(1)), commandResults); + found = true; + } + + if (!found) + { + CommandResult result; + try + { + result = Method(input); + } + catch (Exception) + { + result = new CommandResult(ResultType.UnexpectedError); + } + + commandResults.Add(result); + } + + return commandResults; + } + + internal CommandResult Execute(string input) + { + string[] inputParts = input.Split(' '); + + Command? command = subCommands.FirstOrDefault(command => command.Identifiers.Contains(inputParts[0])); + + if (command is not null) + { + return command.Execute(string.Join(' ', inputParts.Skip(1))); + } + + try + { + return Method(input); + } + catch (Exception) + { + return new CommandResult(ResultType.UnexpectedError); + } + } + + internal string GetHelp(string input) + { + string[] inputParts = input.Split(' '); + + StringBuilder helpText = new StringBuilder($"{string.Join(" | ", Identifiers)} > {HelpText?.Description}"); + + foreach (Command command in subCommands.Where(command => command.Identifiers.Contains(inputParts[0]) || string.IsNullOrWhiteSpace(input))) + { + helpText.Append($"{Environment.NewLine} {command.GetHelp(string.Join(' ', inputParts.Skip(1)))}"); + } + + return helpText.ToString(); + } +} \ No newline at end of file diff --git a/Commander.NET/CommandResult.cs b/Commander.NET/CommandResult.cs new file mode 100644 index 0000000..d8f4393 --- /dev/null +++ b/Commander.NET/CommandResult.cs @@ -0,0 +1,17 @@ +namespace Commander_Net; + +public class CommandResult +{ + public ResultType ResultType { get; } + public string Message { get; } + + public static CommandResult Success => new CommandResult(ResultType.Success); + public static CommandResult InvalidInput => new CommandResult(ResultType.InvalidInput); + public static CommandResult InternalError => new CommandResult(ResultType.InternalError); + + public CommandResult(ResultType type, string message = "") + { + ResultType = type; + Message = message; + } +} \ No newline at end of file diff --git a/Commander.NET/CommandResults.cs b/Commander.NET/CommandResults.cs new file mode 100644 index 0000000..ef3b3a7 --- /dev/null +++ b/Commander.NET/CommandResults.cs @@ -0,0 +1,9 @@ +namespace Commander_Net; + +public enum ResultType +{ + Success, + InvalidInput, + InternalError, + UnexpectedError +} \ No newline at end of file diff --git a/Commander.NET/Commander.NET.csproj b/Commander.NET/Commander.NET.csproj index 132c02c..da42ded 100644 --- a/Commander.NET/Commander.NET.csproj +++ b/Commander.NET/Commander.NET.csproj @@ -4,6 +4,28 @@ net6.0 enable enable + True + README.md + LICENSE + Console.$(AssemblyName) + Commander_Net + https://github.com/Stone-Red-Code/Commander.NET + CLI, Console, Commands + $(AssemblyName) + 1.0.1.0 + 1.0.1.0 + 1.0.1.0 - + + + True + \ + + + True + \ + + + + \ No newline at end of file diff --git a/Commander.NET/Commander.cs b/Commander.NET/Commander.cs index 7a9df2a..8ae735f 100644 --- a/Commander.NET/Commander.cs +++ b/Commander.NET/Commander.cs @@ -1,45 +1,6 @@ -namespace Commander_Net; +using System.Text; -public class Command -{ - internal string[] Identifiers { get; } - - internal readonly Action method; - internal readonly List subCommands = new(); - - public Command(Action method, string[] identifiers) - { - this.method = method; - Identifiers = identifiers; - } - - public Command Register(Action method, params string[] identifiers) - { - Command command = new Command(method, identifiers); - subCommands.Add(command); - return command; - } - - internal void Execute(string input) - { - string[] inputParts = input.Split(' '); - bool found = false; - - foreach (Command? command in subCommands) - { - if (command.Identifiers.Contains(inputParts[0])) - { - command.Execute(string.Join(' ', inputParts.Skip(1))); - found = true; - } - } - - if (!found) - { - method.Invoke(input); - } - } -} +namespace Commander_Net; public class Commander { @@ -47,25 +8,89 @@ public class Commander public Command Register(Action method, params string[] identifiers) { - Command command = new Command(method, identifiers); + return Register(method, new HelpText(), identifiers); + } + + public Command Register(Func method, params string[] identifiers) + { + return Register(method, new HelpText(), identifiers); + } + + public Command Register(Action method, HelpText description, params string[] identifiers) + { + Func commandMethod = (input) => + { + method(input); + return new CommandResult(ResultType.Success); + }; + + return Register(commandMethod, description, identifiers); + } + + public Command Register(Func method, HelpText description, params string[] identifiers) + { + Command command = new Command(method, description, identifiers); + Register(command); + return command; + } + + public Command Register(Command command) + { commands.Add(command); return command; } - public bool Execute(string input) + public bool ExecuteMultible(string input, out List commandResults) { + List internalCommandResults = new List(); string[] inputParts = input.Split(' '); bool found = false; - - foreach (Command? command in commands) + foreach (Command? command in commands.Where(command => command.Identifiers.Contains(inputParts[0]))) { - if (command.Identifiers.Contains(inputParts[0])) - { - command.Execute(string.Join(' ', inputParts.Skip(1))); - found = true; - } + List tempCommandResults = command.ExecuteMultible(string.Join(' ', inputParts.Skip(1))); + internalCommandResults.AddRange(tempCommandResults); + found = true; } + commandResults = internalCommandResults; return found; } + + public bool Execute(string input, out CommandResult? commandResult) + { + string[] inputParts = input.Split(' '); + + Command? command = commands.FirstOrDefault(command => command.Identifiers.Contains(inputParts[0])); + + if (command is null) + { + commandResult = null; + return false; + } + + commandResult = command.Execute(string.Join(' ', inputParts.Skip(1))); + return true; + } + + public bool GetHelp(string input, out string helpText) + { + string[] inputParts = input.Split(' '); + + StringBuilder internalHelpText = new StringBuilder(); + + foreach (Command command in commands.Where(command => command.Identifiers.Contains(inputParts[0]) || string.IsNullOrWhiteSpace(input))) + { + internalHelpText.AppendLine(command.GetHelp(string.Join(' ', inputParts.Skip(1)))); + } + + helpText = internalHelpText.ToString(); + return !string.IsNullOrWhiteSpace(helpText); + } + + public bool PrintHelp(string input) + { + bool result = GetHelp(input, out string helpText); + Console.WriteLine(helpText.TrimEnd('\n', '\r')); + return result; + } } \ No newline at end of file diff --git a/Commander.NET/HelpText.cs b/Commander.NET/HelpText.cs new file mode 100644 index 0000000..e75587c --- /dev/null +++ b/Commander.NET/HelpText.cs @@ -0,0 +1,19 @@ +namespace Commander_Net; + +public class HelpText +{ + public string? Description { get; init; } + + public HelpText(string? description) + { + Description = description; + } + + internal HelpText() + { } + + public static implicit operator HelpText(string helpText) + { + return new HelpText(helpText); + } +} \ No newline at end of file diff --git a/Commander.Test/Commander.Test.csproj b/Commander.Test/Commander.Test.csproj index 5dc6124..1bc5fe9 100644 --- a/Commander.Test/Commander.Test.csproj +++ b/Commander.Test/Commander.Test.csproj @@ -5,6 +5,7 @@ net6.0 enable enable + False diff --git a/Commander.Test/Program.cs b/Commander.Test/Program.cs index cf01a48..7d85d3d 100644 --- a/Commander.Test/Program.cs +++ b/Commander.Test/Program.cs @@ -3,17 +3,38 @@ Console.WriteLine("Hello, World!"); Commander commander = new Commander(); -Command sayCommand = commander.Register(HahaYes, "say", "tell"); +Command sayCommand = commander.Register(HahaYes, "say", "yell"); sayCommand.Register(HahaYesSub, "kek"); commander.Register(HahaNo, "scream", "yell"); commander.Register((args) => Console.Clear(), "clear"); +commander.Register((input) => commander.PrintHelp(input) ? CommandResult.Success : CommandResult.InvalidInput, "help"); + +Command fancyCommand = commander.Register(_ => new CommandResult(ResultType.InvalidInput, "How about no?"), "fancy"); +fancyCommand.Register(new Command() +{ + Identifiers = new string[] { "yes", "YES" }, + HelpText = "Says that the input is fancy", + + Method = (i) => { Console.WriteLine($"Yes, {i} is very fancy!"); return new CommandResult(ResultType.Success); } +}); + +fancyCommand.Register(new Command() +{ + Identifiers = new string[] { "no", "NO" }, + HelpText = "Says that the input is not fancy", + Method = (i) => { Console.WriteLine($"Yes, {i} is not very fancy!"); return new CommandResult(ResultType.Success); } +}); while (true) { - if (!commander.Execute(Console.ReadLine()!)) + if (commander.ExecuteMultible(Console.ReadLine()!, out List commandResult)) { - Console.WriteLine("Command not found!"); + commandResult.ForEach((e) => Console.WriteLine(e.ResultType + " " + e.Message)); + } + else + { + Console.WriteLine("xxx Command not found!"); } } @@ -27,7 +48,14 @@ void HahaYesSub(string yes) Console.WriteLine($">>> {yes} xD"); } -void HahaNo(string no) +CommandResult HahaNo(string no) { + if (string.IsNullOrWhiteSpace(no)) + { + return new CommandResult(ResultType.InvalidInput, "fuck off"); + } + Console.WriteLine($">>> {no.ToUpper()}"); + + return new CommandResult(ResultType.Success); } \ No newline at end of file