mirror of
https://github.com/Stone-Red-Code/TextLore.git
synced 2026-09-04 00:56:26 +02:00
Improve command system and add help command
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
using TextLore.Models;
|
||||
|
||||
namespace TextLore.Commands;
|
||||
|
||||
public class ClearCommand : Command
|
||||
{
|
||||
public override string Name => "clear";
|
||||
public override string Description => "Clears the console.";
|
||||
|
||||
public override string[] Aliases => ["cls"];
|
||||
|
||||
public override bool NoHistoryIfNoOutput => true;
|
||||
|
||||
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||
{
|
||||
consoleOutput.Clear();
|
||||
return Task.FromResult(CommandResult.Success("Console cleared!"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using TextLore.Models;
|
||||
|
||||
namespace TextLore.Commands;
|
||||
|
||||
public class HelpCommand(IEnumerable<Command> commands) : Command
|
||||
{
|
||||
public override string Name => "help";
|
||||
public override string Description => "Displays a list of commands and their descriptions.";
|
||||
public override string Usage => "help <command>";
|
||||
public override string[] Aliases => new[] { "h", "?" };
|
||||
|
||||
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(args))
|
||||
{
|
||||
consoleOutput.WriteLine("Available commands:");
|
||||
foreach (Command command in commands)
|
||||
{
|
||||
consoleOutput.WriteLine($" {command.Name} - {command.Description}");
|
||||
}
|
||||
return Task.FromResult(CommandResult.Success());
|
||||
}
|
||||
else
|
||||
{
|
||||
Command? command = commands.FirstOrDefault(c => c.Name.Equals(args, StringComparison.OrdinalIgnoreCase) || c.Aliases.Contains(args, StringComparer.OrdinalIgnoreCase));
|
||||
if (command is null)
|
||||
{
|
||||
consoleOutput.WriteLine($"Command \"{args[0]}\" not found.");
|
||||
return Task.FromResult(CommandResult.Failure());
|
||||
}
|
||||
else
|
||||
{
|
||||
consoleOutput.WriteLine($"Command: {command.Name}");
|
||||
|
||||
if (command.Aliases.Length > 0)
|
||||
{
|
||||
consoleOutput.WriteLine($"Aliases: {string.Join(", ", command.Aliases)}");
|
||||
}
|
||||
|
||||
consoleOutput.WriteLine($"Description: {command.Description}");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(command.Usage))
|
||||
{
|
||||
consoleOutput.WriteLine($"Usage: {command.Usage}");
|
||||
}
|
||||
|
||||
return Task.FromResult(CommandResult.Success());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ public class TestCommand : Command
|
||||
public override string Name => "test";
|
||||
public override string Description => "A test command.";
|
||||
|
||||
public override Task<bool> Execute(ConsoleOutput consoleOutput, string[] args)
|
||||
public override string[] Aliases => ["tst"];
|
||||
|
||||
public override Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args)
|
||||
{
|
||||
consoleOutput.WriteLine("This is a test command.");
|
||||
return Task.FromResult(true);
|
||||
return Task.FromResult(CommandResult.Success("test"));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
@page "/"
|
||||
@using TextLore.Commands
|
||||
@using TextLore.Models
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<TextLore.Components.Shared.Console Commands="commands" />
|
||||
<PageTitle>TextLore</PageTitle>
|
||||
|
||||
<Console Name="Main Menu" Commands="commands" HelpCommand="helpCommand" />
|
||||
|
||||
@code
|
||||
{
|
||||
Command[] commands = [new TestCommand()];
|
||||
List<Command> commands = [new TestCommand(), new ClearCommand()];
|
||||
|
||||
HelpCommand? helpCommand;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
helpCommand = new HelpCommand(commands);
|
||||
commands.Add(helpCommand);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
<EditForm OnSubmit="Execute" autocomplete="off" Model="ConsoleInput" novalidate>
|
||||
<div id="input-line" class="input-line">
|
||||
<div class="prompt">
|
||||
Command >
|
||||
Command >
|
||||
</div>
|
||||
<div>
|
||||
<InputText @ref="inputText" id="commandline" autocomplete="off" class="cmdline" disabled="@disabled" placeholder="@Placeholder" @bind-Value="@ConsoleInput.Text" />
|
||||
@@ -26,8 +26,16 @@
|
||||
</div>
|
||||
</EditForm>
|
||||
<pre>
|
||||
<code>@((MarkupString)running)</code>
|
||||
<code>@((MarkupString)output)</code>
|
||||
<code>@currentOutput?.Text</code>
|
||||
<code>
|
||||
@foreach (ConsoleOutput output in consoleOutputs.Reverse<ConsoleOutput>())
|
||||
{
|
||||
<p>
|
||||
<span class='header'>@output.Time.ToString("HH:mm") > </span><span class='command'>@output.Command</span>
|
||||
@output.Text
|
||||
</p>
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,20 +51,16 @@
|
||||
[Parameter]
|
||||
public bool ShowDate { get; set; } = true;
|
||||
|
||||
|
||||
public string Placeholder => $"Enter a command{(HelpCommand is null ? "." : ", type 'help' for avaliable commands.")}";
|
||||
|
||||
public ConsoleInput ConsoleInput { get; set; } = new();
|
||||
public ConsoleOutput ConsoleOutput { get; set; } = new();
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public IEnumerable<Command> Commands { get; set; } = [];
|
||||
|
||||
[Parameter]
|
||||
public Command? HelpCommand { get; set; }
|
||||
|
||||
private string output { get; set; } = "";
|
||||
private string running { get; set; } = "";
|
||||
private string Placeholder => $"Enter a command{(HelpCommand is null ? "." : ", type 'help' for avaliable commands.")}";
|
||||
private ConsoleInput ConsoleInput { get; set; } = new();
|
||||
private List<ConsoleOutput> consoleOutputs = new();
|
||||
private ConsoleOutput? currentOutput;
|
||||
private bool disabled { get; set; } = false;
|
||||
private InputText? inputText;
|
||||
|
||||
@@ -68,45 +72,74 @@
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
ConsoleOutput.OnOutput += WriteOutput;
|
||||
}
|
||||
|
||||
public async Task Execute(EditContext context)
|
||||
{
|
||||
Command? command = Commands.FirstOrDefault(c=>c.Name.Equals(ConsoleInput.Text));
|
||||
command ??= HelpCommand;
|
||||
string commandName = ConsoleInput.Text.Split(' ')[0];
|
||||
string commandArgs = new string(ConsoleInput.Text.Skip(commandName.Length).ToArray()).TrimStart(' ');
|
||||
|
||||
if(command is null)
|
||||
Command? command = Commands.FirstOrDefault(c => c.Name.Equals(commandName) || c.Aliases.Contains(commandName));
|
||||
command ??= HelpCommand?.Name.Equals(commandName) == true || HelpCommand?.Aliases.Contains(commandName) == true ? HelpCommand : null;
|
||||
|
||||
if (command is null)
|
||||
{
|
||||
running = $"[Failed] Command '{ConsoleInput.Text}' not found!";
|
||||
ConsoleInput.Text = string.Empty;
|
||||
await CommandNotFound(commandName);
|
||||
return;
|
||||
}
|
||||
|
||||
disabled = true;
|
||||
|
||||
running = $"<p>";
|
||||
running += $"<span class='header'>{ConsoleInput.Time.ToString("HH:mm")} > </span><span class='command'>{ConsoleInput.Text}{Environment.NewLine}</span>";
|
||||
ConsoleWriter consoleWriter = new ConsoleWriter();
|
||||
ConsoleOutput consoleOutput = new ConsoleOutput();
|
||||
|
||||
bool success = await command.Execute(ConsoleOutput, []);
|
||||
consoleWriter.OnOutput += (_, e) => WriteOutput(consoleOutput, e);
|
||||
consoleWriter.OnClear += (_, _) => consoleOutputs.Clear();
|
||||
consoleOutput.Command = ConsoleInput.Text;
|
||||
currentOutput = consoleOutput;
|
||||
|
||||
running += "</p>";
|
||||
CommandResult commandResult = await command.Execute(consoleWriter, commandArgs);
|
||||
|
||||
output = running + output;
|
||||
currentOutput = new()
|
||||
{
|
||||
Text = $"{(commandResult.IsSuccess ? "[Success]" : "[Failed]")} {commandResult.Message}"
|
||||
};
|
||||
|
||||
running = success ? $"[Success]" : $"[Failed]";
|
||||
if (!command.NoHistoryIfNoOutput || !string.IsNullOrWhiteSpace(consoleOutput.Text))
|
||||
{
|
||||
consoleOutputs.Add(consoleOutput);
|
||||
}
|
||||
|
||||
ConsoleInput.Text = string.Empty;
|
||||
disabled = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void WriteOutput(object? sender, ConsoleOutputEventArgs e)
|
||||
public void WriteOutput(ConsoleOutput consoleOutput, ConsoleOutputEventArgs e)
|
||||
{
|
||||
string newOutput = e.Message;
|
||||
output = newOutput + output;
|
||||
consoleOutput.Text += e.Message;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task CommandNotFound(string commandName)
|
||||
{
|
||||
currentOutput = new()
|
||||
{
|
||||
Text = $"[Failed] Command '{commandName}' not found!"
|
||||
};
|
||||
|
||||
if(HelpCommand is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleWriter consoleWriter = new ConsoleWriter();
|
||||
ConsoleOutput consoleOutput = new ConsoleOutput();
|
||||
|
||||
consoleWriter.OnOutput += (_, e) => WriteOutput(consoleOutput, e);
|
||||
consoleOutput.Command = ConsoleInput.Text;
|
||||
consoleOutputs.Add(consoleOutput);
|
||||
|
||||
CommandResult commandResult = await HelpCommand.Execute(consoleWriter, string.Empty);
|
||||
|
||||
ConsoleInput.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -8,3 +8,6 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using TextLore
|
||||
@using TextLore.Components
|
||||
@using TextLore.Components.Shared
|
||||
@using TextLore.Commands
|
||||
@using TextLore.Models
|
||||
@@ -6,6 +6,7 @@ public abstract class Command
|
||||
public abstract string Description { get; }
|
||||
public virtual string Usage { get; } = string.Empty;
|
||||
public virtual string[] Aliases { get; } = [];
|
||||
public virtual bool NoHistoryIfNoOutput { get; } = false;
|
||||
|
||||
public abstract Task<bool> Execute(ConsoleOutput consoleOutput, string[] args);
|
||||
public abstract Task<CommandResult> Execute(ConsoleWriter consoleOutput, string args);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace TextLore.Models;
|
||||
|
||||
public class CommandResult(string message, bool success)
|
||||
{
|
||||
public string Message { get; } = message;
|
||||
public bool IsSuccess { get; } = success;
|
||||
|
||||
public static CommandResult Success(string message = "")
|
||||
{
|
||||
return new(message, true);
|
||||
}
|
||||
|
||||
public static CommandResult Failure(string message = "")
|
||||
{
|
||||
return new(message, false);
|
||||
}
|
||||
|
||||
public static implicit operator CommandResult(string message)
|
||||
{
|
||||
return Success(message);
|
||||
}
|
||||
}
|
||||
@@ -2,45 +2,7 @@
|
||||
|
||||
public class ConsoleOutput
|
||||
{
|
||||
public event EventHandler<ConsoleOutputEventArgs>? OnOutput;
|
||||
|
||||
public void Write(string message, ConsoleMessageType consoleMessageType = ConsoleMessageType.Default)
|
||||
{
|
||||
OnOutput?.Invoke(this, new(message, consoleMessageType));
|
||||
}
|
||||
|
||||
public void WriteLine(string message)
|
||||
{
|
||||
Write(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteError(string message)
|
||||
{
|
||||
Write($"[ERROR] {message}", ConsoleMessageType.Error);
|
||||
}
|
||||
|
||||
public void WriteErrorLine(string message)
|
||||
{
|
||||
WriteError(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteWarning(string message)
|
||||
{
|
||||
Write($"[WARNING] {message}", ConsoleMessageType.Warning);
|
||||
}
|
||||
|
||||
public void WriteWarningLine(string message)
|
||||
{
|
||||
WriteWarning(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteInfo(string message)
|
||||
{
|
||||
Write($"[INFO] {message}", ConsoleMessageType.Info);
|
||||
}
|
||||
|
||||
public void WriteInfoLine(string message)
|
||||
{
|
||||
WriteInfo(message + Environment.NewLine);
|
||||
}
|
||||
public string Text { get; set; } = string.Empty;
|
||||
public string Command { get; set; } = string.Empty;
|
||||
public DateTime Time { get; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace TextLore.Models;
|
||||
|
||||
public class ConsoleWriter
|
||||
{
|
||||
public event EventHandler<ConsoleOutputEventArgs>? OnOutput;
|
||||
|
||||
public event EventHandler<EventArgs>? OnClear;
|
||||
public void Write(string message, ConsoleMessageType consoleMessageType = ConsoleMessageType.Default)
|
||||
{
|
||||
OnOutput?.Invoke(this, new(message, consoleMessageType));
|
||||
}
|
||||
|
||||
public void WriteLine(string message)
|
||||
{
|
||||
Write(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteError(string message)
|
||||
{
|
||||
Write($"[ERROR] {message}", ConsoleMessageType.Error);
|
||||
}
|
||||
|
||||
public void WriteErrorLine(string message)
|
||||
{
|
||||
WriteError(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteWarning(string message)
|
||||
{
|
||||
Write($"[WARNING] {message}", ConsoleMessageType.Warning);
|
||||
}
|
||||
|
||||
public void WriteWarningLine(string message)
|
||||
{
|
||||
WriteWarning(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void WriteInfo(string message)
|
||||
{
|
||||
Write($"[INFO] {message}", ConsoleMessageType.Info);
|
||||
}
|
||||
|
||||
public void WriteInfoLine(string message)
|
||||
{
|
||||
WriteInfo(message + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
OnClear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user