diff --git a/Cli.NET/Cli.NET.Abstractions/Actions/ICommand.cs b/Cli.NET/Cli.NET.Abstractions/Actions/ICommand.cs new file mode 100644 index 0000000..8145b34 --- /dev/null +++ b/Cli.NET/Cli.NET.Abstractions/Actions/ICommand.cs @@ -0,0 +1,7 @@ +namespace Cli.NET.Abstractions.Actions +{ + public interface ICommand + { + public void Execute(string[] arguments); + } +} \ No newline at end of file diff --git a/Cli.NET/Cli.NET.Abstractions/Cli.NET.Abstractions.csproj b/Cli.NET/Cli.NET.Abstractions/Cli.NET.Abstractions.csproj new file mode 100644 index 0000000..132c02c --- /dev/null +++ b/Cli.NET/Cli.NET.Abstractions/Cli.NET.Abstractions.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/Cli.NET/Cli.NET.Console/Cli.NET.Console.csproj b/Cli.NET/Cli.NET.Console/Cli.NET.Console.csproj new file mode 100644 index 0000000..16d8e90 --- /dev/null +++ b/Cli.NET/Cli.NET.Console/Cli.NET.Console.csproj @@ -0,0 +1,15 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + diff --git a/Cli.NET/Cli.NET.Console/Program.cs b/Cli.NET/Cli.NET.Console/Program.cs new file mode 100644 index 0000000..90b2fe6 --- /dev/null +++ b/Cli.NET/Cli.NET.Console/Program.cs @@ -0,0 +1,15 @@ +using Cli.NET.Actions; +using Cli.NET.Tools; + +var container = new CommandContainer(); + +container.Register(new() +{ + { "exit", new ExitCommand() }, + { "echo", new EchoCommand() }, + { "sum", new SumCommand() }, + { "clear", new ClearCommand() }, + { "cls", new ClearCommand() } +}); + +container.WaitForNextCommand(); \ No newline at end of file diff --git a/Cli.NET/Cli.NET.sln b/Cli.NET/Cli.NET.sln new file mode 100644 index 0000000..063e6d9 --- /dev/null +++ b/Cli.NET/Cli.NET.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli.NET", "Cli.NET\Cli.NET.csproj", "{071AAB32-CFAB-4A02-9203-9E0A1D831DB4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli.NET.Abstractions", "Cli.NET.Abstractions\Cli.NET.Abstractions.csproj", "{4887C5D7-2C3B-4E33-B7A5-DF48571FF08F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli.NET.Console", "Cli.NET.Console\Cli.NET.Console.csproj", "{B57D8554-6089-4093-9251-9CE6A30B7D6C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RepositoryItems", "RepositoryItems", "{FE91112C-5E7A-4C53-8708-5EEF11074BE7}" + ProjectSection(SolutionItems) = preProject + ..\README.MD = ..\README.MD + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {071AAB32-CFAB-4A02-9203-9E0A1D831DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {071AAB32-CFAB-4A02-9203-9E0A1D831DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {071AAB32-CFAB-4A02-9203-9E0A1D831DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {071AAB32-CFAB-4A02-9203-9E0A1D831DB4}.Release|Any CPU.Build.0 = Release|Any CPU + {4887C5D7-2C3B-4E33-B7A5-DF48571FF08F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4887C5D7-2C3B-4E33-B7A5-DF48571FF08F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4887C5D7-2C3B-4E33-B7A5-DF48571FF08F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4887C5D7-2C3B-4E33-B7A5-DF48571FF08F}.Release|Any CPU.Build.0 = Release|Any CPU + {B57D8554-6089-4093-9251-9CE6A30B7D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B57D8554-6089-4093-9251-9CE6A30B7D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B57D8554-6089-4093-9251-9CE6A30B7D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B57D8554-6089-4093-9251-9CE6A30B7D6C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {03167DE2-D179-434A-AE02-A17D4058BBE4} + EndGlobalSection +EndGlobal diff --git a/Cli.NET/Cli.NET/Actions/ClearCommand.cs b/Cli.NET/Cli.NET/Actions/ClearCommand.cs new file mode 100644 index 0000000..dac4c3d --- /dev/null +++ b/Cli.NET/Cli.NET/Actions/ClearCommand.cs @@ -0,0 +1,19 @@ +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + /// + /// Default example "clear" command to erase the information in the screen + /// and writes new information if given. + /// + public class ClearCommand : ICommand + { + public void Execute(string[] arguments) + { + Console.Clear(); + + if(arguments.Any()) + Console.WriteLine(string.Join("", arguments)); + } + } +} \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Actions/EchoCommand.cs b/Cli.NET/Cli.NET/Actions/EchoCommand.cs new file mode 100644 index 0000000..b00cec1 --- /dev/null +++ b/Cli.NET/Cli.NET/Actions/EchoCommand.cs @@ -0,0 +1,12 @@ +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + /// + /// Default example "echo" command to display data in the console. + /// + public class EchoCommand : ICommand + { + public void Execute(string[] arguments) => Console.WriteLine(string.Join(" ", arguments)); + } +} \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Actions/ExitCommand.cs b/Cli.NET/Cli.NET/Actions/ExitCommand.cs new file mode 100644 index 0000000..b2e22df --- /dev/null +++ b/Cli.NET/Cli.NET/Actions/ExitCommand.cs @@ -0,0 +1,17 @@ +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + public class ExitCommand : ICommand + { + /// + /// Default example "exit" command with a given exit code. + /// + /// + public void Execute(string[] args) + { + try { Environment.Exit(int.Parse(args[0])); } + catch { Environment.Exit(0); } + } + } +} \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Actions/SumCommand.cs b/Cli.NET/Cli.NET/Actions/SumCommand.cs new file mode 100644 index 0000000..811f266 --- /dev/null +++ b/Cli.NET/Cli.NET/Actions/SumCommand.cs @@ -0,0 +1,13 @@ +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + public class SumCommand : ICommand + { + public void Execute(string[] arguments) + { + try { Console.WriteLine(long.Parse(arguments[0]) + long.Parse(arguments[1])); } + catch { Console.WriteLine("NaN"); } + } + } +} \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Cli.NET.csproj b/Cli.NET/Cli.NET/Cli.NET.csproj new file mode 100644 index 0000000..fca84ef --- /dev/null +++ b/Cli.NET/Cli.NET/Cli.NET.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/Cli.NET/Cli.NET/Extensions/ParameterExtensions.cs b/Cli.NET/Cli.NET/Extensions/ParameterExtensions.cs new file mode 100644 index 0000000..62748ae --- /dev/null +++ b/Cli.NET/Cli.NET/Extensions/ParameterExtensions.cs @@ -0,0 +1,31 @@ +namespace Cli.NET.Extensions +{ + public static class ParameterExtensions + { + public static IDictionary GetArguments(this string[] parameters) + { + Dictionary arguments = new(); + + var targets = parameters.Skip(1); + var argumentHeader = string.Empty; + var argumentInformation = string.Empty; + + int currentHeaderIndex = -1; + foreach (var target in targets) + { + if (target.StartsWith("-")) + { + currentHeaderIndex++; + argumentHeader = target; + } + else + { + argumentInformation += target; + arguments.Add(argumentHeader, argumentInformation); + } + } + + return arguments; + } + } +} diff --git a/Cli.NET/Cli.NET/Models/CommandList.cs b/Cli.NET/Cli.NET/Models/CommandList.cs new file mode 100644 index 0000000..dec4731 --- /dev/null +++ b/Cli.NET/Cli.NET/Models/CommandList.cs @@ -0,0 +1,4 @@ +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Models; +public class CommandList : Dictionary {} \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Models/Output/Output.cs b/Cli.NET/Cli.NET/Models/Output/Output.cs new file mode 100644 index 0000000..a9f7eea --- /dev/null +++ b/Cli.NET/Cli.NET/Models/Output/Output.cs @@ -0,0 +1,19 @@ +namespace Cli.NET.Models +{ + public class Output + { + /// + /// Output default model to manage console responses. + /// + /// + /// + public Output(string message, OutputType type) + { + Message = message; + Type = type; + } + + public OutputType Type { get; set; } + public string Message { get; set; } + } +} diff --git a/Cli.NET/Cli.NET/Models/Output/OutputType.cs b/Cli.NET/Cli.NET/Models/Output/OutputType.cs new file mode 100644 index 0000000..5a225b8 --- /dev/null +++ b/Cli.NET/Cli.NET/Models/Output/OutputType.cs @@ -0,0 +1,9 @@ +namespace Cli.NET.Models +{ + public enum OutputType + { + Message, + Warning, + Error + } +} diff --git a/Cli.NET/Cli.NET/Models/OutputList.cs b/Cli.NET/Cli.NET/Models/OutputList.cs new file mode 100644 index 0000000..e539273 --- /dev/null +++ b/Cli.NET/Cli.NET/Models/OutputList.cs @@ -0,0 +1,2 @@ +namespace Cli.NET.Models; +public class OutputList : Dictionary { } \ No newline at end of file diff --git a/Cli.NET/Cli.NET/Tools/CLNConsole.cs b/Cli.NET/Cli.NET/Tools/CLNConsole.cs new file mode 100644 index 0000000..66ac782 --- /dev/null +++ b/Cli.NET/Cli.NET/Tools/CLNConsole.cs @@ -0,0 +1,55 @@ +namespace Cli.NET.Tools +{ + public static class CLNConsole + { + public static void WriteLine(string message) => Console.WriteLine(message); + public static void WriteLine(string message, string color) => WriteLine(message, Enum.Parse(color)); + public static void WriteLine(string message, int color) => WriteLine(message, (ConsoleColor)color); + public static void WriteLine(string message, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.WriteLine(message); + Console.ResetColor(); + } + + public static void Write(string message) => Console.Write(message); + public static void Write(string message, string color) => Write(message, Enum.Parse(color)); + public static void Write(string message, int color) => Write(message, (ConsoleColor)color); + public static void Write(string message, ConsoleColor color) + { + Console.ForegroundColor = color; + Console.Write(message); + Console.ResetColor(); + } + + public static string ReadText() => Console.ReadLine() ?? string.Empty; + public static string? ReadText(uint minLength = 0, uint maxLength = int.MaxValue) + { + string input = ReadText(); + + if (input.Length > maxLength || input.Length < minLength) + return null; + + return input; + } + + public static string? DataQuestion(string message) + { + WriteLine(message); + return ReadText(); + } + public static string? DataQuestion(string message, string color, uint minLength = 0, uint maxLength = int.MaxValue) + { + return DataQuestion(message, Enum.Parse(color), minLength, maxLength); + } + public static string? DataQuestion(string message, int color, uint minLength = 0, uint maxLength = int.MaxValue) + { + return DataQuestion(message, (ConsoleColor)color, minLength, maxLength); + } + public static string? DataQuestion(string message, ConsoleColor color, uint minLength = 0, uint maxLength = int.MaxValue) + { + WriteLine(message, color); + return ReadText(minLength, maxLength); + } + } +} diff --git a/Cli.NET/Cli.NET/Tools/CommandContainer.cs b/Cli.NET/Cli.NET/Tools/CommandContainer.cs new file mode 100644 index 0000000..adaf540 --- /dev/null +++ b/Cli.NET/Cli.NET/Tools/CommandContainer.cs @@ -0,0 +1,146 @@ +using Cli.NET.Abstractions.Actions; +using Cli.NET.Models; +using System.Linq; + +namespace Cli.NET.Tools +{ + public class CommandContainer + { + private readonly CommandList _commands; + private string _indicator; + private string _notFoundMessage; + private ConsoleColor _notFoundColor; + private ConsoleColor _indicatorColor; + private bool cancelLoop = false; + + /// + /// Create a new CommandContainer to handle the user commands. + /// + /// + /// + /// + /// + public CommandContainer( + string indicator = "Command > ", + string notFoundMessage = "Command {x} not found.", + ConsoleColor notFoundColor = ConsoleColor.DarkRed, + ConsoleColor indicatorColor = ConsoleColor.White) + { + _commands = new(); + _indicator = indicator; + _notFoundMessage = notFoundMessage; + _notFoundColor = notFoundColor; + _indicatorColor = indicatorColor; + } + + /// + /// Releases the execution flow by cancelling all active command listener loops. + /// + public void CancelLoop() => cancelLoop = true; + + /// + /// Register an external dictionary of commands in the commands dictionary. + /// + /// + public void Register(CommandList commands) + { + foreach (var command in commands) Register(command.Key, command.Value); + } + + /// + /// Register a new command in the commands dictionary. + /// + /// + /// + public void Register(string commandName, ICommand command) + { + _commands.Add(commandName, command); + } + + /// + /// Set a new "Not found" message/color to the command listener. + /// + /// + /// + public void SetNotFoundMessage(string message, ConsoleColor color = ConsoleColor.DarkRed) + { + _notFoundMessage = message; + _notFoundColor = color; + } + + /// + /// Set a new indicator to the command listener. + /// + /// + /// + public void SetIndicator(string indicator, ConsoleColor color = ConsoleColor.White) + { + _indicator = indicator; + _indicatorColor = color; + } + + /// + /// Execute the commands provided by the environment startup. + /// + public void ExecuteEnvironmentCommands() + { + var commands = string.Join(" ", Environment.GetCommandLineArgs().Skip(1)).Split("&&"); + + foreach (var command in commands) + { + var input = command.Split(" ").Where(x => !string.IsNullOrWhiteSpace(x)).ToArray(); + CallCommandByName(input[0], input.Skip(1).ToArray()); + } + } + + /// + /// Wait for the next user input (command) using the indicator. + /// + public void WaitForNextCommand(bool loop = true) + { + CLNConsole.Write(_indicator, _indicatorColor); + string[] input = CLNConsole.ReadText().Split(" "); + + CallCommandByName(input[0], input.Skip(1).ToArray()); + + if (cancelLoop) + { + loop = false; + cancelLoop = false; + } + + if (loop) WaitForNextCommand(loop); + } + + /// + /// Call a registered command by name using only one argument. + /// + /// + /// + /// + public void CallCommandByName(string name, string argument, bool enableNotFoundErrorMessage = true) + { + CallCommandByName(name, new string[] { argument }, enableNotFoundErrorMessage); + } + + /// + /// Call a registered command by name, optionally using arguments. + /// + /// + /// + /// + public void CallCommandByName(string name, string[]? arguments = null, bool enableNotFoundErrorMessage = true) + { + if(arguments == null) + arguments = Array.Empty(); + + if (!_commands.ContainsKey(name)) + { + if(enableNotFoundErrorMessage) CLNConsole.WriteLine(_notFoundMessage.Replace("{x}", name), _notFoundColor); + return; + } + + _commands[name].Execute(arguments); + } + } +} diff --git a/Cli.NET/Cli.NET/Tools/OutputProvider.cs b/Cli.NET/Cli.NET/Tools/OutputProvider.cs new file mode 100644 index 0000000..aed40a1 --- /dev/null +++ b/Cli.NET/Cli.NET/Tools/OutputProvider.cs @@ -0,0 +1,42 @@ +using Cli.NET.Models; + +namespace Cli.NET.Tools +{ + public class OutputProvider + { + private readonly OutputList _outputList; + + /// + /// Create a new OutputProvider to manage outputs. + /// + public OutputProvider() + { + _outputList = new(); + } + + /// + /// Add a log to the output list. + /// + /// + /// + public void AddLog(string message, OutputType type) + { + _outputList.Add(DateTime.Now, new Output(message, type)); + } + + /// + /// Add an exception log to the output list. + /// + /// + public void AddLog(Exception exception) + { + _outputList.Add(DateTime.Now, new Output(exception.Message, OutputType.Error)); + } + + /// + /// Get the output list. + /// + /// + public OutputList GetOutput() => _outputList; + } +} diff --git a/Commands/EchoCommand.cs b/Commands/EchoCommand.cs deleted file mode 100644 index b4e4376..0000000 --- a/Commands/EchoCommand.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using TerminalPackage; - -namespace CLIdotNET.Commands { - /* Echo example command. Usage: echo [yourText] */ - public class EchoCommand : ICommand { - public void Execute(string args) { - ConsoleScreen.Write($"Echo > {args}"); - Console.WriteLine(""); - } - } -} \ No newline at end of file diff --git a/Commands/ErrorCommand.cs b/Commands/ErrorCommand.cs deleted file mode 100644 index 9899e11..0000000 --- a/Commands/ErrorCommand.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using TerminalPackage; - -namespace CLIdotNET.Commands { - /* Error action when command doesn't exist */ - public class ErrorCommand : ICommand { - public void Execute(string args) { - ConsoleScreen.Write($"Error > The command {args} doesn't exist", ConsoleColor.DarkRed); - ConsoleScreen.Write("", ConsoleColor.White); - Console.WriteLine(""); - } - } -} \ No newline at end of file diff --git a/Commands/ExitCommand.cs b/Commands/ExitCommand.cs deleted file mode 100644 index 31d9db0..0000000 --- a/Commands/ExitCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using TerminalPackage; - -namespace CLIdotNET.Commands { - /* Exit example command. Usage: exit */ - public class ExitCommand : ICommand { - public void Execute(string args) { - System.Environment.Exit(0); - } - } -} \ No newline at end of file diff --git a/Commands/ICommand.cs b/Commands/ICommand.cs deleted file mode 100644 index e464b73..0000000 --- a/Commands/ICommand.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace CLIdotNET.Commands { - public interface ICommand { - public void Execute(string args); - } -} \ No newline at end of file diff --git a/Commands/NoCommand.cs b/Commands/NoCommand.cs deleted file mode 100644 index cdc36dc..0000000 --- a/Commands/NoCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using TerminalPackage; - -namespace CLIdotNET.Commands { - /* No command placeholder */ - public class NoCommand : ICommand { - public void Execute(string args) { - Console.WriteLine(""); - } - } -} \ No newline at end of file diff --git a/Commands/StartCommand.cs b/Commands/StartCommand.cs deleted file mode 100644 index 962c0c4..0000000 --- a/Commands/StartCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Diagnostics; -using TerminalPackage; - -namespace CLIdotNET.Commands { - /* Start example command. Usage: start [Path] */ - public class StartCommand : ICommand { - public void Execute(string args) { - try { - Process.Start(args); - } - catch {} - } - } -} \ No newline at end of file diff --git a/Controllers/CommandController.cs b/Controllers/CommandController.cs deleted file mode 100644 index b8452b3..0000000 --- a/Controllers/CommandController.cs +++ /dev/null @@ -1,39 +0,0 @@ -using CLIdotNET.Commands; -using System.Collections.Generic; - -namespace CLIdotNET.Controllers { - public static class CommandController { - /* The main commands (before the first space) are managed by the standard CLI.NET dictionary, - the arguments are managed by the developer and are sent in string form to the command */ - public static Dictionary Commands = new Dictionary() { - {"", new NoCommand()}, - {"echo", new EchoCommand()}, - {"exit", new ExitCommand()}, - {"start", new StartCommand()}, - {"_internalErrorNotFound", new ErrorCommand()} - }; - - public static void Execute(string[] args) { - bool commandFound = false; - var command = args[0]; - var arguments = string.Empty; - - for(int i = 0; i < args.Length; i++) { - if (i != 0) { - arguments += args[i] + " "; - } - } - - foreach (var i in Commands.Keys) { - if (i == command) { - Commands[command].Execute(arguments); - commandFound = true; - } - } - - if (!commandFound) { - Commands["_internalErrorNotFound"].Execute(command); - } - } - } -} \ No newline at end of file diff --git a/Program.cs b/Program.cs deleted file mode 100644 index b0abbcb..0000000 --- a/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using CLIdotNET.Controllers; - -namespace CLIdotNET -{ - class Program - { - static void Main(string[] args = null) - { - // If there's no arguments, the program will read the user input - if (args.Length < 1) { - var com = Console.ReadLine(); - CommandController.Execute(com.Split(" ")); - Main(new string[]{}); - } - // If there's arguments, the commands will be executed - else { - CommandController.Execute(args); - Main(new string[]{}); - } - } - } -} diff --git a/README.MD b/README.MD index 0ceae10..a462d5b 100644 --- a/README.MD +++ b/README.MD @@ -3,38 +3,239 @@ -CLI.NET is a library linked to a template for creating simple command line interfaces quickly.
-Its use consists of using the base project as a template and building your own command line from it.
-Supports **.NET 5+** | Can be used to Multiplatform Targets. | [Currently in **Version Alpha**] - -## Usage: -### To start building a CLI.NET project just clone this repository. The Standard Program consists of the following phases:
- -**[Program.cs]** The main module where the program is executed, it has two functionalities, the main one being an automatic -executor where it receives arguments from an external call and the secondary one where the CLI is called for the user to perform various actions. -

- -

- -**[CommandController.cs]** The design brain, place where commands are processed and their arguments are routed to individual commands. -For a command to work two things are needed: a reference to it in the controller's main dictionary and a class - derived from the **IController** -interface that contains the body of the command. -

- -

-The CommandController's "Execute" function performs a search for the command entered by the user in the dictionary, if the command is found it will call -the "Execute" method of the class corresponding to that command, if empty the terminal will do nothing and if the command does not exists the terminal will -raise the error **ErrorCommand** by default. -

- -

- -**[MyCommand.cs]** By default it is interesting that the classes for each command are created in the "Commands" folder, a command is constituted by its -own instantiable class, derived from the ICommand interface that contains the **void Execute(string args)** method, inside it is you can do whatever you -want using the arguments received by the user. -

- -

- -## Thanks -Thank you for reading about the project. If possible, consider collaborating in some way with the project, sharing it, or leaving a star. +CLI.NET is a library for creating command line interfaces, command listeners and scripting languages quickly. + +Supports **.NET 6+** | Version 2.0.0 Alpha + +# Usage: +To start building a CLI.NET project just clone this repository and reference to your project as an external project. + +Example +```csharp +using Cli.NET.Actions; +using Cli.NET.Tools; + +var container = new CommandContainer(); + +container.Register(new() +{ + { "exit", new ExitCommand() }, + { "echo", new EchoCommand() }, + { "sum", new SumCommand() }, + { "clear", new ClearCommand() }, + { "cls", new ClearCommand() } +}); + +container.WaitForNextCommand(); +``` + +## Creating, registering and using a command +A command can be created by just implementing the interface "ICommand" from `Cli.NET.Abstractions`, +you can implement any logic inside `Execute()` and extend the class functions. +Example: + +```csharp +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + /// + /// Default example "echo" command to display data in the console. + /// + public class EchoCommand : IConsoleCommand + { + public void Execute(string[] arguments) => Console.WriteLine(string.Join(" ", arguments)); + } +} +``` + +To register a command, we will need a CommandContainer. Example: + +```csharp +using Cli.NET.Actions; +using Cli.NET.Tools; + +var container = new CommandContainer(); + +container.Register("echo", new EchoCommand()); + +container.WaitForNextCommand(); +``` + +Now, the "echo" command can be used in the console application: + + + +## Initializing the command listener +To read commands, Cli.NET needs a method called `WaitForNextCommand()`, that method can receive +a boolean telling if the command flow will be infinite or if that is a unique command. + +```csharp +container.WaitForNextCommand(); //Will make an infinity command listener +``` + +```csharp +container.WaitForNextCommand(false); //Will only read the first typed input or command +``` + +## Managing outputs/exceptions +An easy way to manage command outputs and exceptions and sharing the data between all the +application is using an `OutputProvider`. + +Example: + +**Program.cs** +```csharp +using Cli.NET.Actions; +using Cli.NET.Tools; + +var container = new CommandContainer(); +var outputProvider = new OutputProvider(); + +container.Register("log", new LogCommand(outputProvider)); +container.CallCommandByName("log", "Test output"); + +``` + +**LogCommand.cs** +```csharp +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + public class LogCommand : IConsoleCommand + { + private readonly OutputProvider _provider; + + public LogCommand(OutputProvider provider) + { + _provider = provider; + } + + public void Execute(string[] arguments) + { + _provider.AddLog(string.Join("", arguments), OutputType.Message); + Console.WriteLine(_provider.GetOutput().LastOrDefault()); + } + } +} +``` + +## Cancelling the loop flow +You can cancel a loop flow passing the container by reference to a command. Example: + +**CancelLoopCommand.cs** +```csharp +using Cli.NET.Abstractions.Actions; + +namespace Cli.NET.Actions +{ + public class CancelLoopCommand : IConsoleCommand + { + private readonly CommandContainer _container; + + public CancelLoopCommand(CommandContainer container) + { + _container = container; + } + + public void Execute(string[] arguments) + { + _container.CancelLoop(); + } + } +} +``` + +**Program.cs** +```csharp +using Cli.NET.Actions; +using Cli.NET.Tools; + +var container = new CommandContainer(); + +container.Register("cancel-loop", new CancelLoopCommand(container)); + +container.WaitForNextCommand(); //If you call "cancel", the loop will be cancelled +``` + +## Customizing the console appearance +You can create a customized CommandContainer by changing the constructor parameter values, the +default configuration (empty constructor) is: + +```csharp +public CommandContainer( + string indicator = "Command > ", + string notFoundMessage = "Command {x} not found.", + ConsoleColor notFoundColor = ConsoleColor.DarkRed, + ConsoleColor indicatorColor = ConsoleColor.White) +{ + _commands = new(); + _indicator = indicator; + _notFoundMessage = notFoundMessage; + _notFoundColor = notFoundColor; + _indicatorColor = indicatorColor; +} +``` + +List of customizable parameters: + +| Name | Description | Type | +| ---- | ----------- | ---- | +| indicator | The command indicator, will be placed to show the current location to the user | string | +| notFoundMessage | A message that will be displayed when the insert command does not exist | string | +| notFoundColor | A color to the notFoundMessage | ConsoleColor | +| indicatorColor | A color to the indicator | ConsoleColor | + +You can use the methods `SetNotFoundMessage()` and `SetIndicator()` to customize the container in any +moment of the application execution, example: + +```csharp +container.SetNotFoundMessage("Oops! Command not found.", ConsoleColor.Red); +container.SetIndicator("Insert command here >", ConsoleColor.Yellow); +``` + +## Cli.NET CLNConsole class tools (only console applications) +There are some built-in console application tools in `Cli.NET.Tools.CLNConsole` +class, check the list below: + +| Method | Parameters | Description | +| ------ | ---------- | ----------- | +| `WriteLine` | `message: string` | Display a new line with a message in the console | +| `WriteLine` | `message: string`
`color: string` | Show a new line with a message in the console with a color (string) | +| `WriteLine` | `message: string`
`color: int` | Show a new line with a message in the console with a color (int) | +| `WriteLine` | `message: string`
`color: ConsoleColor` | Show a new line with a message in the console with a ConsoleColor | +| - | - | - | +| `Write` | `message: string` | Show a message in the current console location | +| `Write` | `message: string`
`color: string` | Show a message in the current console location with a color (string) | +| `Write` | `message: string`
`color: int` | Show a message in the current console location with a color (int) | +| `Write` | `message: string`
`color: ConsoleColor` | Show a message in the current console location with a ConsoleColor | +| - | - | - | +| `ReadText` | | Reads the next text input followed by "Enter" command | +| `ReadText` | `minLength: uint`
`maxLength: uint` | Reads the next text input with a Min/Max length | +| - | - | - | +| `DataQuestion` | `message: string` | Displays a text to the user and waits for a response | +| `DataQuestion` | `message: string`
`color: string`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color || `DataQuestion` | `message: string`
`color: string`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color | +| `DataQuestion` | `message: string`
`color: int`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color || `DataQuestion` | `message: string`
`color: string`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color | +| `DataQuestion` | `message: string`
`color: ConsoleColor`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color || `DataQuestion` | `message: string`
`color: string`
`minLength: string`
`maxLength: string` | Displays a text and waits for a response with a Min/Max length and color | + +## Calling the environment commands +Sometimes we need to pass parameters before the application execution, to execute them the +`ExecuteEnvironmentCommands()` method can be used, example: + +```csharp +container.ExecuteEnvironmentCommands(); +``` + +## Calling commands in the application execution +To call registered commands programatically during the application execution you can use the +method `CallCommandByName`, passing one unique string argument or a string array of arguments, example: + +```csharp +container.CallCommandByName("echo", "argument one"); +container.CallCommandByName("echo", new string[] { "argument one", "argument two" }); +``` + +# Finishing... +You can support that library/repository by leaving a contribution, star or sharing in communities. Thanks +for the attention. You can also create issues or give a feedback in my [Twitter](https://twitter.com/victoriaquasar). \ No newline at end of file diff --git a/TerminalPackage/ConsoleScreen.cs b/TerminalPackage/ConsoleScreen.cs deleted file mode 100644 index b0b9549..0000000 --- a/TerminalPackage/ConsoleScreen.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -namespace TerminalPackage { - public static class ConsoleScreen { - public static void Write(string text, ConsoleColor color = ConsoleColor.White) { - Console.ForegroundColor = color; - Console.Write(text); - } - } -} \ No newline at end of file diff --git a/clidotnet.csproj b/clidotnet.csproj deleted file mode 100644 index 1d2d39a..0000000 --- a/clidotnet.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - - Exe - net5.0 - - -