From 90b86a2c0df8c54947d9f48a22e8a61f1871742d Mon Sep 17 00:00:00 2001 From: Aptivi Date: Sun, 17 Nov 2024 11:11:52 +0300 Subject: [PATCH] add - doc - Backported Nitrocid's shell to Termina... ...ux --- We've backported the shell implementation in to satisfy the requirements, removing some of Nitrocid-exclusive features in the process as they're out of scope for Terminaux. Nitrocid KS will not use it as it has its own shell implementation. --- Type: add Breaking: False Doc Required: True Backport Required: False Part: 1/1 --- .../Cases/Shell/Shells/Commands/Write.cs | 30 + .../Cases/Shell/Shells/Commands/WriteArg.cs | 30 + .../Cases/Shell/Shells/TestShellInfo.cs | 55 ++ .../Cases/Shell/Shells/TestShellInstance.cs | 61 ++ .../Fixtures/Cases/Shell/TestShell.cs | 31 +- Terminaux.Console/Fixtures/FixtureCategory.cs | 3 +- Terminaux.Console/Fixtures/FixtureManager.cs | 4 + Terminaux/Shell/Aliases/AliasManager.cs | 152 +--- Terminaux/Shell/Arguments/ArgumentsParser.cs | 148 +--- .../Shell/Arguments/CommandArgumentInfo.cs | 5 +- .../Shell/Arguments/CommandArgumentPart.cs | 2 +- .../Shell/Arguments/CommandAutoComplete.cs | 45 +- .../Arguments/CommandAutoCompletionList.cs | 18 - Terminaux/Shell/Commands/BaseCommand.cs | 21 +- .../Shell/Commands/CancellationHandlers.cs | 113 --- Terminaux/Shell/Commands/CommandExecutor.cs | 356 ++------ .../Commands/CommandExecutorParameters.cs | 4 - Terminaux/Shell/Commands/CommandFlags.cs | 52 -- Terminaux/Shell/Commands/CommandInfo.cs | 20 +- Terminaux/Shell/Commands/CommandManager.cs | 316 +------ Terminaux/Shell/Commands/CommandParameters.cs | 4 - Terminaux/Shell/Commands/ICommand.cs | 8 +- .../ExecuteProcessThreadParameters.cs | 42 - .../ProcessExecution/ProcessExecutor.cs | 346 -------- .../Shell/Commands/SlashReminderCommand.cs | 11 +- Terminaux/Shell/Commands/UndefinedCommand.cs | 9 +- Terminaux/Shell/Help/HelpPrint.cs | 101 +-- Terminaux/Shell/Help/HelpPrintTools.cs | 157 ++-- Terminaux/Shell/Prompts/PromptPresetBase.cs | 30 +- .../Shell/Prompts/PromptPresetManager.cs | 97 +-- .../Scripting/Conditions/BaseCondition.cs | 69 -- .../Shell/Scripting/Conditions/ICondition.cs | 50 -- .../Scripting/Conditions/Types/Contains.cs | 44 - .../Conditions/Types/DirectoryExists.cs | 65 -- .../Conditions/Types/DirectoryNotExists.cs | 44 - .../Scripting/Conditions/Types/Equals.cs | 44 - .../Scripting/Conditions/Types/FileExists.cs | 44 - .../Conditions/Types/FileHashMatch.cs | 62 -- .../Conditions/Types/FileHashMismatch.cs | 44 - .../Conditions/Types/FileNotExists.cs | 62 -- .../Scripting/Conditions/Types/GreaterThan.cs | 44 - .../Conditions/Types/GreaterThanOrEqual.cs | 44 - .../Scripting/Conditions/Types/HashesMatch.cs | 44 - .../Conditions/Types/HashesMismatch.cs | 44 - .../Conditions/Types/InvalidFileName.cs | 44 - .../Scripting/Conditions/Types/InvalidPath.cs | 44 - .../Shell/Scripting/Conditions/Types/Is.cs | 93 --- .../Shell/Scripting/Conditions/Types/IsNot.cs | 54 -- .../Scripting/Conditions/Types/IsNotPlat.cs | 54 -- .../Scripting/Conditions/Types/IsPlat.cs | 63 -- .../Scripting/Conditions/Types/LessThan.cs | 65 -- .../Conditions/Types/LessThanOrEqual.cs | 44 - .../Shell/Scripting/Conditions/Types/None.cs | 48 -- .../Scripting/Conditions/Types/NotContains.cs | 65 -- .../Scripting/Conditions/Types/NotEquals.cs | 44 - .../Conditions/Types/ValidFileName.cs | 65 -- .../Scripting/Conditions/Types/ValidPath.cs | 62 -- .../Scripting/Conditions/UESHConditional.cs | 230 ------ Terminaux/Shell/Scripting/UESHOperators.cs | 397 --------- Terminaux/Shell/Scripting/UESHParse.cs | 248 ------ Terminaux/Shell/Scripting/UESHVariables.cs | 259 ------ Terminaux/Shell/Shells/BaseShell.cs | 11 +- Terminaux/Shell/Shells/BaseShellInfo.cs | 26 +- Terminaux/Shell/Shells/IShellInfo.cs | 16 +- Terminaux/Shell/Shells/ShellExecuteInfo.cs | 23 +- Terminaux/Shell/Shells/ShellManager.cs | 772 +++--------------- Terminaux/Shell/Shells/ShellType.cs | 48 -- Terminaux/Shell/Shells/Unified/Exec.cs | 49 -- Terminaux/Shell/Shells/Unified/Exit.cs | 16 +- Terminaux/Shell/Shells/Unified/FindCmds.cs | 14 +- Terminaux/Shell/Shells/Unified/Help.cs | 10 +- .../Shell/Shells/Unified/LoadHistories.cs | 41 - Terminaux/Shell/Shells/Unified/Presets.cs | 6 +- Terminaux/Shell/Shells/Unified/Repeat.cs | 79 -- Terminaux/Shell/Shells/Unified/Tip.cs | 46 -- Terminaux/Shell/Shells/Unified/Wrap.cs | 53 -- Terminaux/Shell/Switches/SwitchInfo.cs | 10 +- Terminaux/Shell/Switches/SwitchManager.cs | 4 +- Terminaux/Terminaux.csproj | 4 +- 79 files changed, 596 insertions(+), 5486 deletions(-) create mode 100644 Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/Write.cs create mode 100644 Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/WriteArg.cs create mode 100644 Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInfo.cs create mode 100644 Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInstance.cs rename Terminaux/Shell/Shells/Unified/SaveHistories.cs => Terminaux.Console/Fixtures/Cases/Shell/TestShell.cs (53%) delete mode 100644 Terminaux/Shell/Commands/CancellationHandlers.cs delete mode 100644 Terminaux/Shell/Commands/CommandFlags.cs delete mode 100644 Terminaux/Shell/Commands/ProcessExecution/ExecuteProcessThreadParameters.cs delete mode 100644 Terminaux/Shell/Commands/ProcessExecution/ProcessExecutor.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/BaseCondition.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/ICondition.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/Contains.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/DirectoryExists.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/DirectoryNotExists.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/Equals.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/FileExists.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/FileHashMatch.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/FileHashMismatch.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/FileNotExists.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/GreaterThan.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/GreaterThanOrEqual.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/HashesMatch.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/HashesMismatch.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/InvalidFileName.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/InvalidPath.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/Is.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/IsNot.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/IsNotPlat.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/IsPlat.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/LessThan.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/LessThanOrEqual.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/None.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/NotContains.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/NotEquals.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/ValidFileName.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/Types/ValidPath.cs delete mode 100644 Terminaux/Shell/Scripting/Conditions/UESHConditional.cs delete mode 100644 Terminaux/Shell/Scripting/UESHOperators.cs delete mode 100644 Terminaux/Shell/Scripting/UESHParse.cs delete mode 100644 Terminaux/Shell/Scripting/UESHVariables.cs delete mode 100644 Terminaux/Shell/Shells/ShellType.cs delete mode 100644 Terminaux/Shell/Shells/Unified/Exec.cs delete mode 100644 Terminaux/Shell/Shells/Unified/LoadHistories.cs delete mode 100644 Terminaux/Shell/Shells/Unified/Repeat.cs delete mode 100644 Terminaux/Shell/Shells/Unified/Tip.cs delete mode 100644 Terminaux/Shell/Shells/Unified/Wrap.cs diff --git a/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/Write.cs b/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/Write.cs new file mode 100644 index 000000000..a4a860bb9 --- /dev/null +++ b/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/Write.cs @@ -0,0 +1,30 @@ +// +// Nitrocid KS Copyright (C) 2018-2024 Aptivi +// +// This file is part of Nitrocid KS +// +// Nitrocid KS is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Nitrocid KS is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using Terminaux.Shell.Commands; +using Terminaux.Writer.ConsoleWriters; + +namespace Terminaux.Console.Fixtures.Cases.Shell.Shells.Commands +{ + class WriteCommand : BaseCommand, ICommand + { + public override void Execute(CommandParameters parameters) => + TextWriterColor.Write("Test text"); + } +} diff --git a/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/WriteArg.cs b/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/WriteArg.cs new file mode 100644 index 000000000..e0226f158 --- /dev/null +++ b/Terminaux.Console/Fixtures/Cases/Shell/Shells/Commands/WriteArg.cs @@ -0,0 +1,30 @@ +// +// Nitrocid KS Copyright (C) 2018-2024 Aptivi +// +// This file is part of Nitrocid KS +// +// Nitrocid KS is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Nitrocid KS is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using Terminaux.Shell.Commands; +using Terminaux.Writer.ConsoleWriters; + +namespace Terminaux.Console.Fixtures.Cases.Shell.Shells.Commands +{ + class WriteArgCommand : BaseCommand, ICommand + { + public override void Execute(CommandParameters parameters) => + TextWriterColor.Write(parameters.ArgumentsText); + } +} diff --git a/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInfo.cs b/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInfo.cs new file mode 100644 index 000000000..b6f5beb10 --- /dev/null +++ b/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInfo.cs @@ -0,0 +1,55 @@ +// +// Terminaux Copyright (C) 2023-2024 Aptivi +// +// This file is part of Terminaux +// +// Terminaux is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Terminaux is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Terminaux.Console.Fixtures.Cases.Shell.Shells.Commands; +using Terminaux.Shell.Arguments; +using Terminaux.Shell.Commands; +using Terminaux.Shell.Shells; + +namespace Terminaux.Console.Fixtures.Cases.Shell.Shells +{ + internal class TestShellInfo : BaseShellInfo, IShellInfo + { + /// + /// List of commands + /// + public override List Commands => + [ + new CommandInfo("write", "Writes test text", + [ + new CommandArgumentInfo() + ], new WriteCommand()), + + new CommandInfo("writearg", "Writes test text with argument support", + [ + new CommandArgumentInfo( + [ + new CommandArgumentPart(true, "text") + ]) + ], new WriteArgCommand()), + ]; + + public override BaseShell ShellBase => new TestShellInstance(); + } +} diff --git a/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInstance.cs b/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInstance.cs new file mode 100644 index 000000000..64f98deac --- /dev/null +++ b/Terminaux.Console/Fixtures/Cases/Shell/Shells/TestShellInstance.cs @@ -0,0 +1,61 @@ +// +// Terminaux Copyright (C) 2023-2024 Aptivi +// +// This file is part of Terminaux +// +// Terminaux is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Terminaux is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Terminaux.Shell.Shells; +using Terminaux.Writer.ConsoleWriters; +using Textify.General; + +namespace Terminaux.Console.Fixtures.Cases.Shell.Shells +{ + internal class TestShellInstance : BaseShell, IShell + { + /// + public override string ShellType => "TestShell"; + + /// + public override bool Bail { get; set; } + + /// + public override void InitializeShell(params object[] ShellArgs) + { + while (!Bail) + { + try + { + ShellManager.GetLine(); + } + catch (ThreadInterruptedException) + { + Bail = true; + } + catch (Exception ex) + { + TextWriterRaw.WritePlain("There was an error in the shell." + CharManager.NewLine + "Error {0}: {1}", ex.GetType().FullName ?? "", ex.Message); + continue; + } + } + } + } +} diff --git a/Terminaux/Shell/Shells/Unified/SaveHistories.cs b/Terminaux.Console/Fixtures/Cases/Shell/TestShell.cs similarity index 53% rename from Terminaux/Shell/Shells/Unified/SaveHistories.cs rename to Terminaux.Console/Fixtures/Cases/Shell/TestShell.cs index d6bca5212..52a90bc26 100644 --- a/Terminaux/Shell/Shells/Unified/SaveHistories.cs +++ b/Terminaux.Console/Fixtures/Cases/Shell/TestShell.cs @@ -17,25 +17,30 @@ // along with this program. If not, see . // -using Terminaux.Shell.Commands; +using System; +using System.Text; +using Terminaux.Base; +using Terminaux.Base.Buffered; +using Terminaux.Colors; +using Terminaux.Colors.Data; +using Terminaux.Inputs.Styles.Infobox; +using Terminaux.Inputs; +using Terminaux.Sequences.Builder.Types; +using Terminaux.Base.Extensions; using Terminaux.Shell.Shells; +using Terminaux.Console.Fixtures.Cases.Shell.Shells; -namespace Terminaux.Shell.Shells.Unified +namespace Terminaux.Console.Fixtures.Cases.Shell { - /// - /// Saves shell histories - /// - /// - /// You can use this command to save shell histories. - /// - class SaveHistoriesUnifiedCommand : BaseCommand, ICommand + internal class TestShell : IFixture { + public FixtureCategory Category => FixtureCategory.Shell; - public override int Execute(CommandParameters parameters, ref string variableValue) + public void RunFixture() { - ShellManager.SaveHistories(); - return 0; + ShellManager.RegisterShell("TestShell", new TestShellInfo()); + ShellManager.StartShell("TestShell"); + ShellManager.UnregisterShell("TestShell"); } - } } diff --git a/Terminaux.Console/Fixtures/FixtureCategory.cs b/Terminaux.Console/Fixtures/FixtureCategory.cs index 1f4661769..60e93645b 100644 --- a/Terminaux.Console/Fixtures/FixtureCategory.cs +++ b/Terminaux.Console/Fixtures/FixtureCategory.cs @@ -32,6 +32,7 @@ internal enum FixtureCategory Presentation, Console, Image, - Graphics + Graphics, + Shell, } } diff --git a/Terminaux.Console/Fixtures/FixtureManager.cs b/Terminaux.Console/Fixtures/FixtureManager.cs index 5be11b4c7..8d4591aad 100644 --- a/Terminaux.Console/Fixtures/FixtureManager.cs +++ b/Terminaux.Console/Fixtures/FixtureManager.cs @@ -26,6 +26,7 @@ using Terminaux.Console.Fixtures.Cases.Presentations; using Terminaux.Console.Fixtures.Cases.Reader; using Terminaux.Console.Fixtures.Cases.Screens; +using Terminaux.Console.Fixtures.Cases.Shell; using Terminaux.Console.Fixtures.Cases.Tui; using Terminaux.Console.Fixtures.Cases.Writer; @@ -321,6 +322,9 @@ internal static class FixtureManager new RenderEllipsis(), new RenderCircle(), new RenderArc(), + + // Shell + new TestShell(), ]; } } diff --git a/Terminaux/Shell/Aliases/AliasManager.cs b/Terminaux/Shell/Aliases/AliasManager.cs index 555457f33..6475c02c6 100644 --- a/Terminaux/Shell/Aliases/AliasManager.cs +++ b/Terminaux/Shell/Aliases/AliasManager.cs @@ -19,14 +19,9 @@ using System; using System.Collections.Generic; -using System.Data; using System.Linq; using Newtonsoft.Json; -using Nitrocid.Files.Operations; -using Nitrocid.Files.Paths; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; +using Terminaux.Base; using Terminaux.Shell.Commands; using Terminaux.Shell.Shells; @@ -37,47 +32,10 @@ namespace Terminaux.Shell.Aliases /// public static class AliasManager { - - internal static List builtinAliases = [ - new AliasInfo("ls", "list", ShellManager.GetShellTypeName(ShellType.Shell)) - ]; internal static List aliases = []; /// - /// Initializes aliases - /// - public static void InitAliases() - { - // Get all aliases from file - Making.MakeJsonFile(PathsManagement.GetKernelPath(KernelPathType.Aliases), false, true); - string AliasJsonContent = Reading.ReadContentsText(PathsManagement.GetKernelPath(KernelPathType.Aliases)); - var aliasesArray = JsonConvert.DeserializeObject(AliasJsonContent); - aliases = [.. aliasesArray]; - } - - /// - /// Saves aliases - /// - public static void SaveAliases() - { - // Save all aliases - DebugWriter.WriteDebug(DebugLevel.I, "Saving aliases..."); - string serialized = JsonConvert.SerializeObject(aliases.ToArray(), Formatting.Indented); - Writing.WriteContentsText(PathsManagement.GetKernelPath(KernelPathType.Aliases), serialized); - } - - /// - /// Adds alias to kernel - /// - /// A command to be aliased. It should exist in both shell and remote debug. - /// A one-word command to alias to. - /// Alias type, whether it be shell or remote debug. - /// True if successful, False if unsuccessful. - public static bool AddAlias(string SourceAlias, string Destination, ShellType Type) => - AddAlias(SourceAlias, Destination, ShellManager.GetShellTypeName(Type)); - - /// - /// Adds alias to kernel + /// Adds alias /// /// A command to be aliased. It should exist in both shell and remote debug. /// A one-word command to alias to. @@ -85,54 +43,29 @@ public static bool AddAlias(string SourceAlias, string Destination, ShellType Ty /// True if successful, False if unsuccessful. public static bool AddAlias(string SourceAlias, string Destination, string Type) { - if (Enum.IsDefined(typeof(ShellType), Type)) + if (ShellManager.ShellTypeExists(Type)) { if (SourceAlias == Destination) - { - DebugWriter.WriteDebug(DebugLevel.E, "Assertion succeeded: {0} = {1}", SourceAlias, Destination); - throw new KernelException(KernelExceptionType.AliasInvalidOperation, Translate.DoTranslation("Alias can't be the same name as a command.")); - } + throw new TerminauxException("Alias can't be the same name as a command."); else if (!CommandManager.IsCommandFound(SourceAlias, Type)) - { - DebugWriter.WriteDebug(DebugLevel.E, "{0} not found in all the command lists", Destination); - throw new KernelException(KernelExceptionType.AliasNoSuchCommand, Translate.DoTranslation("Command not found to alias to {0}."), Destination); - } + throw new TerminauxException("Command not found to alias to {0}.", Destination); else if (DoesAliasExist(Destination, Type)) + throw new TerminauxException("Alias already found: {0}", SourceAlias); + var aliasInstance = new AliasInfo() { - DebugWriter.WriteDebug(DebugLevel.E, "Alias {0} already found", SourceAlias); - throw new KernelException(KernelExceptionType.AliasAlreadyExists, Translate.DoTranslation("Alias already found: {0}"), SourceAlias); - } - else - { - DebugWriter.WriteDebug(DebugLevel.I, "Aliasing {0} to {1}", SourceAlias, Destination); - var aliasInstance = new AliasInfo() - { - alias = Destination, - command = SourceAlias, - type = Type, - }; - aliases.Add(aliasInstance); - return true; - } + alias = Destination, + command = SourceAlias, + type = Type, + }; + aliases.Add(aliasInstance); + return true; } else - { - DebugWriter.WriteDebug(DebugLevel.E, "Type {0} not found.", Type); - throw new KernelException(KernelExceptionType.AliasNoSuchType, Translate.DoTranslation("Invalid type {0}."), Type); - } + throw new TerminauxException("Invalid type {0}.", Type); } /// - /// Removes alias from kernel - /// - /// An alias that needs to be removed. - /// Alias type. - /// True if successful, False if unsuccessful. - public static bool RemoveAlias(string TargetAlias, ShellType Type) => - RemoveAlias(TargetAlias, ShellManager.GetShellTypeName(Type)); - - /// - /// Removes alias from kernel + /// Removes alias /// /// An alias that needs to be removed. /// Alias type. @@ -143,25 +76,12 @@ public static bool RemoveAlias(string TargetAlias, string Type) if (DoesAliasExist(TargetAlias, Type)) { var AliasInfo = GetAlias(TargetAlias, Type); - DebugWriter.WriteDebug(DebugLevel.I, "Target alias {0} is found under type {1}, so removing...", TargetAlias, Type); return aliases.Remove(AliasInfo); } else - { - DebugWriter.WriteDebug(DebugLevel.W, "{0} is not found in the {1} aliases", TargetAlias, Type.ToString()); - throw new KernelException(KernelExceptionType.AliasNoSuchAlias, Translate.DoTranslation("Alias {0} is not found to be removed."), TargetAlias); - } + throw new TerminauxException("Alias {0} is not found to be removed.", TargetAlias); } - /// - /// Checks to see if the specified alias exists. - /// - /// The existing alias - /// The alias type - /// True if it exists; false if it doesn't exist - public static bool DoesAliasExist(string TargetAlias, ShellType Type) => - DoesAliasExist(TargetAlias, ShellManager.GetShellTypeName(Type)); - /// /// Checks to see if the specified alias exists. /// @@ -169,47 +89,15 @@ public static bool DoesAliasExist(string TargetAlias, ShellType Type) => /// The alias type /// True if it exists; false if it doesn't exist public static bool DoesAliasExist(string TargetAlias, string Type) => - GetEntireAliasListFromType(Type).Any((info) => info.Alias == TargetAlias && info.Type == Type); + GetAliasListFromType(Type).Any((info) => info.Alias == TargetAlias && info.Type == Type); /// /// Gets the aliases list from the shell type /// /// Selected shell type - public static List GetAliasesListFromType(ShellType ShellType) => - GetAliasesListFromType(ShellManager.GetShellTypeName(ShellType)); - - /// - /// Gets the aliases list from the shell type - /// - /// Selected shell type - public static List GetAliasesListFromType(string ShellType) => + public static List GetAliasListFromType(string ShellType) => aliases.Where((info) => info.Type == ShellType).ToList(); - /// - /// Gets the aliases list from the shell type - /// - /// Selected shell type - public static List GetEntireAliasListFromType(ShellType ShellType) => - GetEntireAliasListFromType(ShellManager.GetShellTypeName(ShellType)); - - /// - /// Gets the aliases list from the shell type - /// - /// Selected shell type - public static List GetEntireAliasListFromType(string ShellType) => - aliases - .Union(builtinAliases) - .Where((info) => info.Type == ShellType).ToList(); - - /// - /// Gets the alias. - /// - /// The existing alias - /// The alias type - /// Alias info if it exists. Throws if it doesn't exist. - public static AliasInfo GetAlias(string TargetAlias, ShellType Type) => - GetAlias(TargetAlias, ShellManager.GetShellTypeName(Type)); - /// /// Gets the alias. /// @@ -219,10 +107,10 @@ public static AliasInfo GetAlias(string TargetAlias, ShellType Type) => public static AliasInfo GetAlias(string TargetAlias, string Type) { if (!DoesAliasExist(TargetAlias, Type)) - throw new KernelException(KernelExceptionType.AliasNoSuchAlias, Translate.DoTranslation("Alias {0} is not found to be queried."), TargetAlias); + throw new TerminauxException("Alias {0} is not found to be queried.", TargetAlias); // Get the list of available aliases and get an alias matching the target alias - var aliases = GetEntireAliasListFromType(Type); + var aliases = GetAliasListFromType(Type); return aliases.Single((info) => info.Alias == TargetAlias); } } diff --git a/Terminaux/Shell/Arguments/ArgumentsParser.cs b/Terminaux/Shell/Arguments/ArgumentsParser.cs index bce0287d0..9cd7a3a52 100644 --- a/Terminaux/Shell/Arguments/ArgumentsParser.cs +++ b/Terminaux/Shell/Arguments/ArgumentsParser.cs @@ -17,20 +17,17 @@ // along with this program. If not, see . // -using Nitrocid.Arguments; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using Nitrocid.Misc.Text.Probers.Regexp; -using Nitrocid.Modifications; using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; +using Terminaux.Base; using Terminaux.Shell.Aliases; using Terminaux.Shell.Commands; using Terminaux.Shell.Shells; using Terminaux.Shell.Switches; using Textify.General; +using Textify.Tools; namespace Terminaux.Shell.Arguments { @@ -39,15 +36,6 @@ namespace Terminaux.Shell.Arguments /// public static class ArgumentsParser { - /// - /// Parses the shell command arguments - /// - /// Command text that the user provided - /// Shell command type. Consult the enum for information about supported shells. - /// An array of that holds information about parsed command - public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ParseShellCommandArguments(string CommandText, ShellType CommandType) => - ParseShellCommandArguments(CommandText, null, ShellManager.GetShellTypeName(CommandType)); - /// /// Parses the shell command arguments /// @@ -57,16 +45,6 @@ public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ParseShellCommandArguments(string CommandText, string CommandType) => ParseShellCommandArguments(CommandText, null, CommandType); - /// - /// Parses the shell command arguments - /// - /// Command text that the user provided - /// Command information - /// Shell command type. Consult the enum for information about supported shells. - /// An array of that holds information about parsed command - public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ParseShellCommandArguments(string CommandText, CommandInfo? cmdInfo, ShellType CommandType) => - ParseShellCommandArguments(CommandText, cmdInfo, ShellManager.GetShellTypeName(CommandType)); - /// /// Parses the shell command arguments /// @@ -78,25 +56,20 @@ public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) { string Command; CommandInfo[] ShellCommands; - CommandInfo[] ModCommands; // Change the available commands list according to command type ShellCommands = CommandManager.GetCommands(CommandType); - ModCommands = ModManager.ListModCommands(CommandType); // Split the requested command string into words var words = CommandText.SplitEncloseDoubleQuotes(); var wordsOrig = CommandText.SplitEncloseDoubleQuotesNoRelease(); - string arguments = string.Join(' ', words.Skip(1)); - string argumentsOrig = string.Join(' ', wordsOrig.Skip(1)); - for (int i = 0; i <= words.Length - 1; i++) - DebugWriter.WriteDebug(DebugLevel.I, "Word {0}: {1}", i + 1, words[i]); + string arguments = string.Join(" ", words.Skip(1)); + string argumentsOrig = string.Join(" ", wordsOrig.Skip(1)); Command = words[0]; // Check to see if the caller has provided a switch that subtracts the number of required arguments - var aliases = AliasManager.GetEntireAliasListFromType(CommandType); - var CommandInfo = ModCommands.Any((info) => info.Command == Command) ? ModCommands.Single((info) => info.Command == Command) : - ShellCommands.Any((info) => info.Command == Command) ? ShellCommands.Single((info) => info.Command == Command) : + var aliases = AliasManager.GetAliasListFromType(CommandType); + var CommandInfo = ShellCommands.Any((info) => info.Command == Command) ? ShellCommands.Single((info) => info.Command == Command) : aliases.Any((info) => info.Alias == Command) ? aliases.Single((info) => info.Alias == Command).TargetCommand : cmdInfo; var fallback = new ProvidedArgumentsInfo(Command, arguments, words.Skip(1).ToArray(), argumentsOrig, wordsOrig.Skip(1).ToArray(), [], true, true, true, [], [], [], true, true, true, new()); @@ -105,69 +78,34 @@ public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) var shellInfo = ShellManager.GetShellInfo(CommandType); if (shellInfo.SlashCommand) { - if (!CommandText.StartsWith('/')) - { - // Change the command info to the non-slash one + // Either change the command info or strip the slash + if (!CommandText.StartsWith("/")) CommandInfo = cmdInfo; - } else - { - // Strip the slash - CommandText = CommandText[1..].Trim(); - } + CommandText = CommandText.Substring(1).Trim(); } // Now, process the arguments if (CommandInfo != null) - return ProcessArgumentOrShellCommandArguments(CommandText, CommandInfo, null); - else - return (fallback, new[] { fallback }); - } - - /// - /// Parses the kernel argument arguments - /// - /// Kernel argument text that the user provided - /// An array of that holds information about parsed command - public static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ParseArgumentArguments(string ArgumentText) - { - string Argument; - var KernelArguments = ArgumentParse.AvailableCMDLineArgs; - - // Split the requested argument string into words - var words = ArgumentText.SplitEncloseDoubleQuotes(); - var wordsOrig = ArgumentText.SplitEncloseDoubleQuotesNoRelease(); - string arguments = string.Join(' ', words.Skip(1)); - string argumentsOrig = string.Join(' ', wordsOrig.Skip(1)); - for (int i = 0; i <= words.Length - 1; i++) - DebugWriter.WriteDebug(DebugLevel.I, "Word {0}: {1}", i + 1, words[i]); - Argument = words[0]; - - // Check to see if the caller has provided a switch that subtracts the number of required arguments - var ArgumentInfo = KernelArguments.TryGetValue(Argument, out ArgumentInfo? argInfo) ? argInfo : null; - var fallback = new ProvidedArgumentsInfo(Argument, arguments, words.Skip(1).ToArray(), argumentsOrig, wordsOrig.Skip(1).ToArray(), [], true, true, true, [], [], [], true, true, true, new()); - if (ArgumentInfo != null) - return ProcessArgumentOrShellCommandArguments(ArgumentText, null, ArgumentInfo); + return ProcessArgumentOrShellCommandArguments(CommandText, CommandInfo); else return (fallback, new[] { fallback }); } - private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ProcessArgumentOrShellCommandArguments(string CommandText, CommandInfo? CommandInfo, ArgumentInfo? ArgumentInfo) + private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) ProcessArgumentOrShellCommandArguments(string CommandText, CommandInfo CommandInfo) { ProvidedArgumentsInfo? satisfiedArg = null; List totalArgs = []; - // Check the command and argument info - bool isCommand = CommandInfo is not null; - // Split the switches properly now string switchRegex = /* lang=regex */ @"((?<= )-\S+=((""(.+?)(? match.Value) - .ToArray(); - CommandText = RegexpTools.Filter(CommandText, switchRegex); + var matches = RegexTools.Matches(CommandText, switchRegex); + List enclosedSwitchList = []; + foreach (Match match in matches) + enclosedSwitchList.Add(match.Value); + string[] enclosedSwitches = [.. enclosedSwitchList]; + CommandText = RegexTools.Filter(CommandText, switchRegex); // Split the requested command string into words var words = CommandText.SplitEncloseDoubleQuotes(); @@ -178,24 +116,21 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) var EnclosedArgMatchesOrig = wordsOrig.Skip(1); var EnclosedArgs = EnclosedArgMatches.ToArray(); var EnclosedArgsOrig = EnclosedArgMatches.ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "{0} arguments parsed: {1}", EnclosedArgs.Length, string.Join(", ", EnclosedArgs)); // Get the string of arguments string strArgs = words.Length > 0 ? string.Join(" ", EnclosedArgMatches) : ""; string strArgsOrig = words.Length > 0 ? string.Join(" ", EnclosedArgMatchesOrig) : ""; - DebugWriter.WriteDebug(DebugLevel.I, "Finished strArgs: {0}", strArgs); - DebugWriter.WriteDebug(DebugLevel.I, "Finished strArgsOrig: {0}", strArgsOrig); // Split the switches to their key-value counterparts - var EnclosedSwitchKeyValuePairs = SwitchManager.GetSwitchValues(EnclosedSwitches, true); + var EnclosedSwitchKeyValuePairs = SwitchManager.GetSwitchValues(enclosedSwitches, true); // Check to see if we're optionalizing some required arguments starting from the last required argument int minimumArgumentsOffset = 0; string[] unknownSwitchesList = []; string[] conflictingSwitchesList = []; string[] noValueSwitchesList = []; - var argInfos = (isCommand ? CommandInfo?.CommandArgumentInfo : ArgumentInfo?.ArgArgumentInfo) ?? - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Can't get argument info for command or argument")); + var argInfos = CommandInfo?.CommandArgumentInfo ?? + throw new TerminauxException("Can't get argument info for command"); foreach (var argInfo in argInfos) { bool RequiredArgumentsProvided = true; @@ -205,26 +140,20 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) bool switchNumberProvided = true; bool exactWordingProvided = true; - // Check for argument info - DebugWriter.WriteDebug(DebugLevel.I, "Argument info is full? {0}", argInfo is not null); - // Optionalize some of the arguments if there are switches that optionalize them if (argInfo is not null) { - foreach (string enclosedSwitch in EnclosedSwitches) + foreach (string enclosedSwitch in enclosedSwitches) { - DebugWriter.WriteDebug(DebugLevel.I, "Optionalizer is processing switch {0}...", enclosedSwitch); - var switches = argInfo.Switches.Where((switchInfo) => switchInfo.SwitchName == enclosedSwitch[1..]); + var switches = argInfo.Switches.Where((switchInfo) => switchInfo.SwitchName == enclosedSwitch.Substring(1)); if (switches.Any()) foreach (var switchInfo in switches.Where(switchInfo => minimumArgumentsOffset < switchInfo.OptionalizeLastRequiredArguments)) minimumArgumentsOffset = switchInfo.OptionalizeLastRequiredArguments; - DebugWriter.WriteDebug(DebugLevel.I, "Minimum arguments offset is now {0}", minimumArgumentsOffset); } } int finalRequiredArgs = argInfo is not null ? argInfo.MinimumArguments - minimumArgumentsOffset : 0; if (finalRequiredArgs < 0) finalRequiredArgs = 0; - DebugWriter.WriteDebug(DebugLevel.I, "Required arguments count is now {0}", finalRequiredArgs); // Check to see if the caller has provided required number of arguments if (argInfo is not null) @@ -233,28 +162,26 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) !argInfo.ArgumentsRequired; else RequiredArgumentsProvided = true; - DebugWriter.WriteDebug(DebugLevel.I, "RequiredArgumentsProvided is {0}. Refer to the value of argument info.", RequiredArgumentsProvided); // Check to see if the caller has provided required number of switches if (argInfo is not null) RequiredSwitchesProvided = argInfo.Switches.Length == 0 || - EnclosedSwitches.Length >= argInfo.Switches.Where((@switch) => @switch.IsRequired).Count() || + enclosedSwitches.Length >= argInfo.Switches.Where((@switch) => @switch.IsRequired).Count() || !argInfo.Switches.Any((@switch) => @switch.IsRequired); else RequiredSwitchesProvided = true; - DebugWriter.WriteDebug(DebugLevel.I, "RequiredSwitchesProvided is {0}. Refer to the value of argument info.", RequiredSwitchesProvided); // Check to see if the caller has provided required number of switches that require arguments if (argInfo is not null) { - if (argInfo.Switches.Length == 0 || EnclosedSwitches.Length == 0 || + if (argInfo.Switches.Length == 0 || enclosedSwitches.Length == 0 || !argInfo.Switches.Any((@switch) => @switch.ArgumentsRequired)) RequiredSwitchArgumentsProvided = true; else { var allSwitches = argInfo.Switches.Where((@switch) => @switch.ArgumentsRequired).Select((@switch) => @switch.SwitchName).ToArray(); - var allProvidedSwitches = EnclosedSwitches.Where((@switch) => allSwitches.Contains($"{@switch[1..]}")).ToArray(); + var allProvidedSwitches = enclosedSwitches.Where((@switch) => allSwitches.Contains($"{@switch.Substring(1)}")).ToArray(); foreach (var providedSwitch in allProvidedSwitches) { if (string.IsNullOrWhiteSpace(EnclosedSwitchKeyValuePairs.Single((kvp) => kvp.Item1 == providedSwitch).Item2)) @@ -264,16 +191,15 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) } else RequiredSwitchArgumentsProvided = true; - DebugWriter.WriteDebug(DebugLevel.I, "RequiredSwitchArgumentsProvided is {0}. Refer to the value of argument info.", RequiredSwitchArgumentsProvided); // Check to see if the caller has provided switches that don't accept values with the values if (argInfo is not null) { var allSwitches = argInfo.Switches.Where((@switch) => !@switch.AcceptsValues).Select((@switch) => @switch.SwitchName).ToArray(); - var allProvidedSwitches = EnclosedSwitches + var allProvidedSwitches = enclosedSwitches .Where((@switch) => @switch.Contains('=')) - .Where((@switch) => allSwitches.Contains($"{@switch[1..@switch.IndexOf('=')]}")) - .Select((@switch) => $"{@switch[..@switch.IndexOf('=')]}") + .Where((@switch) => allSwitches.Contains($"{@switch.Substring(1, @switch.IndexOf("="))}")) + .Select((@switch) => $"{@switch.Substring(0, @switch.IndexOf("="))}") .ToArray(); List rejected = []; foreach (var providedSwitch in allProvidedSwitches) @@ -283,15 +209,13 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) } noValueSwitchesList = [.. rejected]; } - DebugWriter.WriteDebug(DebugLevel.I, "RequiredSwitchArgumentsProvided is {0}. Refer to the value of argument info.", RequiredSwitchArgumentsProvided); // Check to see if the caller has provided non-existent switches if (argInfo is not null) unknownSwitchesList = EnclosedSwitchKeyValuePairs .Select((kvp) => kvp.Item1) - .Where((key) => !argInfo.Switches.Any((switchInfo) => switchInfo.SwitchName == key[1..])) + .Where((key) => !argInfo.Switches.Any((switchInfo) => switchInfo.SwitchName == key.Substring(1))) .ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Unknown switches: {0}", unknownSwitchesList.Length); // Check to see if the caller has provided conflicting switches if (argInfo is not null) @@ -304,7 +228,6 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) string @switch = kvp.Item1; if (unknownSwitchesList.Contains(@switch)) continue; - DebugWriter.WriteDebug(DebugLevel.I, "Processing switch: {0}", @switch); // Get the switch and its conflicts list var switchEnumerator = argInfo.Switches @@ -316,18 +239,12 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) string[] switchConflicts = initialConflicts .Select((conflicting) => $"-{conflicting}") .ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Switch conflicts: {0} [{1}]", switchConflicts.Length, string.Join(", ", switchConflicts)); // Now, get the last switch and check to see if it's provided with the conflicting switch - string lastSwitch = processed.Count > 0 ? processed[^1] : ""; + string lastSwitch = processed.Count > 0 ? processed[processed.Count - 1] : ""; if (switchConflicts.Contains(lastSwitch)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Conflict! {0} and {1} conflict with each other.", @switch, lastSwitch); conflicts.Add($"{@switch} vs. {lastSwitch}"); - } processed.Add(@switch); - DebugWriter.WriteDebug(DebugLevel.I, "Marked conflicts: {0} [{1}]", conflicts.Count, string.Join(", ", conflicts)); - DebugWriter.WriteDebug(DebugLevel.I, "Processed: {0} [{1}]", processed.Count, string.Join(", ", processed)); } } conflictingSwitchesList = [.. conflicts]; @@ -390,7 +307,7 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) EnclosedArgs, strArgsOrig, EnclosedArgsOrig, - EnclosedSwitches, + enclosedSwitches, RequiredArgumentsProvided, RequiredSwitchesProvided, RequiredSwitchArgumentsProvided, @@ -415,7 +332,6 @@ private static (ProvidedArgumentsInfo? satisfied, ProvidedArgumentsInfo[] total) } // Install the parsed values to the new class instance - DebugWriter.WriteDebug(DebugLevel.I, "Finalizing..."); return (satisfiedArg, totalArgs.ToArray()); } } diff --git a/Terminaux/Shell/Arguments/CommandArgumentInfo.cs b/Terminaux/Shell/Arguments/CommandArgumentInfo.cs index b5785e370..d3c33d037 100644 --- a/Terminaux/Shell/Arguments/CommandArgumentInfo.cs +++ b/Terminaux/Shell/Arguments/CommandArgumentInfo.cs @@ -17,7 +17,6 @@ // along with this program. If not, see . // -using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -49,10 +48,10 @@ public class CommandArgumentInfo /// Command switches /// public SwitchInfo[] Switches { get; private set; } = [ - new SwitchInfo("set", /* Localizable */ "Sets the value of the output to the selected UESH variable", false, true) + new SwitchInfo("set", "Sets the value of the output to the selected MESH variable", false, true) ]; /// - /// Whether to accept the -set switch to set the UESH variable value + /// Whether to accept the -set switch to set the MESH variable value /// public bool AcceptsSet { get; private set; } /// diff --git a/Terminaux/Shell/Arguments/CommandArgumentPart.cs b/Terminaux/Shell/Arguments/CommandArgumentPart.cs index 378e8f4d0..97b1b45ff 100644 --- a/Terminaux/Shell/Arguments/CommandArgumentPart.cs +++ b/Terminaux/Shell/Arguments/CommandArgumentPart.cs @@ -86,7 +86,7 @@ public CommandArgumentPart(bool argumentRequired, string argumentExpression, Fun } // Then, the split by the slash (/) characters - if (!done && argumentExpression.Contains('/')) + if (!done && argumentExpression.Contains("/")) { string[] expressions = argumentExpression.Split('/'); autoCompleter = (_) => [.. expressions]; diff --git a/Terminaux/Shell/Arguments/CommandAutoComplete.cs b/Terminaux/Shell/Arguments/CommandAutoComplete.cs index 02e47524f..ccbad96db 100644 --- a/Terminaux/Shell/Arguments/CommandAutoComplete.cs +++ b/Terminaux/Shell/Arguments/CommandAutoComplete.cs @@ -17,10 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Files; -using Nitrocid.Files.Folders; -using Nitrocid.Files.Operations.Querying; -using Nitrocid.Kernel.Debugging; using System.IO; using System.Linq; using Terminaux.Shell.Commands; @@ -38,18 +34,15 @@ internal static class CommandAutoComplete internal static string[] GetSuggestions(string text, int index) { // First, cut the text to index - text = text[..index]; - DebugWriter.WriteDebug(DebugLevel.I, "Text to auto complete: {0} (idx: {1})", text, index); + text = text.Substring(0, index); // Then, check to see is we have shells - DebugWriter.WriteDebug(DebugLevel.I, "Shell count: {0}", ShellManager.ShellStack.Count); if (ShellManager.ShellStack.Count <= 0) return []; // Get the commands based on the current shell type var shellType = ShellManager.CurrentShellType; var ShellCommandNames = CommandManager.GetCommandNames(shellType); - DebugWriter.WriteDebug(DebugLevel.I, "Commands count for type {0}: {1}", shellType, ShellCommandNames.Length); // If text is not provided, return the command list without filtering if (string.IsNullOrEmpty(text)) @@ -64,36 +57,18 @@ internal static string[] GetSuggestions(string text, int index) string[] finalCommandArgsEnclosed = finalCommandArgs.SplitEncloseDoubleQuotes(); int LastArgumentIndex = finalCommandArgsEnclosed.Length - 1; string LastArgument = finalCommandArgsEnclosed.Length > 0 ? finalCommandArgsEnclosed[LastArgumentIndex] : ""; - DebugWriter.WriteDebug(DebugLevel.I, "Command name: {0}", CommandName); - DebugWriter.WriteDebug(DebugLevel.I, "Command arguments [{0}]: {1}", finalCommandArgsEnclosed.Length, finalCommandArgs); - DebugWriter.WriteDebug(DebugLevel.I, "last argument: {0}", LastArgument); - // Make a file and folder list - string[] finalCompletions; - if (!string.IsNullOrEmpty(finalCommandArgs)) + // Make a list + string[] finalCompletions = []; + if (string.IsNullOrEmpty(finalCommandArgs)) { - DebugWriter.WriteDebug(DebugLevel.I, "Creating list of files and directories starting with argument {0} [{1}]...", LastArgument, LastArgument.Length); - string lookupPath = Path.IsPathRooted(LastArgument) ? Path.GetDirectoryName(LastArgument) ?? "" : FilesystemTools.NeutralizePath(LastArgument, CurrentDirectory.CurrentDir); - lookupPath = Checking.FolderExists(lookupPath) ? lookupPath : Path.GetDirectoryName(CurrentDirectory.CurrentDir + "/" + LastArgument) ?? ""; - finalCompletions = Listing.CreateList(lookupPath, true) - .Select(x => Path.IsPathRooted(LastArgument) ? FilesystemTools.NeutralizePath(x.FilePath) : FilesystemTools.NeutralizePath(x.FilePath).Replace(CurrentDirectory.CurrentDir + "/", "")) - .Where(x => x.StartsWith(LastArgument)) - .Select(x => x[LastArgument.Length..]) - .ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Initially invoked, and got {0} autocompletion suggestions. [{1}]", finalCompletions.Length, string.Join(", ", finalCompletions)); - } - else - { - DebugWriter.WriteDebug(DebugLevel.I, "Creating list of commands starting with command {0} [{1}]...", CommandName, CommandName.Length); finalCompletions = ShellCommandNames .Where(x => x.StartsWith(CommandName)) - .Select(x => x[CommandName.Length..]) + .Select(x => x.Substring(CommandName.Length)) .ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Initially invoked, and got {0} autocompletion suggestions. [{1}]", finalCompletions.Length, string.Join(", ", finalCompletions)); } // Check to see if there is such command - DebugWriter.WriteDebug(DebugLevel.I, "Command {0} exists? {1}", CommandName, ShellCommandNames.Contains(CommandName)); if (!ShellCommandNames.Contains(CommandName)) return finalCompletions; @@ -102,9 +77,8 @@ internal static string[] GetSuggestions(string text, int index) var CommandArgumentInfos = cmdInfo.CommandArgumentInfo; foreach (var CommandArgumentInfo in CommandArgumentInfos) { - DebugWriter.WriteDebug(DebugLevel.I, "Command {0} has argument info? {1}", CommandName, CommandArgumentInfo is not null); if (CommandArgumentInfo is null) - // No arguments. Return file list + // No arguments. Return nothing return finalCompletions; // There are arguments! Now, check to see if it has the accessible auto completer from the last argument @@ -112,18 +86,15 @@ internal static string[] GetSuggestions(string text, int index) LastArgumentIndex < CommandArgumentInfo.Arguments.Length && LastArgumentIndex >= 0 ? CommandArgumentInfo.Arguments[LastArgumentIndex].Options.AutoCompleter : null; - DebugWriter.WriteDebug(DebugLevel.I, "Command {0} has auto complete info? {1}", CommandName, AutoCompleter is not null); if (AutoCompleter is null) - // No delegate. Return file list + // No delegate. Return nothing return finalCompletions; // We have the delegate! Invoke it. - DebugWriter.WriteDebug(DebugLevel.I, "If we reach here, it means we have a delegate! Executing delegate with {0} [{1}]...", LastArgument, LastArgument.Length); finalCompletions = AutoCompleter.Invoke(finalCommandArgsEnclosed) .Where(x => x.StartsWith(LastArgument)) - .Select(x => x[LastArgument.Length..]) + .Select(x => x.Substring(LastArgument.Length)) .ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Invoked, and got {0} autocompletion suggestions. [{1}]", finalCompletions.Length, string.Join(", ", finalCompletions)); return finalCompletions; } return finalCompletions; diff --git a/Terminaux/Shell/Arguments/CommandAutoCompletionList.cs b/Terminaux/Shell/Arguments/CommandAutoCompletionList.cs index 8abd159ad..3d2d4f401 100644 --- a/Terminaux/Shell/Arguments/CommandAutoCompletionList.cs +++ b/Terminaux/Shell/Arguments/CommandAutoCompletionList.cs @@ -17,18 +17,10 @@ // along with this program. If not, see . // -using Nitrocid.ConsoleBase.Themes; -using Nitrocid.Misc.Screensaver; -using Nitrocid.Misc.Splash; -using Nitrocid.Modifications; -using Nitrocid.Security.Permissions; -using Nitrocid.Users; -using Nitrocid.Users.Groups; using System; using System.Collections.Generic; using System.Linq; using Terminaux.Shell.Commands; -using Terminaux.Shell.Scripting; using Terminaux.Shell.Shells; namespace Terminaux.Shell.Arguments @@ -40,16 +32,6 @@ public static class CommandAutoCompletionList { private static readonly Dictionary> completions = new() { - { "user", (_) => UserManagement.ListAllUsers().ToArray() }, - { "username", (_) => UserManagement.ListAllUsers().ToArray() }, - { "group", (_) => GroupManagement.AvailableGroups.Select((group) => group.GroupName).ToArray() }, - { "groupname", (_) => GroupManagement.AvailableGroups.Select((group) => group.GroupName).ToArray() }, - { "modname", (_) => ModManager.ListMods().Keys.ToArray() }, - { "splashname", (_) => SplashManager.GetNamesOfSplashes() }, - { "saver", (_) => ScreensaverManager.GetScreensaverNames() }, - { "theme", (_) => ThemeTools.GetInstalledThemes().Keys.ToArray() }, - { "$variable", (_) => UESHVariables.Variables.Keys.ToArray() }, - { "perm", (_) => Enum.GetNames() }, { "cmd", (_) => PopulateCommands() }, { "command", (_) => PopulateCommands() }, { "shell", (_) => ShellManager.AvailableShells.Keys.ToArray() }, diff --git a/Terminaux/Shell/Commands/BaseCommand.cs b/Terminaux/Shell/Commands/BaseCommand.cs index 85ad1724e..82ba0401a 100644 --- a/Terminaux/Shell/Commands/BaseCommand.cs +++ b/Terminaux/Shell/Commands/BaseCommand.cs @@ -17,9 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; - namespace Terminaux.Shell.Commands { /// @@ -32,28 +29,20 @@ public abstract class BaseCommand : ICommand /// Executes a command /// /// Command parameters including passed arguments and switches information - /// Variable value to provide to target variable while -set is passed - /// Error code for the command - public virtual int Execute(CommandParameters parameters, ref string variableValue) - { - DebugWriter.WriteDebug(DebugLevel.F, "We shouldn't be here!!!"); - throw new KernelException(KernelExceptionType.NotImplementedYet); - } + public abstract void Execute(CommandParameters parameters); /// /// Executes a command on dumb consoles /// /// Command parameters including passed arguments and switches information - /// Variable value to provide to target variable while -set is passed - /// Error code for the command - public virtual int ExecuteDumb(CommandParameters parameters, ref string variableValue) => - Execute(parameters, ref variableValue); + public virtual void ExecuteDumb(CommandParameters parameters) => + Execute(parameters); /// /// The help helper /// - public virtual void HelpHelper() => - DebugWriter.WriteDebug(DebugLevel.I, "No additional information found."); + public virtual void HelpHelper() + { } } } diff --git a/Terminaux/Shell/Commands/CancellationHandlers.cs b/Terminaux/Shell/Commands/CancellationHandlers.cs deleted file mode 100644 index bcd5bf442..000000000 --- a/Terminaux/Shell/Commands/CancellationHandlers.cs +++ /dev/null @@ -1,113 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.Threading; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Drivers; -using Nitrocid.Drivers.Console; -using Terminaux.Writer.ConsoleWriters; -using Terminaux.Shell.Shells; - -namespace Terminaux.Shell.Commands -{ - /// - /// Cancellation handler tools - /// - public static class CancellationHandlers - { - - internal static CancellationTokenSource cts = new(); - internal static bool canCancel = false; - internal static bool installed; - internal static bool CancelRequested; - - /// - /// Allows cancelling the current command - /// - public static void AllowCancel() => - canCancel = true; - - /// - /// Prevents cancelling the current command - /// - public static void InhibitCancel() => - canCancel = false; - - internal static void CancelCommand(object? sender, ConsoleCancelEventArgs e) - { - // We can't cancel in a situation where there are no shells. - if (ShellManager.ShellStack.Count <= 0) - { - DebugWriter.WriteDebug(DebugLevel.W, "No shells. Can't cancel."); - e.Cancel = true; - return; - } - - // We can't cancel in situations where cancellation is not possible - if (!canCancel) - { - DebugWriter.WriteDebug(DebugLevel.W, "Cancellation impossible. Can't cancel."); - e.Cancel = true; - return; - } - - // Now, handle the command cancellation - try - { - var StartCommandThread = ShellManager.ShellStack[^1].ShellCommandThread; - var ProcessStartCommandThread = ShellManager.ProcessStartCommandThread; - var syncLock = GetCancelSyncLock(ShellManager.CurrentShellType); - lock (syncLock) - { - DebugWriter.WriteDebug(DebugLevel.I, "Locking to cancel..."); - CancelRequested = true; - TextWriterRaw.Write(); - DriverHandler.SetDriver("Null"); - cts.Cancel(); - ProcessStartCommandThread.Stop(); - DriverHandler.SetDriver("Default"); - DebugWriter.WriteDebug(DebugLevel.I, "Cancelled command."); - } - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Cannot cancel. {0}", ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - } - e.Cancel = true; - } - - internal static void InstallHandler() - { - if (!installed) - { - Console.CancelKeyPress += CancelCommand; - installed = true; - } - } - - internal static object GetCancelSyncLock(ShellType ShellType) => - GetCancelSyncLock(ShellManager.GetShellTypeName(ShellType)); - - internal static object GetCancelSyncLock(string ShellType) => - ShellManager.GetShellInfo(ShellType).ShellLock; - - } -} diff --git a/Terminaux/Shell/Commands/CommandExecutor.cs b/Terminaux/Shell/Commands/CommandExecutor.cs index 2269b0c81..fc57de87e 100644 --- a/Terminaux/Shell/Commands/CommandExecutor.cs +++ b/Terminaux/Shell/Commands/CommandExecutor.cs @@ -20,25 +20,14 @@ using System; using System.Threading; using System.Linq; -using System.Runtime; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Drivers; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Languages; -using Nitrocid.Drivers.Console; -using Nitrocid.Drivers.Console.Bases; -using Nitrocid.Kernel.Events; -using Nitrocid.ConsoleBase.Colors; using Terminaux.Writer.ConsoleWriters; -using Nitrocid.Kernel.Threading; using Textify.General; -using Nitrocid.Misc.Text.Probers.Regexp; -using Nitrocid.Kernel.Exceptions; -using Terminaux.Shell.Shells; using Terminaux.Shell.Arguments; -using Terminaux.Shell.Switches; -using Terminaux.Shell.Aliases; -using Terminaux.Shell.Scripting; +using Terminaux.Base.Checks; +using Terminaux.Base; +using Textify.Tools; +using Terminaux.Writer.CyclicWriters; +using Terminaux.Shell.Shells; namespace Terminaux.Shell.Commands { @@ -50,39 +39,20 @@ public static class CommandExecutor internal static void StartCommandThread(CommandExecutorParameters ThreadParams) { - // Since we're probably trying to run a command using the alternative command threads, if the main shell command thread - // is running, use that to execute the command. This ensures that commands like "wrap" that also execute commands from the - // shell can do their job. var ShellInstance = ThreadParams.ShellInstance; var StartCommandThread = ShellInstance.ShellCommandThread; - bool CommandThreadValid = true; - if (StartCommandThread.IsAlive) - { - DebugWriter.WriteDebug(DebugLevel.W, "Can't make another main command thread. Using alternatives..."); - if (ShellInstance.AltCommandThreads.Count > 0) - { - DebugWriter.WriteDebug(DebugLevel.I, "Using last alt command thread..."); - StartCommandThread = ShellInstance.AltCommandThreads[^1]; - } - else - { - DebugWriter.WriteDebug(DebugLevel.W, "Cmd exec {0} failed: Alt command threads are not there."); - CommandThreadValid = false; - } - } - if (CommandThreadValid) + if (!StartCommandThread.IsAlive) { - DebugWriter.WriteDebug(DebugLevel.I, "Starting command thread..."); StartCommandThread.Start(ThreadParams); - StartCommandThread.Wait(); - StartCommandThread.Stop(); + StartCommandThread.Join(); + ShellInstance.shellCommandThread = ShellManager.RegenerateCommandThread(ShellInstance.ShellType); } } internal static void ExecuteCommand(CommandExecutorParameters? ThreadParams) { if (ThreadParams is null) - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Thread parameters are not specified.")); + throw new TerminauxException("Thread parameters are not specified."); var RequestedCommand = ThreadParams.RequestedCommand; var RequestedCommandInfo = ThreadParams.RequestedCommandInfo; string ShellType = ThreadParams.ShellType; @@ -97,8 +67,7 @@ internal static void ExecuteCommand(CommandExecutorParameters? ThreadParams) argSatisfied = satisfied is not null; if (satisfied is null) { - DebugWriter.WriteDebug(DebugLevel.W, "Arguments not satisfied."); - TextWriters.Write(Translate.DoTranslation("Required arguments are not provided for all usages below:"), true, KernelColorType.Error); + TextWriterRaw.WritePlain("Required arguments are not provided for all usages below:"); for (int i = 0; i < total.Length; i++) { ProvidedArgumentsInfo unsatisfied = total[i]; @@ -106,346 +75,115 @@ internal static void ExecuteCommand(CommandExecutorParameters? ThreadParams) var argInfo = unsatisfied.ArgumentInfo; if (argInfo is null) { - TextWriters.Write($"- [{i + 1}] {command}: ", false, KernelColorType.ListEntry); - TextWriters.Write(Translate.DoTranslation("Unknown argument"), false, KernelColorType.ListValue); + TextWriterRaw.WritePlain($"- [{i + 1}] {command}: ", false); + TextWriterRaw.WritePlain("Unknown argument"); continue; } // Write usage number string renderedUsage = !string.IsNullOrEmpty(argInfo.RenderedUsage) ? " " + argInfo.RenderedUsage : ""; - TextWriters.Write($"- [{i + 1}] {command}{renderedUsage}", true, KernelColorType.ListEntry); + TextWriterRaw.WritePlain($"- [{i + 1}] {command}{renderedUsage}"); // Check for required arguments if (!unsatisfied.RequiredArgumentsProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User hasn't provided enough arguments for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("Required arguments are not provided."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("Required arguments are not provided."); // Check for required switches if (!unsatisfied.RequiredSwitchesProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User hasn't provided enough switches for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("Required switches are not provided."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("Required switches are not provided."); // Check for required switch arguments if (!unsatisfied.RequiredSwitchArgumentsProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User hasn't provided a value for one of the switches for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("One of the switches requires a value that is not provided."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("One of the switches requires a value that is not provided."); // Check for unknown switches if (unsatisfied.UnknownSwitchesList.Length > 0) { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided unknown switches {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("Switches that are listed below are unknown."), true, KernelColorType.ListValue); - ListWriterColor.WriteList(unsatisfied.UnknownSwitchesList); + TextWriterRaw.WritePlain("Switches that are listed below are unknown."); + TextWriterRaw.WriteRaw(new Listing() + { + Objects = unsatisfied.UnknownSwitchesList, + }.Render()); } // Check for conflicting switches if (unsatisfied.ConflictingSwitchesList.Length > 0) { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided conflicting switches for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("Switches that are listed below conflict with each other."), true, KernelColorType.ListValue); - ListWriterColor.WriteList(unsatisfied.ConflictingSwitchesList); + TextWriterRaw.WritePlain("Switches that are listed below conflict with each other."); + TextWriterRaw.WriteRaw(new Listing() + { + Objects = unsatisfied.ConflictingSwitchesList, + }.Render()); } // Check for switches that don't accept values if (unsatisfied.NoValueSwitchesList.Length > 0) { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided switches that don't accept values for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("The below switches don't accept values."), true, KernelColorType.ListValue); - ListWriterColor.WriteList(unsatisfied.NoValueSwitchesList); + TextWriterRaw.WritePlain("The below switches don't accept values."); + TextWriterRaw.WriteRaw(new Listing() + { + Objects = unsatisfied.NoValueSwitchesList, + }.Render()); } // Check for invalid number in numeric arguments if (!unsatisfied.NumberProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided invalid number for one or more of the arguments for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("One or more of the arguments expect a numeric value, but you provided an invalid number."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("One or more of the arguments expect a numeric value, but you provided an invalid number."); // Check for invalid exact wording if (!unsatisfied.ExactWordingProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided non-exact wording for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("One or more of the arguments expect an exact wording, but you provided an invalid word."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("One or more of the arguments expect an exact wording, but you provided an invalid word."); // Check for invalid number in numeric switches if (!unsatisfied.SwitchNumberProvided) - { - DebugWriter.WriteDebug(DebugLevel.W, "User has provided invalid number for one or more of the switches for {0}", command); - TextWriters.Write(" - " + Translate.DoTranslation("One or more of the switches expect a numeric value, but you provided an invalid number."), true, KernelColorType.ListValue); - } + TextWriterRaw.WritePlain("One or more of the switches expect a numeric value, but you provided an invalid number."); } - TextWriters.Write(Translate.DoTranslation("Consult the help entry for this command for more info"), KernelColorType.NeutralText); - ShellInstance.LastErrorCode = -6; + TextWriterRaw.WritePlain("Consult the help entry for this command for more info"); return; } // Now, assume that an argument is satisfied var ArgumentInfo = satisfied; string Command = ArgumentInfo.Command; - var Args = ArgumentInfo.ArgumentsList.Select(RegexpTools.Unescape).ToArray(); + var Args = ArgumentInfo.ArgumentsList.Select(RegexTools.Unescape).ToArray(); var ArgsOrig = ArgumentInfo.ArgumentsListOrig; - var Switches = ArgumentInfo.SwitchesList.Select(RegexpTools.Unescape).ToArray(); - string StrArgs = RegexpTools.Unescape(ArgumentInfo.ArgumentsText); + var Switches = ArgumentInfo.SwitchesList.Select(RegexTools.Unescape).ToArray(); + string StrArgs = RegexTools.Unescape(ArgumentInfo.ArgumentsText); string StrArgsOrig = ArgumentInfo.ArgumentsTextOrig; - bool containsSetSwitch = SwitchManager.ContainsSwitch(Switches, "-set"); - string variable = ""; - - // Check to see if a requested command is obsolete - if (RequestedCommandInfo.Flags.HasFlag(CommandFlags.Obsolete)) - { - DebugWriter.WriteDebug(DebugLevel.I, "The command requested {0} is obsolete", Command); - TextWriterColor.Write(Translate.DoTranslation("This command is obsolete and will be removed in a future release.")); - } - - // If there are enough arguments provided, execute. Otherwise, fail with not enough arguments. - var ArgInfos = RequestedCommandInfo.CommandArgumentInfo; - for (int i = 0; i < ArgInfos.Length; i++) - { - argSatisfied = true; - CommandArgumentInfo ArgInfo = ArgInfos[i]; - bool isLast = i == ArgInfos.Length - 1; - if (ArgInfo is not null) - { - // Trim the -set switch - if (containsSetSwitch) - { - // First, work on the string - string setValue = $"-set={SwitchManager.GetSwitchValue(Switches, "-set")}"; - - // Work on the list - if (Switches.Contains(setValue)) - { - for (int j = 0; j < Switches.Length; j++) - { - string @switch = Switches[j]; - if (@switch == setValue && ArgInfo.AcceptsSet) - { - variable = SwitchManager.GetSwitchValue(Switches, "-set"); - Switches = Switches.Except([setValue]).ToArray(); - break; - } - } - } - } - } - if (argSatisfied) - break; - } // Execute the command if (argSatisfied) { // Prepare the command parameter instance - var parameters = new CommandParameters(StrArgs, Args, StrArgsOrig, ArgsOrig, Switches, Command) - { - SwitchSetPassed = containsSetSwitch - }; + var parameters = new CommandParameters(StrArgs, Args, StrArgsOrig, ArgsOrig, Switches, Command); // Now, get the base command and execute it - DebugWriter.WriteDebug(DebugLevel.I, "Really executing command {0} with args {1}", Command, StrArgs); var CommandBase = RequestedCommandInfo.CommandBase; - string value = ""; - CancellationHandlers.cts = new CancellationTokenSource(); -#pragma warning disable SYSLIB0046 - try - { - ControlledExecution.Run(() => CommandDelegate(ShellInstance, CommandBase, parameters, ref value), CancellationHandlers.cts.Token); - } - catch (OperationCanceledException ex) - { - DebugWriter.WriteDebug(DebugLevel.W, "Command aborted in the .NET Framework way. This is currently not supported as it may corrupt the state. Any weird behavior logged below is most likely from this."); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Command has been aborted."), true, KernelColorType.Error); - } -#pragma warning restore SYSLIB0046 - - // Set the error code and set the UESH variable as appropriate - DebugWriter.WriteDebug(DebugLevel.I, "Error code is {0}", ShellInstance.LastErrorCode); - if (containsSetSwitch) - { - // Check to see if the value contains newlines - if (value.Contains('\n')) - { - // Assume that we're setting an array. - DebugWriter.WriteDebug(DebugLevel.I, "Array variable to set is {0}", variable); - string[] values = value.Replace((char)13, default).Split('\n'); - UESHVariables.SetVariables(variable, values); - } - else if (value.StartsWith('[') && value.EndsWith(']')) - { - // Assume that we're setting an array - DebugWriter.WriteDebug(DebugLevel.I, "Array variable to set is {0}", variable); - value = value[1..(value.Length - 1)]; - string[] values = value.Split(", "); - UESHVariables.SetVariables(variable, values); - } - else - { - DebugWriter.WriteDebug(DebugLevel.I, "Variable to set {0} is {1}", value, variable); - UESHVariables.SetVariable(variable, value); - } - } - } - else - { - DebugWriter.WriteDebug(DebugLevel.W, "Arguments not satisfied."); - ShellInstance.LastErrorCode = -6; + CommandDelegate(CommandBase, parameters); } } catch (ThreadInterruptedException) { - CancellationHandlers.CancelRequested = false; - ShellInstance.LastErrorCode = -5; + TextWriterRaw.WritePlain("Command is being interrupted..."); } catch (Exception ex) { - EventsManager.FireEvent(EventType.CommandError, ShellType, RequestedCommand, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Failed to execute command {0} from type {1}: {2}", RequestedCommand, ShellType.ToString(), ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Error trying to execute command") + " {2}." + CharManager.NewLine + Translate.DoTranslation("Error {0}: {1}"), true, KernelColorType.Error, ex.GetType().FullName ?? "", ex.Message, RequestedCommand); - ShellInstance.LastErrorCode = ex.GetHashCode(); + TextWriterRaw.WritePlain("Error trying to execute command {2}." + CharManager.NewLine + "Error {0}: {1}", ex.GetType().FullName ?? "", ex.Message, RequestedCommand); } } - /// - /// Executes a command in a wrapped mode (must be run from a separate command execution entry point, .) - /// - /// Requested command with its arguments and switches - public static void ExecuteCommandWrapped(string Command) - { - var currentShell = ShellManager.ShellStack[^1]; - var currentType = currentShell.ShellType; - var StartCommandThread = currentShell.ShellCommandThread; - var (satisfied, total) = ArgumentsParser.ParseShellCommandArguments(Command, currentType); - string CommandToBeWrapped = total[0].Command; - - // Check to see if the command is found - if (!CommandManager.IsCommandFound(CommandToBeWrapped, currentType)) - { - DebugWriter.WriteDebug(DebugLevel.E, "Wrappable command {0} not found", Command); - TextWriters.Write(Translate.DoTranslation("The wrappable command is not found."), true, KernelColorType.Error); - return; - } - - // Check to see if we can start an alternative thread - if (!StartCommandThread.IsAlive) - { - DebugWriter.WriteDebug(DebugLevel.E, "Can't directly execute command {0} in wrapped mode.", Command); - TextWriters.Write(Translate.DoTranslation("You must not directly execute this command in a wrapped mode."), true, KernelColorType.Error); - return; - } - - // Now, check to see if the command is wrappable - if (!CommandManager.GetCommand(CommandToBeWrapped, currentType).Flags.HasFlag(CommandFlags.Wrappable)) - { - var WrappableCmds = GetWrappableCommands(currentType); - DebugWriter.WriteDebug(DebugLevel.E, "Unwrappable command {0}! Wrappable commands: [{1}]", Command, string.Join(", ", WrappableCmds)); - TextWriters.Write(Translate.DoTranslation("The command is not wrappable. These commands are wrappable:"), true, KernelColorType.Error); - ListWriterColor.WriteList(WrappableCmds); - return; - } - - bool buffered = false; - try - { - // First, initialize the alternative command thread - var AltThreads = ShellManager.ShellStack[^1].AltCommandThreads; - if (AltThreads.Count == 0 || AltThreads[^1].IsAlive) - { - DebugWriter.WriteDebug(DebugLevel.I, "Making alt thread for wrapped command {0}...", Command); - var WrappedCommand = new KernelThread($"Wrapped Shell Command Thread", false, (cmdThreadParams) => ExecuteCommand((CommandExecutorParameters?)cmdThreadParams)); - ShellManager.ShellStack[^1].AltCommandThreads.Add(WrappedCommand); - } - - // Then, initialize the buffered writer and execute the commands - DriverHandler.BeginLocalDriver("Buffered"); - DebugWriter.WriteDebug(DebugLevel.I, "Buffering..."); - ShellManager.GetLine(Command, "", currentType, false, false); - CancellationHandlers.AllowCancel(); - buffered = true; - - // Extract the buffer and then end the local driver - var wrapBuffer = ((Buffered)DriverHandler.CurrentConsoleDriverLocal).consoleBuffer; - var wrapOutput = wrapBuffer.ToString(); - wrapBuffer.Clear(); - DriverHandler.EndLocalDriver(); - - // Now, print the output - DebugWriter.WriteDebug(DebugLevel.I, "Printing..."); - TextDynamicWriters.WriteWrapped(wrapOutput, false, KernelColorType.NeutralText); - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Failed to wrap command {0}: {1}", CommandToBeWrapped, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("An error occurred while trying to wrap a command output") + ": {0}", true, KernelColorType.Error, ex.Message); - } - - // In case error happens - if (!buffered) - DriverHandler.EndLocalDriver(); - } - - /// - /// Gets the wrappable commands - /// - /// Shell type - /// List of commands that one of their flags contains - public static string[] GetWrappableCommands(ShellType shellType) => - GetWrappableCommands(ShellManager.GetShellTypeName(shellType)); - - /// - /// Gets the wrappable commands - /// - /// Shell type - /// List of commands that one of their flags contains - public static string[] GetWrappableCommands(string shellType) - { - // Get shell info - var shellInfo = ShellManager.GetShellInfo(shellType); - - // Get wrappable commands - var WrappableCmds = shellInfo.Commands - .Where(CommandInfo => CommandInfo.Flags.HasFlag(CommandFlags.Wrappable)) - .Select(CommandInfo => CommandInfo.Command) - .ToArray(); - var WrappableUnified = ShellManager.UnifiedCommands - .Where(CommandInfo => CommandInfo.Flags.HasFlag(CommandFlags.Wrappable)) - .Select(CommandInfo => CommandInfo.Command) - .ToArray(); - var WrappableAliases = AliasManager.GetEntireAliasListFromType(shellType) - .Where((info) => WrappableCmds.Contains(info.Command) || WrappableUnified.Contains(info.Command)) - .Select((info) => info.Alias) - .ToArray(); - var finalWrappables = WrappableCmds - .Union(WrappableAliases) - .Union(WrappableUnified) - .ToArray(); - - return finalWrappables; - } - - private static void CommandDelegate(ShellExecuteInfo ShellInstance, BaseCommand CommandBase, CommandParameters parameters, ref string value) + private static void CommandDelegate(BaseCommand CommandBase, CommandParameters parameters) { try { - if (DriverHandler.CurrentConsoleDriverLocal.IsDumb) - ShellInstance.LastErrorCode = CommandBase.ExecuteDumb(parameters, ref value); + if (ConsoleChecker.IsDumb) + CommandBase.ExecuteDumb(parameters); else - ShellInstance.LastErrorCode = CommandBase.Execute(parameters, ref value); + CommandBase.Execute(parameters); } catch (Exception ex) { - DebugWriter.WriteDebug(DebugLevel.E, $"Command aborted: {ex.Message}"); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Command aborted for the following reason:") + $" {ex.Message}", KernelColorType.Error); + TextWriterRaw.WritePlain($"Command aborted for the following reason: {ex.Message}"); } } diff --git a/Terminaux/Shell/Commands/CommandExecutorParameters.cs b/Terminaux/Shell/Commands/CommandExecutorParameters.cs index 6b4ffce7c..096ce6dae 100644 --- a/Terminaux/Shell/Commands/CommandExecutorParameters.cs +++ b/Terminaux/Shell/Commands/CommandExecutorParameters.cs @@ -47,10 +47,6 @@ internal class CommandExecutorParameters /// internal ShellExecuteInfo ShellInstance; - internal CommandExecutorParameters(string RequestedCommand, CommandInfo RequestedCommandInfo, ShellType ShellType, ShellExecuteInfo ShellInstance) : - this(RequestedCommand, RequestedCommandInfo, ShellManager.GetShellTypeName(ShellType), ShellInstance) - { } - internal CommandExecutorParameters(string RequestedCommand, CommandInfo RequestedCommandInfo, string ShellType, ShellExecuteInfo ShellInstance) { this.RequestedCommand = RequestedCommand; diff --git a/Terminaux/Shell/Commands/CommandFlags.cs b/Terminaux/Shell/Commands/CommandFlags.cs deleted file mode 100644 index 507149591..000000000 --- a/Terminaux/Shell/Commands/CommandFlags.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Commands -{ - /// - /// Command flags - /// - public enum CommandFlags - { - /// - /// No flags - /// - None = 0, - /// - /// The command is strict, meaning that it's only available for administrators. - /// - Strict = 1, - /// - /// This command can't run in maintenance mode. - /// - NoMaintenance = 2, - /// - /// The command is obsolete. - /// - Obsolete = 4, - /// - /// Redirection is supported, meaning that all the output to the commands can be redirected to a file. - /// - RedirectionSupported = 8, - /// - /// This command is wrappable to pages. - /// - Wrappable = 16, - } -} diff --git a/Terminaux/Shell/Commands/CommandInfo.cs b/Terminaux/Shell/Commands/CommandInfo.cs index 79f12d076..810be992f 100644 --- a/Terminaux/Shell/Commands/CommandInfo.cs +++ b/Terminaux/Shell/Commands/CommandInfo.cs @@ -17,7 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Languages; using System.Linq; using Terminaux.Shell.Aliases; using Terminaux.Shell.Arguments; @@ -35,7 +34,7 @@ public class CommandInfo /// public string Command { get; private set; } /// - /// The untranslated help definition of command. Translated by + /// The help definition of command /// public string HelpDefinition { get; set; } /// @@ -47,14 +46,10 @@ public class CommandInfo /// public BaseCommand CommandBase { get; private set; } /// - /// Command properties - /// - public CommandFlags Flags { get; private set; } - /// /// Aliases for this command /// public AliasInfo[] Aliases => - AliasManager.builtinAliases.Union(AliasManager.aliases) + AliasManager.aliases .Where((ai) => ai.Command == Command) .ToArray(); @@ -65,14 +60,12 @@ public class CommandInfo /// Command help definition /// Command argument info /// Command base for execution - /// Command flags - public CommandInfo(string Command, string HelpDefinition, CommandArgumentInfo[]? CommandArgumentInfo, BaseCommand? CommandBase, CommandFlags Flags = CommandFlags.None) + public CommandInfo(string Command, string HelpDefinition, CommandArgumentInfo[]? CommandArgumentInfo, BaseCommand? CommandBase) { this.Command = Command; this.HelpDefinition = HelpDefinition; this.CommandArgumentInfo = CommandArgumentInfo ?? []; this.CommandBase = CommandBase ?? new UndefinedCommand(); - this.Flags = Flags; } /// @@ -83,12 +76,5 @@ public CommandInfo(string Command, string HelpDefinition, CommandArgumentInfo[]? internal CommandInfo(string Command, string HelpDefinition) : this(Command, HelpDefinition, null, null) { } - - /// - /// Gets the translated version of help entry (KS built-in commands and addon commands only) - /// - public string GetTranslatedHelpEntry() => - Translate.DoTranslation(HelpDefinition); - } } diff --git a/Terminaux/Shell/Commands/CommandManager.cs b/Terminaux/Shell/Commands/CommandManager.cs index b263d19bf..40169bbc5 100644 --- a/Terminaux/Shell/Commands/CommandManager.cs +++ b/Terminaux/Shell/Commands/CommandManager.cs @@ -17,20 +17,14 @@ // along with this program. If not, see . // -extern alias TextifyDep; - -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using Nitrocid.Misc.Splash; -using Nitrocid.Misc.Text.Probers.Regexp; -using Nitrocid.Modifications; using System; using System.Collections.Generic; -using TextifyDep::System.Diagnostics.CodeAnalysis; using System.Linq; using Textify.General; using Terminaux.Shell.Shells; +using System.Diagnostics.CodeAnalysis; +using Terminaux.Base; +using Textify.Tools; namespace Terminaux.Shell.Commands { @@ -39,26 +33,14 @@ namespace Terminaux.Shell.Commands /// public static class CommandManager { - /// - /// Checks to see if the command is found in selected shell command type - /// - /// A command - /// The shell type - /// True if found; False if not found or shell type is invalid. - public static bool IsCommandFound(string Command, ShellType ShellType) => - IsCommandFound(Command, ShellManager.GetShellTypeName(ShellType)); - /// /// Checks to see if the command is found in selected shell command type /// /// A command /// The shell type name /// True if found; False if not found or shell type is invalid. - public static bool IsCommandFound(string Command, string ShellType) - { - DebugWriter.WriteDebug(DebugLevel.I, "Command: {0}, ShellType: {1}", Command, ShellType); - return GetCommands(ShellType).Any((ci) => ci.Command == Command || ci.Aliases.Any((ai) => ai.Alias == Command)); - } + public static bool IsCommandFound(string Command, string ShellType) => + GetCommands(ShellType).Any((ci) => ci.Command == Command || ci.Aliases.Any((ai) => ai.Alias == Command)); /// /// Checks to see if the command is found in all the shells @@ -67,7 +49,6 @@ public static bool IsCommandFound(string Command, string ShellType) /// True if found; False if not found. public static bool IsCommandFound(string Command) { - DebugWriter.WriteDebug(DebugLevel.I, "Command: {0}", Command); bool found = false; foreach (var ShellType in ShellManager.AvailableShells.Keys) { @@ -78,13 +59,6 @@ public static bool IsCommandFound(string Command) return found; } - /// - /// Gets the command list according to the shell type - /// - /// The shell type - public static CommandInfo[] GetCommands(ShellType ShellType) => - GetCommands(ShellManager.GetShellTypeName(ShellType)); - /// /// Gets the command list according to the shell type /// @@ -93,8 +67,7 @@ public static CommandInfo[] GetCommands(string ShellType) { // Individual shells var shellInfo = ShellManager.GetShellInfo(ShellType); - var addonCommands = ShellManager.GetShellInfo(ShellType).addonCommands; - var modCommands = ModManager.ListModCommands(ShellType); + var extraCommands = ShellManager.GetShellInfo(ShellType).extraCommands; List FinalCommands = shellInfo.Commands; // Unified commands @@ -104,30 +77,16 @@ public static CommandInfo[] GetCommands(string ShellType) FinalCommands.Add(UnifiedCommand); } - // Addon commands - foreach (var AddonCommand in addonCommands) - { - if (!FinalCommands.Contains(AddonCommand)) - FinalCommands.Add(AddonCommand); - } - - // Mod commands - foreach (var ModCommand in modCommands) + // Extra commands + foreach (var ExtraCommand in extraCommands) { - if (!FinalCommands.Contains(ModCommand)) - FinalCommands.Add(ModCommand); + if (!FinalCommands.Contains(ExtraCommand)) + FinalCommands.Add(ExtraCommand); } return [.. FinalCommands]; } - /// - /// Gets the command names according to the shell type - /// - /// The shell type - public static string[] GetCommandNames(ShellType ShellType) => - GetCommandNames(ShellManager.GetShellTypeName(ShellType)); - /// /// Gets the command names according to the shell type /// @@ -139,14 +98,6 @@ public static string[] GetCommandNames(string ShellType) return FinalCommands; } - /// - /// Gets the command list according to the shell type by searching for the partial command name - /// - /// A valid regex pattern for command name - /// The shell type - public static CommandInfo[] FindCommands([StringSyntax(StringSyntaxAttribute.Regex)] string namePattern, ShellType ShellType) => - FindCommands(namePattern, ShellManager.GetShellTypeName(ShellType)); - /// /// Gets the command list according to the shell type by searching for the partial command name /// @@ -155,28 +106,19 @@ public static CommandInfo[] FindCommands([StringSyntax(StringSyntaxAttribute.Reg public static CommandInfo[] FindCommands([StringSyntax(StringSyntaxAttribute.Regex)] string namePattern, string ShellType) { // Verify that the provided regex is valid - if (!RegexpTools.IsValidRegex(namePattern)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Invalid command pattern provided.")); + if (!RegexTools.IsValidRegex(namePattern)) + throw new TerminauxException("Invalid command pattern provided."); // Get all the commands first var allCommands = GetCommands(ShellType); // Now, find the commands that match the specified regex pattern. var foundCommands = allCommands - .Where((info) => RegexpTools.IsMatch(info.Command, namePattern)) + .Where((info) => RegexTools.IsMatch(info.Command, namePattern)) .ToArray(); return foundCommands; } - /// - /// Gets a command, specified by the shell type - /// - /// A command - /// The shell type - /// A instance of a specified command - public static CommandInfo GetCommand(string Command, ShellType ShellType) => - GetCommand(Command, ShellManager.GetShellTypeName(ShellType)); - /// /// Gets a command, specified by the shell type /// @@ -185,21 +127,12 @@ public static CommandInfo GetCommand(string Command, ShellType ShellType) => /// True if found; False if not found or shell type is invalid. public static CommandInfo GetCommand(string Command, string ShellType) { - DebugWriter.WriteDebug(DebugLevel.I, "Command: {0}, ShellType: {1}", Command, ShellType); var commandList = GetCommands(ShellType); if (!IsCommandFound(Command, ShellType)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Command not found.")); + throw new TerminauxException("Command not found."); return commandList.Single((ci) => ci.Command == Command || ci.Aliases.Any((ai) => ai.Alias == Command)); } - /// - /// Registers a command to the mod command list - /// - /// Type of Nitrocid's built-in shell - /// Custom command base to register - public static void RegisterCustomCommand(ShellType ShellType, CommandInfo? commandBase) => - RegisterCustomCommand(ShellManager.GetShellTypeName(ShellType), commandBase); - /// /// Registers a command to the mod command list /// @@ -209,46 +142,29 @@ public static void RegisterCustomCommand(string ShellType, CommandInfo? commandB { // First, check the values if (!ShellManager.ShellTypeExists(ShellType)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Shell type {0} doesn't exist."), ShellType); + throw new TerminauxException("Shell type {0} doesn't exist.", ShellType); if (commandBase is null) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command base.")); + throw new TerminauxException("You must provide the command base."); string command = commandBase.Command; - DebugWriter.WriteDebug(DebugLevel.I, "Trying to register {0}, ShellType: {1}", command, ShellType); // Check the command name if (string.IsNullOrEmpty(command)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command.")); + throw new TerminauxException("You must provide the command."); // Check to see if the command conflicts with pre-existing shell commands if (IsCommandFound(command, ShellType)) - { - DebugWriter.WriteDebug(DebugLevel.E, "Command {0} conflicts with available shell commands or mod commands.", command); - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("The command specified is already added! It's possible that you may have conflicting mods.")); - } + throw new TerminauxException("The command specified is already added."); // Check to see if the help definition is full if (string.IsNullOrEmpty(commandBase.HelpDefinition)) - { - SplashReport.ReportProgress(Translate.DoTranslation("No definition for command {0}."), command); - DebugWriter.WriteDebug(DebugLevel.W, "No definition, {0}.Def = \"Command not defined\"", command); - commandBase.HelpDefinition = Translate.DoTranslation("Command not defined"); - } + commandBase.HelpDefinition = "Command not defined"; - // Now, add the command to the mod list - DebugWriter.WriteDebug(DebugLevel.I, "Adding command {0} for {1}...", command, ShellType); - if (!ModManager.ListModCommands(ShellType).Contains(commandBase)) - ShellManager.GetShellInfo(ShellType).ModCommands.Add(commandBase); - DebugWriter.WriteDebug(DebugLevel.I, "Registered {0}, ShellType: {1}", command, ShellType); + // Now, add the command to the extra list + var info = ShellManager.GetShellInfo(ShellType); + if (!info.extraCommands.Contains(commandBase)) + info.extraCommands.Add(commandBase); } - /// - /// Registers a group of custom commands - /// - /// Type of Nitrocid's built-in shell - /// Custom command bases to register - public static void RegisterCustomCommands(ShellType ShellType, CommandInfo[] commandBases) => - RegisterCustomCommands(ShellManager.GetShellTypeName(ShellType), commandBases); - /// /// Registers a group of custom commands /// @@ -265,55 +181,38 @@ public static void RegisterCustomCommands(string ShellType, CommandInfo[] comman } catch (Exception ex) { - DebugWriter.WriteDebug(DebugLevel.E, $"Can't register custom command: {ex.Message}"); - DebugWriter.WriteDebugStackTrace(ex); - failedCommands.Add($" - {(commandBase is not null ? commandBase.Command : "???")}: {(ex is KernelException kex ? kex.OriginalExceptionMessage : ex.Message)}"); + failedCommands.Add($" - {(commandBase is not null ? commandBase.Command : "???")}: {ex.Message}"); } } if (failedCommands.Count > 0) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Some of the custom commands can't be loaded.") + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); + throw new TerminauxException("Some of the custom commands can't be loaded." + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); } - /// - /// Unregisters a custom command - /// - /// Type of Nitrocid's built-in shell - /// Custom command name to unregister - public static void UnregisterCustomCommand(ShellType ShellType, string? commandName) => - UnregisterCustomCommand(ShellManager.GetShellTypeName(ShellType), commandName); - /// /// Unregisters a custom command /// /// Type of a shell, including your custom type and other mod's custom type to extend it /// Custom command name to unregister - public static void UnregisterCustomCommand(string ShellType, string? commandName) + public static void UnregisterCustomCommand(string ShellType, string commandName) { // First, check the values if (!ShellManager.ShellTypeExists(ShellType)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Shell type {0} doesn't exist."), ShellType); + throw new TerminauxException("Shell type {0} doesn't exist.", ShellType); if (string.IsNullOrEmpty(commandName)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command.")); + throw new TerminauxException("You must provide the command."); // Check to see if we have this command if (!GetCommandNames(ShellType).Contains(commandName)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("The custom command specified is not found.")); + throw new TerminauxException("The custom command specified is not found."); else { // We have the command. Remove it. var cmd = GetCommand(commandName, ShellType); - ShellManager.GetShellInfo(ShellType).ModCommands.Remove(cmd); + var info = ShellManager.GetShellInfo(ShellType); + info.extraCommands.Remove(cmd); } } - /// - /// Unregisters a group of custom commands - /// - /// Type of Nitrocid's built-in shell - /// Custom command names to unregister - public static void UnregisterCustomCommands(ShellType ShellType, string[] commandNames) => - UnregisterCustomCommands(ShellManager.GetShellTypeName(ShellType), commandNames); - /// /// Unregisters a group of custom commands /// @@ -330,160 +229,11 @@ public static void UnregisterCustomCommands(string ShellType, string[] commandNa } catch (Exception ex) { - DebugWriter.WriteDebug(DebugLevel.E, $"Can't unregister custom command: {ex.Message}"); - DebugWriter.WriteDebugStackTrace(ex); - failedCommands.Add($" - {(!string.IsNullOrEmpty(commandBase) ? commandBase : "???")}: {(ex is KernelException kex ? kex.OriginalExceptionMessage : ex.Message)}"); - } - } - if (failedCommands.Count > 0) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Some of the custom commands can't be unloaded.") + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); - } - - /// - /// Registers a command to the addon command list - /// - /// Type of Nitrocid's built-in shell - /// Custom command base to register - internal static void RegisterAddonCommand(ShellType ShellType, CommandInfo commandBase) => - RegisterAddonCommand(ShellManager.GetShellTypeName(ShellType), commandBase); - - /// - /// Registers a command to the addon command list - /// - /// Type of a shell, including your custom type and other addon's custom type to extend it - /// Custom command base to register - internal static void RegisterAddonCommand(string ShellType, CommandInfo commandBase) - { - // First, check the values - if (!ShellManager.ShellTypeExists(ShellType)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Shell type {0} doesn't exist."), ShellType); - if (commandBase is null) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command base.")); - string command = commandBase.Command; - DebugWriter.WriteDebug(DebugLevel.I, "Trying to register {0}, ShellType: {1}", command, ShellType); - - // Check the command name - if (string.IsNullOrEmpty(command)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command.")); - - // Check to see if the command conflicts with pre-existing shell commands - if (IsCommandFound(command, ShellType)) - { - DebugWriter.WriteDebug(DebugLevel.E, "Command {0} conflicts with available shell commands or addon commands.", command); - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("The command specified is already added! It's possible that you may have conflicting addons.")); - } - - // Check to see if the help definition is full - if (string.IsNullOrEmpty(commandBase.HelpDefinition)) - { - SplashReport.ReportProgress(Translate.DoTranslation("No definition for command {0}."), command); - DebugWriter.WriteDebug(DebugLevel.W, "No definition, {0}.Def = \"Command not defined\"", command); - commandBase.HelpDefinition = Translate.DoTranslation("Command not defined"); - } - - // Now, add the command to the addon list - DebugWriter.WriteDebug(DebugLevel.I, "Adding command {0} for {1}...", command, ShellType); - if (!ShellManager.AvailableShells[ShellType].addonCommands.Contains(commandBase)) - ShellManager.AvailableShells[ShellType].addonCommands.Add(commandBase); - DebugWriter.WriteDebug(DebugLevel.I, "Registered {0}, ShellType: {1}", command, ShellType); - } - - /// - /// Registers a group of addon commands - /// - /// Type of Nitrocid's built-in shell - /// Addon command bases to register - internal static void RegisterAddonCommands(ShellType ShellType, CommandInfo[] commandBases) => - RegisterAddonCommands(ShellManager.GetShellTypeName(ShellType), commandBases); - - /// - /// Registers a group of addon commands - /// - /// Type of a shell, including your custom type and other addon's custom type to extend it - /// Addon command bases to register - internal static void RegisterAddonCommands(string ShellType, CommandInfo[] commandBases) - { - List failedCommands = []; - foreach (var commandBase in commandBases) - { - try - { - RegisterAddonCommand(ShellType, commandBase); - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, $"Can't register addon command: {ex.Message}"); - DebugWriter.WriteDebugStackTrace(ex); - failedCommands.Add($" - {(commandBase is not null ? commandBase.Command : "???")}: {(ex is KernelException kex ? kex.OriginalExceptionMessage : ex.Message)}"); - } - } - if (failedCommands.Count > 0) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Some of the addon commands can't be loaded.") + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); - } - - /// - /// Unregisters a addon command - /// - /// Type of Nitrocid's built-in shell - /// Addon command name to unregister - internal static void UnregisterAddonCommand(ShellType ShellType, string commandName) => - UnregisterAddonCommand(ShellManager.GetShellTypeName(ShellType), commandName); - - /// - /// Unregisters a addon command - /// - /// Type of a shell, including your custom type and other addon's custom type to extend it - /// Addon command name to unregister - internal static void UnregisterAddonCommand(string ShellType, string commandName) - { - // First, check the values - if (!ShellManager.ShellTypeExists(ShellType)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Shell type {0} doesn't exist."), ShellType); - if (string.IsNullOrEmpty(commandName)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("You must provide the command.")); - - // Check to see if we have this command - if (!GetCommandNames(ShellType).Contains(commandName)) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("The addon command specified is not found.")); - else - { - // We have the command. Remove it. - var cmd = GetCommand(commandName, ShellType); - ShellManager.availableShells[ShellType].addonCommands.Remove(cmd); - } - } - - /// - /// Unregisters a group of addon commands - /// - /// Type of Nitrocid's built-in shell - /// Addon command names to unregister - internal static void UnregisterAddonCommands(ShellType ShellType, string[] commandNames) => - UnregisterAddonCommands(ShellManager.GetShellTypeName(ShellType), commandNames); - - /// - /// Unregisters a group of addon commands - /// - /// Type of a shell, including your custom type and other addon's custom type to extend it - /// Addon command names to unregister - internal static void UnregisterAddonCommands(string ShellType, string[] commandNames) - { - List failedCommands = []; - foreach (string commandBase in commandNames) - { - try - { - UnregisterAddonCommand(ShellType, commandBase); - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, $"Can't unregister addon command: {ex.Message}"); - DebugWriter.WriteDebugStackTrace(ex); - failedCommands.Add($" - {(!string.IsNullOrEmpty(commandBase) ? commandBase : "???")}: {(ex is KernelException kex ? kex.OriginalExceptionMessage : ex.Message)}"); + failedCommands.Add($" - {(!string.IsNullOrEmpty(commandBase) ? commandBase : "???")}: {ex.Message}"); } } if (failedCommands.Count > 0) - throw new KernelException(KernelExceptionType.CommandManager, Translate.DoTranslation("Some of the addon commands can't be unloaded.") + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); + throw new TerminauxException("Some of the custom commands can't be unloaded." + CharManager.NewLine + string.Join(CharManager.NewLine, failedCommands)); } } } diff --git a/Terminaux/Shell/Commands/CommandParameters.cs b/Terminaux/Shell/Commands/CommandParameters.cs index b9dc0ff1b..fde648032 100644 --- a/Terminaux/Shell/Commands/CommandParameters.cs +++ b/Terminaux/Shell/Commands/CommandParameters.cs @@ -84,10 +84,6 @@ public class CommandParameters /// public string[] SwitchesList => listSwitchesOnly; - /// - /// Whether the -set=var switch has been passed to the command or not - /// - public bool SwitchSetPassed { get; internal set; } internal CommandParameters(string stringArgs, string[] listArgsOnly, string stringArgsOrig, string[] listArgsOnlyOrig, string[] listSwitchesOnly, string commandName) { diff --git a/Terminaux/Shell/Commands/ICommand.cs b/Terminaux/Shell/Commands/ICommand.cs index b900f3408..eeeb8897c 100644 --- a/Terminaux/Shell/Commands/ICommand.cs +++ b/Terminaux/Shell/Commands/ICommand.cs @@ -29,17 +29,13 @@ public interface ICommand /// Executes the command with the given argument /// /// Command parameters including passed arguments and switches information - /// Variable value to provide to target variable while -set is passed - /// Error code for the command - int Execute(CommandParameters parameters, ref string variableValue); + void Execute(CommandParameters parameters); /// /// Executes the command with the given argument on dumb consoles /// /// Command parameters including passed arguments and switches information - /// Variable value to provide to target variable while -set is passed - /// Error code for the command - int ExecuteDumb(CommandParameters parameters, ref string variableValue); + void ExecuteDumb(CommandParameters parameters); /// /// Shows additional information for the command when "help command" is invoked diff --git a/Terminaux/Shell/Commands/ProcessExecution/ExecuteProcessThreadParameters.cs b/Terminaux/Shell/Commands/ProcessExecution/ExecuteProcessThreadParameters.cs deleted file mode 100644 index e7813128e..000000000 --- a/Terminaux/Shell/Commands/ProcessExecution/ExecuteProcessThreadParameters.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Commands.ProcessExecution -{ - /// - /// Thread parameters for ExecuteProcess() - /// - internal class ExecuteProcessThreadParameters - { - /// - /// Full path to file - /// - internal string File; - /// - /// Arguments, if any - /// - internal string Args; - - internal ExecuteProcessThreadParameters(string File, string Args) - { - this.File = File; - this.Args = Args; - } - } -} diff --git a/Terminaux/Shell/Commands/ProcessExecution/ProcessExecutor.cs b/Terminaux/Shell/Commands/ProcessExecution/ProcessExecutor.cs deleted file mode 100644 index cfed78ea5..000000000 --- a/Terminaux/Shell/Commands/ProcessExecution/ProcessExecutor.cs +++ /dev/null @@ -1,346 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.Diagnostics; -using System.Threading; -using System.Text; -using System.Reflection; -using Nitrocid.Kernel.Debugging; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Files.Folders; -using Nitrocid.Languages; -using Nitrocid.Kernel.Events; -using Nitrocid.ConsoleBase.Colors; -using Terminaux.Writer.ConsoleWriters; -using Textify.General; -using Nitrocid.Kernel.Exceptions; - -namespace Terminaux.Shell.Commands.ProcessExecution -{ - /// - /// Process executor module - /// - public static class ProcessExecutor - { - - /// - /// Executes a file with specified arguments - /// - internal static void ExecuteProcess(ExecuteProcessThreadParameters? ThreadParams) - { - if (ThreadParams is null) - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Can't get thread parameters for process execution.")); - ExecuteProcess(ThreadParams.File, ThreadParams.Args); - } - - /// - /// Executes a file with specified arguments - /// - /// Full path to file - /// Arguments, if any - /// Application exit code. -1 if internal error occurred. - public static int ExecuteProcess(string File, string Args) => - ExecuteProcess(File, Args, CurrentDirectory.CurrentDir); - - /// - /// Executes a file with specified arguments - /// - /// Full path to file - /// Arguments, if any - /// Specifies the working directory - /// Application exit code. -1 if internal error occurred. - public static int ExecuteProcess(string File, string Args, string WorkingDirectory) - { - try - { - bool HasProcessExited = false; - var CommandProcess = new Process(); - var CommandProcessStart = new ProcessStartInfo() - { - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - FileName = File, - Arguments = Args, - WorkingDirectory = WorkingDirectory, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = false - }; - CommandProcess.StartInfo = CommandProcessStart; - CommandProcess.EnableRaisingEvents = true; - CommandProcess.OutputDataReceived += ExecutableOutput; - CommandProcess.ErrorDataReceived += ExecutableOutput; - CommandProcess.Exited += (sender, args) => HasProcessExited = true; - - // Start the process - DebugWriter.WriteDebug(DebugLevel.I, "Starting process {0} with working directory {1} and arguments {2}...", File, WorkingDirectory, Args); - CommandProcess.Start(); - CommandProcess.BeginOutputReadLine(); - CommandProcess.BeginErrorReadLine(); - - // Wait for process exit - while (!HasProcessExited | !CancellationHandlers.CancelRequested) - { - if (HasProcessExited) - { - DebugWriter.WriteDebug(DebugLevel.W, "Process exited! Output may not be complete!"); - CommandProcess.WaitForExit(); - DebugWriter.WriteDebug(DebugLevel.I, "Flushed as much as possible."); - break; - } - else if (CancellationHandlers.CancelRequested) - { - DebugWriter.WriteDebug(DebugLevel.W, "Process killed! Output may not be complete!"); - CommandProcess.Kill(); - CommandProcess.WaitForExit(); - DebugWriter.WriteDebug(DebugLevel.I, "Flushed as much as possible."); - break; - } - } - DebugWriter.WriteDebug(DebugLevel.I, "Process exited with exit code {0}.", CommandProcess.ExitCode); - return CommandProcess.ExitCode; - } - catch (ThreadInterruptedException) - { - CancellationHandlers.CancelRequested = false; - return default; - } - catch (Exception ex) - { - EventsManager.FireEvent(EventType.ProcessError, File + Args, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Process error for {0}, {1}, {2}: {3}.", File, WorkingDirectory, Args, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Error trying to execute command") + " {2}." + CharManager.NewLine + Translate.DoTranslation("Error {0}: {1}"), true, KernelColorType.Error, ex.GetType().FullName ?? "", ex.Message, File); - } - return -1; - } - - /// - /// Executes a file with specified arguments and puts the output to the string - /// - /// Full path to file - /// Arguments, if any - /// Application exit code. -1 if internal error occurred - /// Include output printed to StdErr - /// Output of a command from stdout - public static string ExecuteProcessToString(string File, string Args, ref int exitCode, bool includeStdErr) => - ExecuteProcessToString(File, Args, CurrentDirectory.CurrentDir, ref exitCode, includeStdErr); - - /// - /// Executes a file with specified arguments and puts the output to the string - /// - /// Full path to file - /// Arguments, if any - /// Specifies the working directory - /// Application exit code. -1 if internal error occurred - /// Include output printed to StdErr - /// Output of a command from stdout - public static string ExecuteProcessToString(string File, string Args, string WorkingDirectory, ref int exitCode, bool includeStdErr) - { - var commandOutputBuilder = new StringBuilder(); - try - { - bool HasProcessExited = false; - var CommandProcess = new Process(); - var CommandProcessStart = new ProcessStartInfo() - { - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = includeStdErr, - FileName = File, - Arguments = Args, - WorkingDirectory = WorkingDirectory, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - UseShellExecute = false - }; - CommandProcess.StartInfo = CommandProcessStart; - - // Set events up - void DataReceivedHandler(object _, DataReceivedEventArgs data) - { - if (data.Data is not null) - commandOutputBuilder.Append(data.Data); - } - CommandProcess.EnableRaisingEvents = true; - CommandProcess.OutputDataReceived += DataReceivedHandler; - if (includeStdErr) - CommandProcess.ErrorDataReceived += DataReceivedHandler; - CommandProcess.Exited += (sender, args) => HasProcessExited = true; - - // Start the process - DebugWriter.WriteDebug(DebugLevel.I, "Starting process {0} with working directory {1} and arguments {2}...", File, WorkingDirectory, Args); - CommandProcess.Start(); - CommandProcess.BeginOutputReadLine(); - if (includeStdErr) - CommandProcess.BeginErrorReadLine(); - - // Wait for process exit - while (!HasProcessExited | !CancellationHandlers.CancelRequested) - { - if (HasProcessExited) - { - DebugWriter.WriteDebug(DebugLevel.W, "Process exited! Output may not be complete!"); - CommandProcess.WaitForExit(); - DebugWriter.WriteDebug(DebugLevel.I, "Flushed as much as possible."); - break; - } - else if (CancellationHandlers.CancelRequested) - { - DebugWriter.WriteDebug(DebugLevel.W, "Process killed! Output may not be complete!"); - CommandProcess.Kill(); - CommandProcess.WaitForExit(); - DebugWriter.WriteDebug(DebugLevel.I, "Flushed as much as possible."); - break; - } - } - DebugWriter.WriteDebug(DebugLevel.I, "Process exited with exit code {0}.", CommandProcess.ExitCode); - exitCode = CommandProcess.ExitCode; - } - catch (ThreadInterruptedException) - { - CancellationHandlers.CancelRequested = false; - exitCode = -1; - } - catch (Exception ex) - { - EventsManager.FireEvent(EventType.ProcessError, File + Args, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Process error for {0}, {1}, {2}: {3}.", File, WorkingDirectory, Args, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Error trying to execute command") + " {2}." + CharManager.NewLine + Translate.DoTranslation("Error {0}: {1}"), true, KernelColorType.Error, ex.GetType().FullName ?? "", ex.Message, File); - exitCode = -1; - } - return commandOutputBuilder.ToString(); - } - - /// - /// Executes a file with specified arguments to a separate window. Doesn't block. - /// - internal static void ExecuteProcessForked(ExecuteProcessThreadParameters ThreadParams) => - ExecuteProcessForked(ThreadParams.File, ThreadParams.Args); - - /// - /// Executes a file with specified arguments to a separate window. Doesn't block. - /// - /// Full path to file - /// Arguments, if any - /// Application exit code. -1 if internal error occurred. - public static void ExecuteProcessForked(string File, string Args) => - ExecuteProcessForked(File, Args, CurrentDirectory.CurrentDir); - - /// - /// Executes a file with specified arguments to a separate window. Doesn't block. - /// - /// Full path to file - /// Arguments, if any - /// Specifies the working directory - /// Application exit code. -1 if internal error occurred. - public static void ExecuteProcessForked(string File, string Args, string WorkingDirectory) - { - try - { - var CommandProcess = new Process(); - var CommandProcessStart = new ProcessStartInfo() - { - FileName = File, - Arguments = Args, - WorkingDirectory = WorkingDirectory, - UseShellExecute = true, - }; - CommandProcess.StartInfo = StripEnvironmentVariables(CommandProcessStart); - - // Start the process - DebugWriter.WriteDebug(DebugLevel.I, "Starting process {0} with working directory {1} and arguments {2}...", File, WorkingDirectory, Args); - CommandProcess.Start(); - } - catch (ThreadInterruptedException) - { - CancellationHandlers.CancelRequested = false; - } - catch (Exception ex) - { - EventsManager.FireEvent(EventType.ProcessError, File + Args, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Process error for {0}, {1}, {2}: {3}.", File, WorkingDirectory, Args, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Error trying to execute command") + " {2}." + CharManager.NewLine + Translate.DoTranslation("Error {0}: {1}"), true, KernelColorType.Error, ex.GetType().FullName ?? "", ex.Message, File); - } - } - - internal static ProcessStartInfo StripEnvironmentVariables(ProcessStartInfo processStartInfo) - { - // --- UseShellExecute and the Environment property population Hack --- - // - // We need UseShellExecute to be able to use the runas verb, but it looks like that we can't start the process with the VS debugger, - // because the StartInfo always populates the _environmentVariables field once the Environment property is populated. - // _environmentVariables is not a public field. - // - // .NET expects _environmentVariables to be null when trying to start the process with the UseShellExecute being set to true, - // but when calling Start(), .NET calls StartWithShellExecuteEx() and checks to see if that variable is null, so executing the - // process in this way is basically impossible after evaluating the Environment property without having to somehow nullify this - // _environmentVariables field using private reflection after evaluating the Environment property. - // - // if (startInfo._environmentVariables != null) - // throw new InvalidOperationException(SR.CantUseEnvVars); - // - // Please DO NOT even try to evaluate selfProcess.StartInfo.Environment in your debugger even if hovering over selfProcess.StartInfo, - // because that would undo all the changes that we've made to the _environmentVariables and causes us to lose all the changes made - // to this instance of StartInfo. - // - // if (_environmentVariables == null) - // { - // IDictionary envVars = System.Environment.GetEnvironmentVariables(); - // _environmentVariables = new DictionaryWrapper(new Dictionary( - // (...) - // } - // - // This hack is only applicable to developers debugging the StartInfo instance of this specific process using VS. Nitrocid should - // be able to restart itself as elevated normally if no debugger is attached. - // - // References: - // - https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs#L47 - // - https://github.com/dotnet/runtime/blob/release/8.0/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs#L91 - // - // Issue report: https://github.com/dotnet/runtime/issues/94338 - var privateReflection = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField; - var startInfoType = processStartInfo.GetType(); - var envVarsField = startInfoType.GetField("_environmentVariables", privateReflection) ?? - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Can't get internal field for environment variables")); - envVarsField.SetValue(processStartInfo, null); - // - // --- UseShellExecute and the Environment property population Hack End --- - return processStartInfo; - } - - /// - /// Handles executable output - /// - /// Sender - /// Output - private static void ExecutableOutput(object sendingProcess, DataReceivedEventArgs outLine) - { - if (outLine.Data is null) - return; - DebugWriter.WriteDebug(DebugLevel.I, outLine.Data); - TextWriterColor.Write(outLine.Data); - } - - } -} diff --git a/Terminaux/Shell/Commands/SlashReminderCommand.cs b/Terminaux/Shell/Commands/SlashReminderCommand.cs index 650665c44..c7f189977 100644 --- a/Terminaux/Shell/Commands/SlashReminderCommand.cs +++ b/Terminaux/Shell/Commands/SlashReminderCommand.cs @@ -17,20 +17,17 @@ // along with this program. If not, see . // -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Languages; +using Terminaux.Writer.ConsoleWriters; namespace Terminaux.Shell.Commands { internal class SlashReminderCommand : BaseCommand, ICommand { - public override int Execute(CommandParameters parameters, ref string variableValue) + public override void Execute(CommandParameters parameters) { - TextWriters.Write( - "* " + Translate.DoTranslation("This shell uses the slash commands to execute the commands. Please append the slash symbol '/' to the beginning of the command to get started. For example:") + $" /{parameters.CommandText} {parameters.ArgumentsText}", true, KernelColorType.Tip); - return 0; + TextWriterRaw.WritePlain( + "* This shell uses the slash commands to execute the commands. Please append the slash symbol '/' to the beginning of the command to get started. For example:" + $" /{parameters.CommandText} {parameters.ArgumentsText}"); } } diff --git a/Terminaux/Shell/Commands/UndefinedCommand.cs b/Terminaux/Shell/Commands/UndefinedCommand.cs index 3e19e8010..9289bd09a 100644 --- a/Terminaux/Shell/Commands/UndefinedCommand.cs +++ b/Terminaux/Shell/Commands/UndefinedCommand.cs @@ -17,8 +17,15 @@ // along with this program. If not, see . // +using System; + namespace Terminaux.Shell.Commands { internal class UndefinedCommand : BaseCommand, ICommand - { } + { + public override void Execute(CommandParameters parameters) + { + throw new NotImplementedException("This command is not defined."); + } + } } diff --git a/Terminaux/Shell/Help/HelpPrint.cs b/Terminaux/Shell/Help/HelpPrint.cs index 8795b4474..f6812a660 100644 --- a/Terminaux/Shell/Help/HelpPrint.cs +++ b/Terminaux/Shell/Help/HelpPrint.cs @@ -17,7 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Kernel.Configuration; using Terminaux.Shell.Shells; namespace Terminaux.Shell.Help @@ -31,36 +30,24 @@ public static class HelpPrint /// Shows the list of commands under the current shell type /// /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelp(bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended("", ShellManager.CurrentShellType, Config.MainConfig.SimHelp, showGeneral, showMod, showAlias, showUnified, showAddon); - - /// - /// Shows the list of commands under the specified shell type - /// - /// A specified shell type - /// Shows all general commands - /// Shows all mod commands - /// Shows all aliased commands - /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelp(ShellType commandType, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended("", ShellManager.GetShellTypeName(commandType), Config.MainConfig.SimHelp, showGeneral, showMod, showAlias, showUnified, showAddon); + /// Shows all kernel extra commands + public static void ShowHelp(bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) => + ShowHelpExtended("", ShellManager.CurrentShellType, false, showGeneral, showAlias, showUnified, showExtra, showCount); /// /// Shows the help of a command, or command list under the current shell type if nothing is specified /// /// A specified command /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelp(string command, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended(command, ShellManager.CurrentShellType, Config.MainConfig.SimHelp, showGeneral, showMod, showAlias, showUnified, showAddon); + /// Shows all kernel extra commands + public static void ShowHelp(string command, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) => + ShowHelpExtended(command, ShellManager.CurrentShellType, false, showGeneral, showAlias, showUnified, showExtra, showCount); /// /// Shows the help of a command, or command list under the specified shell type if nothing is specified @@ -68,50 +55,24 @@ public static void ShowHelp(string command, bool showGeneral = true, bool showMo /// A specified command /// A specified shell type /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelp(string command, ShellType commandType, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended(command, ShellManager.GetShellTypeName(commandType), Config.MainConfig.SimHelp, showGeneral, showMod, showAlias, showUnified, showAddon); - - /// - /// Shows the help of a command, or command list under the specified shell type if nothing is specified - /// - /// A specified command - /// A specified shell type - /// Shows all general commands - /// Shows all mod commands - /// Shows all aliased commands - /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelp(string command, string commandType, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended(command, commandType, Config.MainConfig.SimHelp, showGeneral, showMod, showAlias, showUnified, showAddon); + /// Shows all kernel extra commands + public static void ShowHelp(string command, string commandType, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) => + ShowHelpExtended(command, commandType, false, showGeneral, showAlias, showUnified, showExtra, showCount); /// /// Shows the list of commands under the current shell type /// /// Uses simplified help /// Shows all general commands - /// Shows all mod commands - /// Shows all aliased commands - /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelpExtended(bool simplified = false, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended("", ShellManager.CurrentShellType, simplified, showGeneral, showMod, showAlias, showUnified, showAddon); - - /// - /// Shows the list of commands under the specified shell type - /// - /// Uses simplified help - /// A specified shell type - /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelpExtended(ShellType commandType, bool simplified = false, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended("", ShellManager.GetShellTypeName(commandType), simplified, showGeneral, showMod, showAlias, showUnified, showAddon); + /// Shows all kernel extra commands + public static void ShowHelpExtended(bool simplified = false, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) => + ShowHelpExtended("", ShellManager.CurrentShellType, simplified, showGeneral, showAlias, showUnified, showExtra, showCount); /// /// Shows the help of a command, or command list under the current shell type if nothing is specified @@ -119,26 +80,12 @@ public static void ShowHelpExtended(ShellType commandType, bool simplified = fal /// Uses simplified help /// A specified command /// Shows all general commands - /// Shows all mod commands - /// Shows all aliased commands - /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelpExtended(string command, bool simplified = false, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended(command, ShellManager.CurrentShellType, simplified, showGeneral, showMod, showAlias, showUnified, showAddon); - - /// - /// Shows the help of a command, or command list under the specified shell type if nothing is specified - /// - /// Uses simplified help - /// A specified command - /// A specified shell type - /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelpExtended(string command, ShellType commandType, bool simplified = false, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) => - ShowHelpExtended(command, ShellManager.GetShellTypeName(commandType), simplified, showGeneral, showMod, showAlias, showUnified, showAddon); + /// Shows all kernel extra commands + public static void ShowHelpExtended(string command, bool simplified = false, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) => + ShowHelpExtended(command, ShellManager.CurrentShellType, simplified, showGeneral, showAlias, showUnified, showExtra, showCount); /// /// Shows the help of a command, or command list under the specified shell type if nothing is specified @@ -147,11 +94,11 @@ public static void ShowHelpExtended(string command, ShellType commandType, bool /// A specified command /// A specified shell type /// Shows all general commands - /// Shows all mod commands + /// Shows command count /// Shows all aliased commands /// Shows all unified commands - /// Shows all kernel addon commands - public static void ShowHelpExtended(string command, string commandType, bool simplified = false, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) + /// Shows all kernel extra commands + public static void ShowHelpExtended(string command, string commandType, bool simplified = false, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) { // Check to see if command exists if (!string.IsNullOrWhiteSpace(command)) @@ -162,7 +109,7 @@ public static void ShowHelpExtended(string command, string commandType, bool sim if (simplified) HelpPrintTools.ShowCommandListSimplified(commandType); else - HelpPrintTools.ShowCommandList(commandType, showGeneral, showMod, showAlias, showUnified, showAddon); + HelpPrintTools.ShowCommandList(commandType, showGeneral, showAlias, showUnified, showExtra, showCount); } } } diff --git a/Terminaux/Shell/Help/HelpPrintTools.cs b/Terminaux/Shell/Help/HelpPrintTools.cs index efdaf7370..9e33536f5 100644 --- a/Terminaux/Shell/Help/HelpPrintTools.cs +++ b/Terminaux/Shell/Help/HelpPrintTools.cs @@ -20,14 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.ConsoleBase.Writers; using Terminaux.Writer.ConsoleWriters; -using Nitrocid.Kernel; -using Nitrocid.Kernel.Configuration; -using Nitrocid.Languages; -using Nitrocid.Modifications; -using Nitrocid.Users; using Textify.General; using Terminaux.Shell.Switches; using Terminaux.Shell.Shells; @@ -39,97 +32,68 @@ namespace Terminaux.Shell.Help { internal static class HelpPrintTools { - internal static void ShowCommandList(string commandType, bool showGeneral = true, bool showMod = false, bool showAlias = false, bool showUnified = false, bool showAddon = false) + internal static void ShowCommandList(string commandType, bool showGeneral = true, bool showAlias = false, bool showUnified = false, bool showExtra = false, bool showCount = false) { // Get general commands var commands = CommandManager.GetCommands(commandType); var commandList = ShellManager.GetShellInfo(commandType).Commands; - // Add every command from each mod, addon, and alias - var ModCommandList = ModManager.ListModCommands(commandType); - var AddonCommandList = ShellManager.GetShellInfo(commandType).addonCommands; + // Add every command from each extra and alias + var ExtraCommandList = ShellManager.GetShellInfo(commandType).extraCommands; var unifiedCommandList = ShellManager.unifiedCommandDict; - var AliasedCommandList = AliasManager.GetEntireAliasListFromType(commandType) + var AliasedCommandList = AliasManager.GetAliasListFromType(commandType) .ToDictionary((ai) => ai, (ai) => ai.TargetCommand); - TextWriters.Write(Translate.DoTranslation("Available commands:") + (Config.MainConfig.ShowCommandsCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, commands.Length); + TextWriterRaw.WritePlain("Available commands:" + (showCount ? " [{0}]" : ""), commands.Length); // The built-in commands if (showGeneral) { - TextWriters.Write(CharManager.NewLine + Translate.DoTranslation("General commands:") + (Config.MainConfig.ShowCommandsCount & Config.MainConfig.ShowShellCommandsCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, commandList.Count); + TextWriterRaw.WritePlain(CharManager.NewLine + "General commands:" + (showCount ? " [{0}]" : ""), commandList.Count); if (commandList.Count == 0) - TextWriters.Write(" - " + Translate.DoTranslation("Shell commands not implemented!!!"), true, KernelColorType.Warning); + TextWriterRaw.WritePlain(" - No shell commands."); foreach (var cmd in commandList) { - if ((!cmd.Flags.HasFlag(CommandFlags.Strict) | cmd.Flags.HasFlag(CommandFlags.Strict) & UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) & (KernelEntry.Maintenance & !cmd.Flags.HasFlag(CommandFlags.NoMaintenance) | !KernelEntry.Maintenance)) - { - TextWriters.Write(" - {0}: ", false, KernelColorType.ListEntry, cmd.Command); - TextWriters.Write("{0}", true, KernelColorType.ListValue, cmd.GetTranslatedHelpEntry()); - } - } - } - - // The addon commands - if (showAddon) - { - TextWriters.Write(CharManager.NewLine + Translate.DoTranslation("Kernel addon commands:") + (Config.MainConfig.ShowCommandsCount & Config.MainConfig.ShowAddonCommandsCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, AddonCommandList.Count); - if (AddonCommandList.Count == 0) - TextWriters.Write(" - " + Translate.DoTranslation("No kernel addon commands."), true, KernelColorType.Warning); - foreach (var cmd in AddonCommandList) - { - if ((!cmd.Flags.HasFlag(CommandFlags.Strict) | cmd.Flags.HasFlag(CommandFlags.Strict) & UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) & (KernelEntry.Maintenance & !cmd.Flags.HasFlag(CommandFlags.NoMaintenance) | !KernelEntry.Maintenance)) - { - TextWriters.Write(" - {0}: ", false, KernelColorType.ListEntry, cmd.Command); - TextWriters.Write("{0}", true, KernelColorType.ListValue, cmd.GetTranslatedHelpEntry()); - } + TextWriterRaw.WritePlain(" - {0}: ", false, cmd.Command); + TextWriterRaw.WritePlain("{0}", cmd.HelpDefinition); } } - // The mod commands - if (showMod) + // The extra commands + if (showExtra) { - TextWriters.Write(CharManager.NewLine + Translate.DoTranslation("Mod commands:") + (Config.MainConfig.ShowCommandsCount & Config.MainConfig.ShowModCommandsCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, ModCommandList.Length); - if (ModCommandList.Length == 0) - TextWriters.Write(" - " + Translate.DoTranslation("No mod commands."), true, KernelColorType.Warning); - foreach (var cmd in ModCommandList) + TextWriterRaw.WritePlain(CharManager.NewLine + "Extra commands:" + (showCount ? " [{0}]" : ""), ExtraCommandList.Count); + if (ExtraCommandList.Count == 0) + TextWriterRaw.WritePlain(" - No extra commands."); + foreach (var cmd in ExtraCommandList) { - if ((!cmd.Flags.HasFlag(CommandFlags.Strict) | cmd.Flags.HasFlag(CommandFlags.Strict) & UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) & (KernelEntry.Maintenance & !cmd.Flags.HasFlag(CommandFlags.NoMaintenance) | !KernelEntry.Maintenance)) - { - TextWriters.Write(" - {0}: ", false, KernelColorType.ListEntry, cmd.Command); - TextWriters.Write("{0}", true, KernelColorType.ListValue, cmd.GetTranslatedHelpEntry()); - } + TextWriterRaw.WritePlain(" - {0}: ", false, cmd.Command); + TextWriterRaw.WritePlain("{0}", cmd.HelpDefinition); } } // The alias commands if (showAlias) { - TextWriters.Write(CharManager.NewLine + Translate.DoTranslation("Alias commands:") + (Config.MainConfig.ShowCommandsCount & Config.MainConfig.ShowShellAliasesCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, AliasedCommandList.Count); + TextWriterRaw.WritePlain(CharManager.NewLine + "Alias commands:" + (showCount ? " [{0}]" : ""), AliasedCommandList.Count); if (AliasedCommandList.Count == 0) - TextWriters.Write(" - " + Translate.DoTranslation("No alias commands."), true, KernelColorType.Warning); + TextWriterRaw.WritePlain(" - No alias commands."); foreach (var cmd in AliasedCommandList) { - if ((!cmd.Value.Flags.HasFlag(CommandFlags.Strict) | cmd.Value.Flags.HasFlag(CommandFlags.Strict) & UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) & (KernelEntry.Maintenance & !cmd.Value.Flags.HasFlag(CommandFlags.NoMaintenance) | !KernelEntry.Maintenance)) - { - TextWriters.Write(" - {0} -> {1}: ", false, KernelColorType.ListEntry, cmd.Key.Alias, cmd.Value.Command); - TextWriters.Write("{0}", true, KernelColorType.ListValue, cmd.Value.GetTranslatedHelpEntry()); - } + TextWriterRaw.WritePlain(" - {0} -> {1}: ", false, cmd.Key.Alias, cmd.Value.Command); + TextWriterRaw.WritePlain("{0}", cmd.Value.HelpDefinition); } } // The unified commands if (showUnified) { - TextWriters.Write(CharManager.NewLine + Translate.DoTranslation("Unified commands:") + (Config.MainConfig.ShowCommandsCount & Config.MainConfig.ShowUnifiedCommandsCount ? " [{0}]" : ""), true, KernelColorType.ListTitle, unifiedCommandList.Count); + TextWriterRaw.WritePlain(CharManager.NewLine + "Unified commands:" + (showCount ? " [{0}]" : ""), unifiedCommandList.Count); if (unifiedCommandList.Count == 0) - TextWriters.Write(" - " + Translate.DoTranslation("Unified commands not implemented!!!"), true, KernelColorType.Warning); + TextWriterRaw.WritePlain(" - No unified commands."); foreach (var cmd in unifiedCommandList) { - if ((!cmd.Flags.HasFlag(CommandFlags.Strict) | cmd.Flags.HasFlag(CommandFlags.Strict) & UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) & (KernelEntry.Maintenance & !cmd.Flags.HasFlag(CommandFlags.NoMaintenance) | !KernelEntry.Maintenance)) - { - TextWriters.Write(" - {0}: ", false, KernelColorType.ListEntry, cmd.Command); - TextWriters.Write("{0}", true, KernelColorType.ListValue, cmd.GetTranslatedHelpEntry()); - } + TextWriterRaw.WritePlain(" - {0}: ", false, cmd.Command); + TextWriterRaw.WritePlain("{0}", cmd.HelpDefinition); } } } @@ -138,21 +102,7 @@ internal static void ShowCommandListSimplified(string commandType) { // Get visible commands var commands = CommandManager.GetCommandNames(commandType); - List finalCommand = []; - foreach (string cmd in commands) - { - // Get the necessary flags - var command = CommandManager.GetCommand(cmd, commandType); - bool hasAdmin = UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator); - bool isStrict = command.Flags.HasFlag(CommandFlags.Strict); - bool isNoMaintenance = command.Flags.HasFlag(CommandFlags.NoMaintenance); - - // Now, populate the command list - if ((!isStrict | isStrict & hasAdmin) & - (KernelEntry.Maintenance & !isNoMaintenance | !KernelEntry.Maintenance)) - finalCommand.Add(cmd); - } - TextWriterColor.Write(string.Join(", ", finalCommand)); + TextWriterColor.Write(string.Join(", ", commands)); } internal static void ShowHelpUsage(string command, string commandType) @@ -160,11 +110,10 @@ internal static void ShowHelpUsage(string command, string commandType) // Determine command type var CommandList = ShellManager.GetShellInfo(commandType).Commands; - // Add every command from each mod, addon, and alias - var ModCommandList = ModManager.ListModCommands(commandType); - var AddonCommandList = ShellManager.GetShellInfo(commandType).addonCommands; + // Add every command from each mod, extra, and alias + var ExtraCommandList = ShellManager.GetShellInfo(commandType).extraCommands; var unifiedCommandList = ShellManager.unifiedCommandDict; - var AliasedCommandList = AliasManager.GetEntireAliasListFromType(commandType) + var AliasedCommandList = AliasManager.GetAliasListFromType(commandType) .ToDictionary((ai) => ai, (ai) => ai.TargetCommand); var totalCommandList = CommandManager.GetCommands(commandType); @@ -172,34 +121,31 @@ internal static void ShowHelpUsage(string command, string commandType) if (!string.IsNullOrWhiteSpace(command) && (CommandList.Any((ci) => ci.Command == command) || AliasedCommandList.Any((info) => info.Key.Alias == command) || - ModCommandList.Any((ci) => ci.Command == command) || - AddonCommandList.Any((ci) => ci.Command == command) || + ExtraCommandList.Any((ci) => ci.Command == command) || unifiedCommandList.Any((ci) => ci.Command == command))) { // Found! - bool IsMod = ModCommandList.Any((ci) => ci.Command == command); bool IsAlias = AliasedCommandList.Any((info) => info.Key.Alias == command); - bool IsAddon = AddonCommandList.Any((ci) => ci.Command == command); + bool IsExtra = ExtraCommandList.Any((ci) => ci.Command == command); bool IsUnified = unifiedCommandList.Any((ci) => ci.Command == command); var FinalCommandList = - IsMod ? ModCommandList.ToDictionary((info) => info.Command, (info) => info) : - IsAddon ? AddonCommandList.ToDictionary((info) => info.Command, (info) => info) : + IsExtra ? ExtraCommandList.ToDictionary((info) => info.Command, (info) => info) : IsAlias ? AliasedCommandList.ToDictionary((info) => info.Key.Command, (info) => info.Key.TargetCommand) : IsUnified ? unifiedCommandList.ToDictionary((info) => info.Command, (info) => info) : CommandList.ToDictionary((info) => info.Command, (info) => info); string FinalCommand = - IsMod || IsAddon || IsUnified ? command : + IsExtra || IsUnified ? command : IsAlias ? AliasManager.GetAlias(command, commandType).Command : command; - string HelpDefinition = FinalCommandList[FinalCommand].GetTranslatedHelpEntry(); + string HelpDefinition = FinalCommandList[FinalCommand].HelpDefinition; // Write the description now if (string.IsNullOrEmpty(HelpDefinition)) - HelpDefinition = Translate.DoTranslation("Command defined by ") + command; - TextWriters.Write(Translate.DoTranslation("Command:"), false, KernelColorType.ListEntry); - TextWriters.Write($" {FinalCommand}", KernelColorType.ListValue); - TextWriters.Write(Translate.DoTranslation("Description:"), false, KernelColorType.ListEntry); - TextWriters.Write($" {HelpDefinition}", KernelColorType.ListValue); + HelpDefinition = "Command defined by " + command; + TextWriterRaw.WritePlain("Command:", false); + TextWriterRaw.WritePlain($" {FinalCommand}"); + TextWriterRaw.WritePlain("Description:", false); + TextWriterRaw.WritePlain($" {HelpDefinition}"); // Iterate through command argument information instances var argumentInfos = FinalCommandList[FinalCommand].CommandArgumentInfo ?? []; @@ -218,35 +164,32 @@ internal static void ShowHelpUsage(string command, string commandType) } // Print usage information - TextWriters.Write(Translate.DoTranslation("Usage:"), false, KernelColorType.ListEntry); - TextWriters.Write($" {FinalCommand} {renderedUsage}", KernelColorType.ListValue); + TextWriterRaw.WritePlain("Usage:", false); + TextWriterRaw.WritePlain($" {FinalCommand} {renderedUsage}"); // If we have arguments, print their descriptions if (Arguments.Length != 0) { - TextWriters.Write(Translate.DoTranslation("This command has the below arguments that change how it works:"), KernelColorType.NeutralText); + TextWriterRaw.WritePlain("This command has the below arguments that change how it works:"); foreach (var argument in Arguments) { - string argumentDescUnlocalized = argument.Options.ArgumentDescription; - if (string.IsNullOrWhiteSpace(argument.Options.ArgumentDescription)) - argumentDescUnlocalized = /* Localizable */ "Unspecified argument description"; string argumentName = argument.ArgumentExpression; - string argumentDesc = Translate.DoTranslation(argumentDescUnlocalized); - TextWriters.Write($" {argumentName}: ", false, KernelColorType.ListEntry); - TextWriters.Write(argumentDesc, KernelColorType.ListValue); + string argumentDesc = argument.Options.ArgumentDescription; + TextWriterRaw.WritePlain($" {argumentName}: ", false); + TextWriterRaw.WritePlain(argumentDesc); } } // If we have switches, print their descriptions if (Switches.Length != 0) { - TextWriters.Write(Translate.DoTranslation("This command has the below switches that change how it works:"), KernelColorType.NeutralText); + TextWriterRaw.WritePlain("This command has the below switches that change how it works:"); foreach (var Switch in Switches) { string switchName = Switch.SwitchName; - string switchDesc = Switch.GetTranslatedHelpEntry(); - TextWriters.Write($" -{switchName}: ", false, KernelColorType.ListEntry); - TextWriters.Write(switchDesc, KernelColorType.ListValue); + string switchDesc = Switch.HelpDefinition; + TextWriterRaw.WritePlain($" -{switchName}: ", false); + TextWriterRaw.WritePlain(switchDesc); } } } @@ -255,7 +198,7 @@ internal static void ShowHelpUsage(string command, string commandType) FinalCommandList[FinalCommand].CommandBase?.HelpHelper(); } else - TextWriters.Write(Translate.DoTranslation("No help for command \"{0}\"."), true, KernelColorType.Error, command); + TextWriterRaw.WritePlain("No help for command \"{0}\".", command); } } } diff --git a/Terminaux/Shell/Prompts/PromptPresetBase.cs b/Terminaux/Shell/Prompts/PromptPresetBase.cs index f80fdad81..080ab7fa4 100644 --- a/Terminaux/Shell/Prompts/PromptPresetBase.cs +++ b/Terminaux/Shell/Prompts/PromptPresetBase.cs @@ -17,8 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Kernel.Debugging; - namespace Terminaux.Shell.Prompts { /// @@ -49,38 +47,26 @@ public class PromptPresetBase : IPromptPreset /// public virtual string PresetShellType { get; } = "Shell"; - internal virtual string PresetPromptBuilder() - { - DebugWriter.WriteDebug(DebugLevel.W, "Tried to call prompt builder on base."); - return "> "; - } + internal virtual string PresetPromptBuilder() => + "> "; string IPromptPreset.PresetPromptBuilder() => PresetPromptBuilder(); - internal virtual string PresetPromptCompletionBuilder() - { - DebugWriter.WriteDebug(DebugLevel.W, "Tried to call prompt builder on base."); - return "[+] > "; - } + internal virtual string PresetPromptCompletionBuilder() => + "[+] > "; string IPromptPreset.PresetPromptCompletionBuilder() => PresetPromptCompletionBuilder(); - internal virtual string PresetPromptBuilderShowcase() - { - DebugWriter.WriteDebug(DebugLevel.W, "Tried to call prompt builder on base."); - return "> "; - } + internal virtual string PresetPromptBuilderShowcase() => + "> "; string IPromptPreset.PresetPromptBuilderShowcase() => PresetPromptBuilderShowcase(); - internal virtual string PresetPromptCompletionBuilderShowcase() - { - DebugWriter.WriteDebug(DebugLevel.W, "Tried to call prompt builder on base."); - return "[+] > "; - } + internal virtual string PresetPromptCompletionBuilderShowcase() => + "[+] > "; string IPromptPreset.PresetPromptCompletionBuilderShowcase() => PresetPromptCompletionBuilderShowcase(); diff --git a/Terminaux/Shell/Prompts/PromptPresetManager.cs b/Terminaux/Shell/Prompts/PromptPresetManager.cs index 895a67f18..2b42088c0 100644 --- a/Terminaux/Shell/Prompts/PromptPresetManager.cs +++ b/Terminaux/Shell/Prompts/PromptPresetManager.cs @@ -18,16 +18,12 @@ // using System.Collections.Generic; -using System.Data; using System.Linq; -using Nitrocid.ConsoleBase.Colors; using Terminaux.Inputs.Styles.Selection; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; using Textify.General; using Terminaux.Shell.Shells; +using Terminaux.Base; +using Terminaux.Writer.ConsoleWriters; namespace Terminaux.Shell.Prompts { @@ -36,33 +32,12 @@ namespace Terminaux.Shell.Prompts /// public static class PromptPresetManager { - // Current presets internal static Dictionary CurrentPresets = new() { { "Shell", "Default" }, - { "FTPShell", "Default" }, - { "MailShell", "Default" }, - { "SFTPShell", "Default" }, - { "TextShell", "Default" }, - { "RSSShell", "Default" }, - { "JsonShell", "Default" }, - { "HTTPShell", "Default" }, - { "HexShell", "Default" }, - { "AdminShell", "Default" }, - { "SqlShell", "Default" }, - { "DebugShell", "Default" }, }; - /// - /// Sets the shell preset - /// - /// The preset name - /// Type of shell - /// If the preset is not found, throw an exception. Otherwise, use the default preset. - public static void SetPreset(string PresetName, ShellType ShellType, bool ThrowOnNotFound = true) => - SetPreset(PresetName, ShellManager.GetShellTypeName(ShellType), ThrowOnNotFound); - /// /// Sets the shell preset /// @@ -76,29 +51,13 @@ public static void SetPreset(string PresetName, string ShellType, bool ThrowOnNo // Check to see if we have the preset if (Presets.ContainsKey(PresetName) || CustomPresets.ContainsKey(PresetName)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Preset {0} for {1} exists. Setting dryly...", PresetName, ShellType.ToString()); CurrentPresets[ShellType] = PresetName; - } else if (ThrowOnNotFound) - { - DebugWriter.WriteDebug(DebugLevel.I, "Preset {0} for {1} doesn't exist. Throwing...", PresetName, ShellType.ToString()); - throw new KernelException(KernelExceptionType.NoSuchShellPreset, Translate.DoTranslation("The specified preset {0} is not found."), PresetName); - } + throw new TerminauxException("The specified preset {0} is not found.", PresetName); else - { - DebugWriter.WriteDebug(DebugLevel.W, "Preset {0} for {1} doesn't exist. Setting dryly to default...", PresetName, ShellType.ToString()); CurrentPresets[ShellType] = "Default"; - } } - /// - /// Gets the current preset base from the shell - /// - /// The shell type - public static PromptPresetBase GetCurrentPresetBaseFromShell(ShellType ShellType) => - GetCurrentPresetBaseFromShell(ShellManager.GetShellTypeName(ShellType)); - /// /// Gets the current preset base from the shell /// @@ -106,13 +65,6 @@ public static PromptPresetBase GetCurrentPresetBaseFromShell(ShellType ShellType public static PromptPresetBase GetCurrentPresetBaseFromShell(string ShellType) => ShellManager.GetShellInfo(ShellType).CurrentPreset; - /// - /// Gets the predefined presets from the shell - /// - /// The shell type - public static Dictionary GetPresetsFromShell(ShellType ShellType) => - GetPresetsFromShell(ShellManager.GetShellTypeName(ShellType)); - /// /// Gets the predefined presets from the shell /// @@ -121,26 +73,12 @@ public static Dictionary GetPresetsFromShell(string Sh ShellManager.GetShellInfo(ShellType).ShellPresets; /// - /// Gets the custom presets (defined by mods) from the shell - /// - /// The shell type - public static Dictionary GetCustomPresetsFromShell(ShellType ShellType) => - GetCustomPresetsFromShell(ShellManager.GetShellTypeName(ShellType)); - - /// - /// Gets the custom presets (defined by mods) from the shell + /// Gets the custom presets from the shell /// /// The shell type public static Dictionary GetCustomPresetsFromShell(string ShellType) => ShellManager.GetShellInfo(ShellType).CustomShellPresets; - /// - /// Gets all presets from the shell - /// - /// The shell type - public static Dictionary GetAllPresetsFromShell(ShellType ShellType) => - GetAllPresetsFromShell(ShellManager.GetShellTypeName(ShellType)); - /// /// Gets all presets from the shell /// @@ -155,13 +93,6 @@ public static Dictionary GetAllPresetsFromShell(string return presets; } - /// - /// Writes the shell prompt - /// - /// Shell type - public static void WriteShellPrompt(ShellType ShellType) => - WriteShellPrompt(ShellManager.GetShellTypeName(ShellType)); - /// /// Writes the shell prompt /// @@ -169,16 +100,9 @@ public static void WriteShellPrompt(ShellType ShellType) => public static void WriteShellPrompt(string ShellType) { var CurrentPresetBase = GetCurrentPresetBaseFromShell(ShellType); - TextWriters.Write(CurrentPresetBase.PresetPrompt, false, KernelColorType.Input); + TextWriterRaw.WritePlain(CurrentPresetBase.PresetPrompt, false); } - /// - /// Writes the shell completion prompt - /// - /// Shell type - public static void WriteShellCompletionPrompt(ShellType ShellType) => - WriteShellCompletionPrompt(ShellManager.GetShellTypeName(ShellType)); - /// /// Writes the shell completion prompt /// @@ -186,7 +110,7 @@ public static void WriteShellCompletionPrompt(ShellType ShellType) => public static void WriteShellCompletionPrompt(string ShellType) { var CurrentPresetBase = GetCurrentPresetBaseFromShell(ShellType); - TextWriters.Write(CurrentPresetBase.PresetPromptCompletion, false, KernelColorType.Input); + TextWriterRaw.WritePlain(CurrentPresetBase.PresetPromptCompletion, false); } /// @@ -195,13 +119,6 @@ public static void WriteShellCompletionPrompt(string ShellType) public static string PromptForPresets() => PromptForPresets(ShellManager.CurrentShellType); - /// - /// Prompts a user to select the preset - /// - /// Sets preset in shell type - public static string PromptForPresets(ShellType shellType) => - PromptForPresets(shellType.ToString()); - /// /// Prompts a user to select the preset /// @@ -216,7 +133,7 @@ public static string PromptForPresets(string shellType) // Now, prompt the user var PresetNames = Presets.Select((kvp) => (kvp.Key, kvp.Value.PresetPromptShowcase)).ToArray(); - int SelectedPreset = SelectionStyle.PromptSelection(TextTools.FormatString(Translate.DoTranslation("Select preset for {0}:"), shellType), PresetNames); + int SelectedPreset = SelectionStyle.PromptSelection(TextTools.FormatString("Select preset for {0}:", shellType), PresetNames); if (SelectedPreset == -1) return "Default"; string SelectedPresetName = Presets.Keys.ElementAt(SelectedPreset - 1); diff --git a/Terminaux/Shell/Scripting/Conditions/BaseCondition.cs b/Terminaux/Shell/Scripting/Conditions/BaseCondition.cs deleted file mode 100644 index faee89fc2..000000000 --- a/Terminaux/Shell/Scripting/Conditions/BaseCondition.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Kernel.Debugging; - -namespace Terminaux.Shell.Scripting.Conditions -{ - /// - /// Base UESH scripting condition class - /// - public abstract class BaseCondition : ICondition - { - - /// - /// Condition name - /// - public virtual string ConditionName => "none"; - - /// - /// Condition position (starts from 1) - /// - public virtual int ConditionPosition { get; } = 1; - - /// - /// Condition required argument numbers (starts from 1) - /// - public virtual int ConditionRequiredArguments { get; } = 1; - - /// - /// Is the condition satisfied? - /// - /// The first UESH variable (can be unsanitized; can start without $) - /// The second UESH variable (can be unsanitized; can start without $) - /// True if satisfied; otherwise, false - public virtual bool IsConditionSatisfied(string FirstVariable, string SecondVariable) - { - DebugWriter.WriteDebug(DebugLevel.I, "Doing nothing because the condition is undefined. Returning true..."); - return true; - } - - /// - /// Is the condition satisfied? - /// - /// Array of UESH variables (can be unsanitized; can start without $) - /// True if satisfied; otherwise, false - public bool IsConditionSatisfied(string[] Variables) - { - DebugWriter.WriteDebug(DebugLevel.I, "Doing nothing because the condition is undefined. Returning true..."); - return true; - } - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/ICondition.cs b/Terminaux/Shell/Scripting/Conditions/ICondition.cs deleted file mode 100644 index 973d170c3..000000000 --- a/Terminaux/Shell/Scripting/Conditions/ICondition.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Scripting.Conditions -{ - /// - /// UESH scripting condition interface - /// - public interface ICondition - { - - /// - /// Specifies the condition name - /// - string ConditionName { get; } - /// - /// Specifies where the condition should be located. Beware that it starts from 1. - /// - int ConditionPosition { get; } - /// - /// How many arguments are required (counting the condition itself)? Beware that it starts from 1. - /// - int ConditionRequiredArguments { get; } - /// - /// Checks whether the condition is satisfied - /// - bool IsConditionSatisfied(string FirstVariable, string SecondVariable); - /// - /// Checks whether the condition is satisfiedfor more than two variables - /// - bool IsConditionSatisfied(string[] Variables); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/Contains.cs b/Terminaux/Shell/Scripting/Conditions/Types/Contains.cs deleted file mode 100644 index 1e2dedb45..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/Contains.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition that checks to see if it contains an expression - /// - public class ContainsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "has"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableContains(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/DirectoryExists.cs b/Terminaux/Shell/Scripting/Conditions/Types/DirectoryExists.cs deleted file mode 100644 index c1248217e..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/DirectoryExists.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check to see if the directory exists - /// - public class DirectoryExistsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "direx"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableDirectoryExists(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/DirectoryNotExists.cs b/Terminaux/Shell/Scripting/Conditions/Types/DirectoryNotExists.cs deleted file mode 100644 index 208b70437..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/DirectoryNotExists.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check to see if the directory doesn't exist - /// - public class DirectoryNotExistsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "dirnex"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableDirectoryDoesNotExist(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/Equals.cs b/Terminaux/Shell/Scripting/Conditions/Types/Equals.cs deleted file mode 100644 index 87e9f2806..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/Equals.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if the two UESH variables are equal - /// - public class EqualsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "eq"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableEqual(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/FileExists.cs b/Terminaux/Shell/Scripting/Conditions/Types/FileExists.cs deleted file mode 100644 index 0627882fe..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/FileExists.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if the value of the UESH variable is a file path and exists - /// - public class FileExistsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "fileex"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableFileExists(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/FileHashMatch.cs b/Terminaux/Shell/Scripting/Conditions/Types/FileHashMatch.cs deleted file mode 100644 index 1a56ddcad..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/FileHashMatch.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a file specified from a UESH variable matches its hash specified on the second - /// - public class FileHashMatchCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "fsane"; - - /// - public override int ConditionPosition { get; } = 3; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableFileHashMatch(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/FileHashMismatch.cs b/Terminaux/Shell/Scripting/Conditions/Types/FileHashMismatch.cs deleted file mode 100644 index e83e4cfde..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/FileHashMismatch.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a file specified from a UESH variable doesn't match its hash specified on the second - /// - public class FileHashMismatchCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "finsane"; - - /// - public override int ConditionPosition { get; } = 3; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableFileHashNoMatch(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/FileNotExists.cs b/Terminaux/Shell/Scripting/Conditions/Types/FileNotExists.cs deleted file mode 100644 index ea27d44fa..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/FileNotExists.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if the value of the UESH variable is a file path and doesn't exist - /// - public class FileNotExistsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "filenex"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableFileDoesNotExist(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/GreaterThan.cs b/Terminaux/Shell/Scripting/Conditions/Types/GreaterThan.cs deleted file mode 100644 index fd0f3d016..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/GreaterThan.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if one of the two UESH variables is greater than the other - /// - public class GreaterThanCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "gre"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableGreaterThan(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/GreaterThanOrEqual.cs b/Terminaux/Shell/Scripting/Conditions/Types/GreaterThanOrEqual.cs deleted file mode 100644 index ef1447180..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/GreaterThanOrEqual.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if one of the two UESH variables is greater than the other or equal to each other - /// - public class GreaterThanOrEqualCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "greoreq"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableGreaterThanOrEqual(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/HashesMatch.cs b/Terminaux/Shell/Scripting/Conditions/Types/HashesMatch.cs deleted file mode 100644 index 4bcd2b179..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/HashesMatch.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable matches its hash specified on the second - /// - public class HashesMatchCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "sane"; - - /// - public override int ConditionPosition { get; } = 3; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableHashMatch(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/HashesMismatch.cs b/Terminaux/Shell/Scripting/Conditions/Types/HashesMismatch.cs deleted file mode 100644 index d284d1b3d..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/HashesMismatch.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable doesn't match its hash specified on the second - /// - public class HashesMismatchCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "insane"; - - /// - public override int ConditionPosition { get; } = 3; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableHashNoMatch(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/InvalidFileName.cs b/Terminaux/Shell/Scripting/Conditions/Types/InvalidFileName.cs deleted file mode 100644 index cab68476e..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/InvalidFileName.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check if the filename is not valid - /// - public class InvalidFileNameCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "isnotfname"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableInvalidFileName(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/InvalidPath.cs b/Terminaux/Shell/Scripting/Conditions/Types/InvalidPath.cs deleted file mode 100644 index 2154cef20..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/InvalidPath.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check if the path is not valid - /// - public class InvalidPathCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "isnotpath"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableInvalidPath(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/Is.cs b/Terminaux/Shell/Scripting/Conditions/Types/Is.cs deleted file mode 100644 index f50e78f60..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/Is.cs +++ /dev/null @@ -1,93 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using Nitrocid.Misc.Text.Probers.Regexp; -using System; -using System.Collections.Generic; -using Terminaux.Shell.Scripting.Conditions; -using Textify.General; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable is of the correct type - /// - public class IsCondition : BaseCondition, ICondition - { - internal static Dictionary> DataTypes = new() - { - { "null", (value) => value is null }, - { "string", (value) => value is not null }, - { "fullstring", (value) => value is not null && !string.IsNullOrEmpty(value) }, - { "numeric", (value) => value is not null && value.IsStringNumeric() }, - { "byte", (value) => value is not null && sbyte.TryParse(value, out _) }, - { "i8", (value) => value is not null && sbyte.TryParse(value, out _) }, - { "ubyte", (value) => value is not null && byte.TryParse(value, out _) }, - { "u8", (value) => value is not null && byte.TryParse(value, out _) }, - { "int16", (value) => value is not null && short.TryParse(value, out _) }, - { "short", (value) => value is not null && short.TryParse(value, out _) }, - { "i16", (value) => value is not null && short.TryParse(value, out _) }, - { "int32", (value) => value is not null && int.TryParse(value, out _) }, - { "integer", (value) => value is not null && int.TryParse(value, out _) }, - { "i32", (value) => value is not null && int.TryParse(value, out _) }, - { "int64", (value) => value is not null && long.TryParse(value, out _) }, - { "long", (value) => value is not null && long.TryParse(value, out _) }, - { "i64", (value) => value is not null && long.TryParse(value, out _) }, - { "uint16", (value) => value is not null && ushort.TryParse(value, out _) }, - { "ushort", (value) => value is not null && ushort.TryParse(value, out _) }, - { "u16", (value) => value is not null && ushort.TryParse(value, out _) }, - { "uint32", (value) => value is not null && uint.TryParse(value, out _) }, - { "uinteger", (value) => value is not null && uint.TryParse(value, out _) }, - { "u32", (value) => value is not null && uint.TryParse(value, out _) }, - { "uint64", (value) => value is not null && ulong.TryParse(value, out _) }, - { "ulong", (value) => value is not null && ulong.TryParse(value, out _) }, - { "u64", (value) => value is not null && ulong.TryParse(value, out _) }, - { "decimal", (value) => value is not null && decimal.TryParse(value, out _) }, - { "float", (value) => value is not null && float.TryParse(value, out _) }, - { "f32", (value) => value is not null && float.TryParse(value, out _) }, - { "double", (value) => value is not null && double.TryParse(value, out _) }, - { "f64", (value) => value is not null && double.TryParse(value, out _) }, - { "bool", (value) => value is not null && bool.TryParse(value, out _) }, - { "regex", (value) => value is not null && RegexpTools.IsValidRegex(value) }, - }; - - /// - public override string ConditionName => "is"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) - { - // SecondVariable is actually a data type needed for parsing. - if (!DataTypes.TryGetValue(SecondVariable, out Func? dataFunc)) - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Data type {0} specified is invalid."), SecondVariable); - - // Get the action needed to get the comparer and test the condition defined above - return dataFunc(FirstVariable); - } - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/IsNot.cs b/Terminaux/Shell/Scripting/Conditions/Types/IsNot.cs deleted file mode 100644 index 921990c7a..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/IsNot.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using System; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable is not of the correct type - /// - public class IsNotCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "isnot"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) - { - // SecondVariable is actually a data type needed for parsing. - if (!IsCondition.DataTypes.TryGetValue(SecondVariable, out Func? dataFunc)) - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Data type {0} specified is invalid."), SecondVariable); - - // Get the action needed to get the comparer and test the condition defined above - return !dataFunc(FirstVariable); - } - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/IsNotPlat.cs b/Terminaux/Shell/Scripting/Conditions/Types/IsNotPlat.cs deleted file mode 100644 index 6eebf4af2..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/IsNotPlat.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using System; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable is not of the correct type - /// - public class IsNotPlatCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "isnotplat"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) - { - // FirstVariable is actually a platform needed for parsing. - if (!IsPlatCondition.Platforms.TryGetValue(FirstVariable, out Func? platFunc)) - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Platform {0} specified is invalid."), FirstVariable); - - // Get the action needed to get the comparer and test the condition defined above - return !platFunc(); - } - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/IsPlat.cs b/Terminaux/Shell/Scripting/Conditions/Types/IsPlat.cs deleted file mode 100644 index 9796cd464..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/IsPlat.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Kernel; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using System; -using System.Collections.Generic; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable is of the correct type - /// - public class IsPlatCondition : BaseCondition, ICondition - { - internal static Dictionary> Platforms = new() - { - { "win", KernelPlatform.IsOnWindows }, - { "mac", KernelPlatform.IsOnMacOS }, - { "unix", KernelPlatform.IsOnUnix }, - { "android", KernelPlatform.IsOnAndroid }, - }; - - /// - public override string ConditionName => "isplat"; - - /// - public override int ConditionPosition { get; } = 1; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) - { - // FirstVariable is actually a platform needed for parsing. - if (!Platforms.TryGetValue(FirstVariable, out Func? platFunc)) - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Platform {0} specified is invalid."), FirstVariable); - - // Get the action needed to get the comparer and test the condition defined above - return platFunc(); - } - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/LessThan.cs b/Terminaux/Shell/Scripting/Conditions/Types/LessThan.cs deleted file mode 100644 index c42930056..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/LessThan.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if one of the two UESH variables is less than the other - /// - public class LessThanCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "les"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableLessThan(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/LessThanOrEqual.cs b/Terminaux/Shell/Scripting/Conditions/Types/LessThanOrEqual.cs deleted file mode 100644 index c196232f3..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/LessThanOrEqual.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if one of the two UESH variables is less than the other or equal to each other - /// - public class LessThanOrEqualCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "lesoreq"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableLessThanOrEqual(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/None.cs b/Terminaux/Shell/Scripting/Conditions/Types/None.cs deleted file mode 100644 index a17fb10f7..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/None.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// This condition always returns true. - /// - public class NoneCondition : BaseCondition, ICondition { } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/NotContains.cs b/Terminaux/Shell/Scripting/Conditions/Types/NotContains.cs deleted file mode 100644 index aa7922762..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/NotContains.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if a UESH variable doesn't contain an expression - /// - public class NotContainsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "hasno"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableNotContains(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/NotEquals.cs b/Terminaux/Shell/Scripting/Conditions/Types/NotEquals.cs deleted file mode 100644 index f47948499..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/NotEquals.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Checks to see if the two UESH variables are different - /// - public class NotEqualsCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "neq"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 3; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableNotEqual(FirstVariable, SecondVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/ValidFileName.cs b/Terminaux/Shell/Scripting/Conditions/Types/ValidFileName.cs deleted file mode 100644 index 9ccdfd6e9..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/ValidFileName.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check if the filename is valid - /// - public class ValidFileNameCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "isfname"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableValidFileName(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/Types/ValidPath.cs b/Terminaux/Shell/Scripting/Conditions/Types/ValidPath.cs deleted file mode 100644 index 5994d2156..000000000 --- a/Terminaux/Shell/Scripting/Conditions/Types/ValidPath.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -// -// Nitrocid KS Copyright (C) 2018-2024 Aptivi -// -// This file is part of Nitrocid KS -// -// Nitrocid KS is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Nitrocid KS is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Scripting.Conditions.Types -{ - /// - /// Condition to check if the path is valid - /// - public class ValidPathCondition : BaseCondition, ICondition - { - - /// - public override string ConditionName => "ispath"; - - /// - public override int ConditionPosition { get; } = 2; - - /// - public override int ConditionRequiredArguments { get; } = 2; - - /// - public override bool IsConditionSatisfied(string FirstVariable, string SecondVariable) => UESHOperators.UESHVariableValidPath(FirstVariable); - - } -} diff --git a/Terminaux/Shell/Scripting/Conditions/UESHConditional.cs b/Terminaux/Shell/Scripting/Conditions/UESHConditional.cs deleted file mode 100644 index 09b724283..000000000 --- a/Terminaux/Shell/Scripting/Conditions/UESHConditional.cs +++ /dev/null @@ -1,230 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.Collections.Generic; -using System.Linq; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Languages; -using Nitrocid.Shell.ShellBase.Scripting.Conditions.Types; -using Textify.General; - -namespace Terminaux.Shell.Scripting.Conditions -{ - /// - /// UESH condition manager - /// - public static class UESHConditional - { - - private readonly static Dictionary Conditions = new() - { - { "eq", new EqualsCondition() }, - { "neq", new NotEqualsCondition() }, - { "les", new LessThanCondition() }, - { "lesoreq", new LessThanOrEqualCondition() }, - { "gre", new GreaterThanCondition() }, - { "greoreq", new GreaterThanOrEqualCondition() }, - { "fileex", new FileExistsCondition() }, - { "filenex", new FileNotExistsCondition() }, - { "direx", new DirectoryExistsCondition() }, - { "dirnex", new DirectoryNotExistsCondition() }, - { "has", new ContainsCondition() }, - { "hasno", new NotContainsCondition() }, - { "ispath", new ValidPathCondition() }, - { "isnotpath", new InvalidPathCondition() }, - { "isfname", new ValidFileNameCondition() }, - { "isnotfname", new InvalidFileNameCondition() }, - { "sane", new HashesMatchCondition() }, - { "insane", new HashesMismatchCondition() }, - { "fsane", new FileHashMatchCondition() }, - { "finsane", new FileHashMismatchCondition() }, - { "is", new IsCondition() }, - { "isnot", new IsNotCondition() }, - { "isplat", new IsPlatCondition() }, - { "isnotplat", new IsNotPlatCondition() }, - { "none", new NoneCondition() } - }; - - private readonly static Dictionary CustomConditions = []; - - /// - /// The available condition names - /// - public static Dictionary AvailableConditions => - Conditions.Union(CustomConditions).ToDictionary((kvp) => kvp.Key, (kvp) => kvp.Value); - - /// - /// Checks if the UESH condition was satisfied - /// - /// The UESH condition to satisfy - public static bool ConditionSatisfied(string ConditionToSatisfy) - { - if (!string.IsNullOrWhiteSpace(ConditionToSatisfy)) - { - bool Satisfied; - - // First, check for the existence of one of the conditional words - DebugWriter.WriteDebug(DebugLevel.I, "Checking expression {0} for condition", ConditionToSatisfy); - var EnclosedWords = ConditionToSatisfy.SplitEncloseDoubleQuotes(); - var ConditionFound = false; - string ConditionType = "none"; - var ConditionBase = AvailableConditions[ConditionType]; - foreach (string Condition in AvailableConditions.Keys) - { - if (EnclosedWords.Contains(Condition)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Condition found in the expression string. It was {0}", Condition); - ConditionFound = true; - ConditionType = Condition; - ConditionBase = AvailableConditions[ConditionType]; - } - } - if (!ConditionFound) - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("The condition was not found in the expression.")); - - // Check the expression for argument numbers and middle condition - int RequiredArguments = ConditionBase.ConditionRequiredArguments; - int ConditionPosition = ConditionBase.ConditionPosition; - if (EnclosedWords.Length < RequiredArguments) - { - DebugWriter.WriteDebug(DebugLevel.E, "Argument count {0} is less than the required arguments {1}", EnclosedWords.Length, RequiredArguments); - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Condition {0} requires {1} arguments. Got {2}."), ConditionType, RequiredArguments, EnclosedWords.Length); - } - if (!AvailableConditions.ContainsKey(EnclosedWords[ConditionPosition - 1])) - { - DebugWriter.WriteDebug(DebugLevel.E, "Condition should be in position {0}, but {1} is not a condition.", ConditionPosition, EnclosedWords[ConditionPosition - 1]); - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("The condition needs to be placed in the end.")); - } - - // Execute the conditions - try - { - switch (RequiredArguments) - { - case 1: - { - Satisfied = ConditionBase.IsConditionSatisfied("", ""); - break; - } - case 2: - { - string Variable = ""; - switch (ConditionPosition) - { - case 1: - { - // Expression can be " ". Since there is no middle here, assume first. - Variable = EnclosedWords[1]; - break; - } - case 2: - { - // Expression can be " " - Variable = EnclosedWords[0]; - break; - } - } - Satisfied = ConditionBase.IsConditionSatisfied(Variable, ""); - break; - } - case 3: - { - string FirstVariable = ""; - string SecondVariable = ""; - switch (ConditionPosition) - { - case 1: - { - // Expression can be " " - FirstVariable = EnclosedWords[1]; - SecondVariable = EnclosedWords[2]; - break; - } - case 2: - { - // Expression can be " " - FirstVariable = EnclosedWords[0]; - SecondVariable = EnclosedWords[2]; - break; - } - case 3: - { - // Expression can be " " - FirstVariable = EnclosedWords[0]; - SecondVariable = EnclosedWords[1]; - break; - } - } - Satisfied = ConditionBase.IsConditionSatisfied(FirstVariable, SecondVariable); - break; - } - - default: - { - var Variables = EnclosedWords.SkipWhile(str => str == EnclosedWords[ConditionPosition - 1]).ToArray(); - Satisfied = ConditionBase.IsConditionSatisfied(Variables); - break; - } - } - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Syntax error in {0}: {1}", ConditionToSatisfy, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - throw new KernelException(KernelExceptionType.UESHConditionParse, Translate.DoTranslation("Error parsing expression due to syntax error.") + " {0}: {1}", ex, ConditionToSatisfy, ex.Message); - } - } - return false; - } - - /// - /// Registers a custom condition - /// - /// Condition name to register. Must be short and not contain whitespace - /// Condition class containing information about the condition - public static void RegisterCondition(string name, BaseCondition condition) - { - if (Conditions.ContainsKey(name) || CustomConditions.ContainsKey(name)) - throw new KernelException(KernelExceptionType.UESHConditional, Translate.DoTranslation("Can't register a condition that already exists.")); - if (condition is null) - throw new KernelException(KernelExceptionType.UESHConditional, Translate.DoTranslation("Can't register an empty condition.")); - - // Add a custom condition - CustomConditions.Add(name, condition); - } - - /// - /// Unregisters a custom condition - /// - /// Condition name to unregister. Must be short and not contain whitespace - public static void UnregisterCondition(string name) - { - if (!CustomConditions.ContainsKey(name)) - throw new KernelException(KernelExceptionType.UESHConditional, Translate.DoTranslation("Can't unregister a condition that doesn't exist.")); - - // Add a custom condition - CustomConditions.Remove(name); - } - - } -} diff --git a/Terminaux/Shell/Scripting/UESHOperators.cs b/Terminaux/Shell/Scripting/UESHOperators.cs deleted file mode 100644 index 8a2bcc00f..000000000 --- a/Terminaux/Shell/Scripting/UESHOperators.cs +++ /dev/null @@ -1,397 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.Drivers.Encryption; -using Nitrocid.Files.Operations.Querying; -using Nitrocid.Kernel.Debugging; - -namespace Terminaux.Shell.Scripting -{ - /// - /// UESH operator code functions - /// - public static class UESHOperators - { - - /// - /// Checks to see if the two UESH variables are equal - /// - /// The first $variable - /// The second $variable - /// True if the two UESH variables are equal. False if otherwise. - public static bool UESHVariableEqual(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for equality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = FirstVarValue == SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the two UESH variables are different - /// - /// The first $variable - /// The second $variable - /// True if the two UESH variables are different. False if otherwise. - public static bool UESHVariableNotEqual(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for inequality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = FirstVarValue != SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if one of the two UESH variables is less than the other - /// - /// The first $variable - /// The second $variable - /// True if the one of the two UESH variables is less than the other. False if otherwise. - public static bool UESHVariableLessThan(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for inequality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - long FirstVarInt = long.Parse(FirstVarValue); - long SecondVarInt = long.Parse(SecondVarValue); - Satisfied = FirstVarInt < SecondVarInt; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if one of the two UESH variables is greater than the other - /// - /// The first $variable - /// The second $variable - /// True if the one of the two UESH variables is greater than the other. False if otherwise. - public static bool UESHVariableGreaterThan(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for inequality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - long FirstVarInt = long.Parse(FirstVarValue); - long SecondVarInt = long.Parse(SecondVarValue); - Satisfied = FirstVarInt > SecondVarInt; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if one of the two UESH variables is less than the other or equal to each other - /// - /// The first $variable - /// The second $variable - /// True if the one of the two UESH variables is less than the other or equal to each other. False if otherwise. - public static bool UESHVariableLessThanOrEqual(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for inequality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - long FirstVarInt = long.Parse(FirstVarValue); - long SecondVarInt = long.Parse(SecondVarValue); - Satisfied = FirstVarInt <= SecondVarInt; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if one of the two UESH variables is greater than the other or equal to each other - /// - /// The first $variable - /// The second $variable - /// True if the one of the two UESH variables is greater than the other or equal to each other. False if otherwise. - public static bool UESHVariableGreaterThanOrEqual(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1} for inequality...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - long FirstVarInt = long.Parse(FirstVarValue); - long SecondVarInt = long.Parse(SecondVarValue); - Satisfied = FirstVarInt >= SecondVarInt; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a file path and exists - /// - /// The $variable - /// True if the file exists. False if otherwise. - public static bool UESHVariableFileExists(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} for file existence...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = Checking.FileExists(VarValue, true); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a file path and doesn't exist - /// - /// The $variable - /// True if the file doesn't exist. False if otherwise. - public static bool UESHVariableFileDoesNotExist(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} for file existence...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = !Checking.FileExists(VarValue, true); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a directory path and exists - /// - /// The $variable - /// True if the directory exists. False if otherwise. - public static bool UESHVariableDirectoryExists(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} for directory existence...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = Checking.FolderExists(VarValue, true); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a directory path and doesn't exist - /// - /// The $variable - /// True if the directory doesn't exist. False if otherwise. - public static bool UESHVariableDirectoryDoesNotExist(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} for directory existence...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = !Checking.FolderExists(VarValue, true); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a UESH variable contains an expression - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableContains(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = FirstVarValue.Contains(SecondVarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a UESH variable doesn't contain an expression - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableNotContains(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = !FirstVarValue.Contains(SecondVarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a valid file path - /// - /// The $variable - /// True if valid. False if otherwise. - public static bool UESHVariableValidPath(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0}...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = Parsing.TryParsePath(VarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is not a valid file path - /// - /// The $variable - /// True if invalid. False if otherwise. - public static bool UESHVariableInvalidPath(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0}...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = !Parsing.TryParsePath(VarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is a valid file name - /// - /// The $variable - /// True if valid. False if otherwise. - public static bool UESHVariableValidFileName(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0}...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = Parsing.TryParseFileName(VarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if the value of the UESH variable is not a valid file name - /// - /// The $variable - /// True if invalid. False if otherwise. - public static bool UESHVariableInvalidFileName(string Variable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0}...", Variable); - string VarValue = UESHVariables.GetVariable(Variable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of {0}: {1}...", Variable, VarValue); - Satisfied = !Parsing.TryParseFileName(VarValue); - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a UESH variable matches its hash specified on the second - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableHashMatch(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = Encryption.GetEncryptedString(FirstVarValue, "SHA256") == SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a UESH variable doesn't match its hash specified on the second - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableHashNoMatch(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = Encryption.GetEncryptedString(FirstVarValue, "SHA256") != SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a file specified from a UESH variable matches its hash specified on the second - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableFileHashMatch(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = Encryption.GetEncryptedFile(FirstVarValue, "SHA256") == SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - /// - /// Checks to see if a file specified from a UESH variable doesn't match its hash specified on the second - /// - /// The first $variable - /// The second $variable - /// True if satisfied. False if otherwise. - public static bool UESHVariableFileHashNoMatch(string FirstVariable, string SecondVariable) - { - bool Satisfied; - DebugWriter.WriteDebug(DebugLevel.I, "Querying {0} and {1}...", FirstVariable, SecondVariable); - string FirstVarValue = UESHVariables.GetVariable(FirstVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of first var {0}: {1}...", FirstVariable, FirstVarValue); - string SecondVarValue = UESHVariables.GetVariable(SecondVariable); - DebugWriter.WriteDebug(DebugLevel.I, "Got value of second var {0}: {1}...", SecondVariable, SecondVarValue); - Satisfied = Encryption.GetEncryptedFile(FirstVarValue, "SHA256") != SecondVarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Satisfied: {0}", Satisfied); - return Satisfied; - } - - } -} diff --git a/Terminaux/Shell/Scripting/UESHParse.cs b/Terminaux/Shell/Scripting/UESHParse.cs deleted file mode 100644 index b94a284ca..000000000 --- a/Terminaux/Shell/Scripting/UESHParse.cs +++ /dev/null @@ -1,248 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.Linq; -using System.Collections.Generic; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Files.Operations; -using Nitrocid.Languages; -using Nitrocid.Kernel.Exceptions; -using Terminaux.Writer.MiscWriters; -using Nitrocid.Kernel.Events; -using Textify.General; -using Terminaux.Shell.Shells; -using Terminaux.Shell.Scripting.Conditions; - -namespace Terminaux.Shell.Scripting -{ - /// - /// UESH script parser - /// - public static class UESHParse - { - - /// - /// Executes the UESH script - /// - /// Full path to script - /// Script arguments - /// If true, just lints the script and throws exception if there are parsing errors - public static void Execute(string ScriptPath, string ScriptArguments, bool justLint = false) - { - int LineNo = 1; - try - { - // Raise event - EventsManager.FireEvent(EventType.UESHPreExecute, ScriptPath, ScriptArguments); - - // Open the script file for reading - var FileLines = Reading.ReadAllLinesNoBlock(ScriptPath); - DebugWriter.WriteDebug(DebugLevel.I, "Stream opened. Parsing script"); - - // Look for $variables and initialize them - for (int l = 0; l < FileLines.Length; l++) - { - // Get line - string Line = FileLines[l]; - DebugWriter.WriteDebug(DebugLevel.I, "Line {0}: \"{1}\"", LineNo, Line); - - // If $variable is found in string, initialize it - var SplitWords = Line.Split(' '); - for (int i = 0; i <= SplitWords.Length - 1; i++) - if (!UESHVariables.ShellVariables.ContainsKey(SplitWords[i]) & SplitWords[i].StartsWith("$")) - UESHVariables.InitializeVariable(SplitWords[i]); - LineNo++; - } - - // Get all lines and parse comments, commands, and arguments - string[] commandBlocks = ["if", "while", "until"]; - int commandStackNum = 0; - bool newCommandStackRequired = false; - bool retryLoopCondition = false; - bool advance = true; - List<(int, int)> whilePlaces = []; - LineNo = 1; - for (int l = 0; l < FileLines.Length; l++) - { - // Decrement if not advancing - if (!advance) - { - advance = true; - l--; - } - - // Get line - string Line = FileLines[l]; - DebugWriter.WriteDebug(DebugLevel.I, "Line {0}: \"{1}\"", LineNo, Line); - - // First, trim the line from the left after checking the stack - string stackIndicator = new('|', commandStackNum); - if (Line.StartsWith(stackIndicator)) - { - newCommandStackRequired = false; - - // Get the actual command - Line = Line[commandStackNum..]; - - // If it still starts with the new stack indicator, throw an error - if (Line.StartsWith('|')) - throw new KernelException(KernelExceptionType.UESHScript, Translate.DoTranslation("You can't declare the new block before you place expressions that support the creation, like conditions or loops. The stack number is {0}.") + " {1}:{2}\n{3}", commandStackNum, ScriptPath, LineNo, LineHandleWriter.RenderLineWithHandle(ScriptPath, LineNo, commandStackNum)); - } - else if (!Line.StartsWith(stackIndicator) && newCommandStackRequired) - throw new KernelException(KernelExceptionType.UESHScript, Translate.DoTranslation("When starting a new block, make sure that you've indented the stack correctly. The stack number is {0}.") + " {1}:{2}\n{3}", commandStackNum, ScriptPath, LineNo, LineHandleWriter.RenderLineWithHandle(ScriptPath, LineNo, commandStackNum)); - else - { - if (retryLoopCondition && !justLint) - { - (int, int) whilePlace = whilePlaces[^1]; - commandStackNum = whilePlace.Item2; - l = whilePlace.Item1; - Line = FileLines[l][commandStackNum..]; - } - else - commandStackNum = 0; - } - - // See if the line contains variable, and replace every instance of it with its value - var SplitWords = Line.SplitEncloseDoubleQuotes(); - if (SplitWords is not null) - // Iterate every word - for (int i = 0; i <= SplitWords.Length - 1; i++) - // Every word that start with the $ sign means it's a variable that should be replaced with the - // value from the UESH variable manager. - if (SplitWords[i].StartsWith("$")) - Line = UESHVariables.GetVariableCommand(SplitWords[i], Line); - - // See if the line contains argument placeholder, and replace every instance of it with its value - var SplitArguments = ScriptArguments.SplitEncloseDoubleQuotes(); - if (SplitArguments is not null) - // Iterate every script argument - for (int j = 0; j <= SplitArguments.Length - 1; j++) - // If there is a placeholder variable like so: - // echo Hello, {0} - // ...or... - // echo {0}ification - // ...then proceed to replace the placeholder that contains an index of argument with the - // actual value - Line = Line.Replace($"{{{j}}}", SplitArguments[j]); - - // See if the line is a command that starts with the if statement - if (SplitWords is not null) - { - string Command = SplitWords[0]; - string Arguments = Line.RemovePrefix($"{Command} "); - bool isBlock = commandBlocks.Contains(Command); - if (isBlock) - { - bool satisfied = false; - switch (Command) - { - case "if": - case "while": - satisfied = justLint || UESHConditional.ConditionSatisfied(Arguments); - if (Command == "while") - { - if (!whilePlaces.Contains((l, commandStackNum))) - whilePlaces.Add((l, commandStackNum)); - retryLoopCondition = true; - } - break; - case "until": - satisfied = justLint || !UESHConditional.ConditionSatisfied(Arguments); - if (!whilePlaces.Contains((l, commandStackNum))) - whilePlaces.Add((l, commandStackNum)); - retryLoopCondition = true; - break; - } - if (satisfied) - { - // New stack required - newCommandStackRequired = true; - commandStackNum++; - continue; - } - else if (!justLint) - { - // Skip all the if block until we reach our stack - while (true) - { - l++; - if (l < FileLines.Length) - Line = FileLines[l]; - string blockStackIndicator = new('|', commandStackNum + 1); - if (!Line.StartsWith(blockStackIndicator)) - { - int newStackNum = 0; - int charNum = 0; - while (Line[charNum] == '|') - { - newStackNum++; - charNum++; - } - commandStackNum = newStackNum; - break; - } - if (l >= FileLines.Length) - return; - } - Line = Line[commandStackNum..]; - retryLoopCondition = false; - - // Continue, because the script might have the if condition directly after the stack - advance = false; - continue; - } - } - } - - // See if the line is a comment or command - if (!Line.StartsWith("#") & !Line.StartsWith(" ")) - { - DebugWriter.WriteDebug(DebugLevel.I, "Line {0} is not a comment.", Line); - if (!justLint) - ShellManager.GetLine(Line); - } - else - // For debugging purposes - DebugWriter.WriteDebug(DebugLevel.I, "Line {0} is a comment.", Line); - - // Increment the new line number - LineNo++; - } - EventsManager.FireEvent(EventType.UESHPostExecute, ScriptPath, ScriptArguments); - } - catch (KernelException ex) - { - EventsManager.FireEvent(EventType.UESHError, ScriptPath, ScriptArguments, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Error trying to execute script {0} with arguments {1}: {2}", ScriptPath, ScriptArguments, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - throw new KernelException(KernelExceptionType.UESHScript, Translate.DoTranslation("The script is malformed. Check the script and resolve any errors.") + "\n{0}", ex, LineHandleWriter.RenderLineWithHandle(ScriptPath, LineNo, 0)); - } - catch (Exception ex) - { - EventsManager.FireEvent(EventType.UESHError, ScriptPath, ScriptArguments, ex); - DebugWriter.WriteDebug(DebugLevel.E, "Error trying to execute script {0} with arguments {1}: {2}", ScriptPath, ScriptArguments, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - throw new KernelException(KernelExceptionType.UESHScript, Translate.DoTranslation("The script is malformed. Check the script and resolve any errors: {0}") + "\n{1}", ex, ex.Message, LineHandleWriter.RenderLineWithHandle(ScriptPath, LineNo, 0)); - } - } - - } -} diff --git a/Terminaux/Shell/Scripting/UESHVariables.cs b/Terminaux/Shell/Scripting/UESHVariables.cs deleted file mode 100644 index cc8b55415..000000000 --- a/Terminaux/Shell/Scripting/UESHVariables.cs +++ /dev/null @@ -1,259 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Nitrocid.Kernel; -using Nitrocid.Kernel.Configuration; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Misc.Text.Probers.Regexp; -using Terminaux.Shell.Arguments; -using Terminaux.Shell.Commands; -using Terminaux.Shell.Shells; -using Textify.General; - -namespace Terminaux.Shell.Scripting -{ - /// - /// UESH shell variable manager - /// - public static class UESHVariables - { - - internal static Dictionary ShellVariables = new() - { - { "$FrameworkSpecificRid", KernelPlatform.GetCurrentRid() }, - { "$FrameworkRid", KernelPlatform.GetCurrentGenericRid() }, - { "$CurrentCulture", Config.MainConfig.CurrentCultStr }, - { "$CurrentSysCulture", CultureInfo.CurrentCulture.Name }, - { "$CurrentUiSysCulture", CultureInfo.CurrentUICulture.Name }, - }; - - /// - /// Checks to see if the variable name starts with the correct format - /// - /// A $variable name - /// Sanitized variable name - public static string SanitizeVariableName(string var) - { - DebugWriter.WriteDebug(DebugLevel.I, "Sanitizing variable {0}...", var); - if (!var.StartsWith("$")) - { - DebugWriter.WriteDebug(DebugLevel.W, "Unsanitized variable found. Prepending $..."); - var = $"${var}"; - } - return var; - } - - /// - /// Initializes a $variable - /// - /// A $variable - public static void InitializeVariable(string var) - { - var = SanitizeVariableName(var); - if (ShellVariables.TryAdd(var, "")) - DebugWriter.WriteDebug(DebugLevel.I, "Initialized variable {0}", var); - } - - /// - /// Gets a value of a $variable on command line - /// - /// A $variable - /// A command line in script - /// A command line in script that has a value of $variable - public static string GetVariableCommand(string var, string cmd) - { - var CommandArgumentsInfo = ArgumentsParser.ParseShellCommandArguments(cmd, ShellType.Shell).total[0]; - string NewCommand = $"{CommandArgumentsInfo.Command} "; - var commands = CommandManager.GetCommands(ShellType.Shell); - if (!CommandManager.IsCommandFound(CommandArgumentsInfo.Command) || - !ShellManager.GetShellInfo(ShellType.Shell).Commands.Single((ci) => ci.Command == CommandArgumentsInfo.Command).CommandArgumentInfo.Any((cai) => cai.AcceptsSet)) - { - foreach (string Word in CommandArgumentsInfo.ArgumentsList) - { - string finalWord = Word; - if (finalWord.Contains(var) & finalWord.StartsWith("$")) - { - finalWord = ShellVariables[var]; - } - NewCommand += $"{finalWord} "; - } - DebugWriter.WriteDebug(DebugLevel.I, "Replaced variable {0} with their values. Result: {1}", var, NewCommand); - return NewCommand.TrimEnd(' '); - } - return cmd; - } - - /// - /// Gets a value of a $variable - /// - /// A $variable - /// A value of $variable, or a variable name if not found - public static string GetVariable(string var) - { - try - { - string FinalVar = SanitizeVariableName(var); - if (ShellVariables.TryGetValue(FinalVar, out string? variableValue)) - return variableValue; - return var; - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Error getting variable {0}: {1}", var, ex.Message); - } - return var; - } - - /// - /// Gets the variables and returns the available variables as a dictionary - /// - public static Dictionary Variables => - ShellVariables; - - /// - /// Sets a $variable - /// - /// A $variable - /// A value to set to $variable - public static bool SetVariable(string var, string value) - { - try - { - var = SanitizeVariableName(var); - if (!ShellVariables.ContainsKey(var)) - InitializeVariable(var); - ShellVariables[var] = value; - DebugWriter.WriteDebug(DebugLevel.I, "Set variable {0} to {1}", var, value); - return true; - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Error setting variable {0}: {1}", var, ex.Message); - } - return false; - } - - /// - /// Makes an array of a $variable with the chosen number of values (e.g. $variable[0] = first value, $variable[1] = second value, ...) - /// - /// A $variable array name - /// A set of values to set - public static bool SetVariables(string var, string[] values) - { - try - { - var = SanitizeVariableName(var); - for (int ValueIndex = 0; ValueIndex <= values.Length - 1; ValueIndex++) - { - string VarName = $"{var}[{ValueIndex}]"; - string VarValue = values[ValueIndex]; - if (!ShellVariables.ContainsKey(VarName)) - InitializeVariable(VarName); - ShellVariables[VarName] = VarValue; - DebugWriter.WriteDebug(DebugLevel.I, "Set variable {0} to {1}", VarName, VarValue); - } - return true; - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Error creating variable array {0}: {1}", var, ex.Message); - } - return false; - } - - /// - /// Removes a variable from the shell variables dictionary - /// - /// Target variable - public static bool RemoveVariable(string var) - { - try - { - var = SanitizeVariableName(var); - return ShellVariables.Remove(var); - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Error removing variable {0}: {1}", var, ex.Message); - } - return false; - } - - /// - /// Parses the system environment variables and converts them to the UESH shell variables - /// - public static void ConvertSystemEnvironmentVariables() - { - var EnvVars = Environment.GetEnvironmentVariables(); - foreach (string EnvVar in EnvVars.Keys) - SetVariable(EnvVar, EnvVars[EnvVar]?.ToString() ?? ""); - } - - /// - /// Initializes the UESH variables from the expression - /// - /// UESH variable expressions in the form of $var=value - public static void InitializeVariablesFrom(string expression) - { - // Get the variable keys and values - expression = string.IsNullOrEmpty(expression) ? "" : expression; - var varTuple = GetVariablesFrom(expression); - var varStoreKeys = varTuple.varStoreKeys; - var varStoreValues = varTuple.varStoreValues; - - // Now, initialize the variables one by one - for (int i = 0; i < varStoreKeys.Length; i++) - { - // Get the key and the value - string varStoreKey = varStoreKeys[i]; - string varStoreValue = varStoreValues[i].ReleaseDoubleQuotes(); - DebugWriter.WriteDebug(DebugLevel.I, "Adding {0} to {1}...", varStoreValue, varStoreKey); - - // Initialize each variable and set them - InitializeVariable(varStoreKey); - bool result = SetVariable(varStoreKey, varStoreValue); - DebugWriter.WriteDebug(DebugLevel.I, "Added {0} to {1}: {2}", varStoreValue, varStoreKey, result); - } - } - - /// - /// Gets the UESH variables from the expression - /// - /// UESH variable expressions in the form of $var=value - public static (string[] varStoreKeys, string[] varStoreValues) GetVariablesFrom(string expression) - { - // Get the variable keys and values - expression = string.IsNullOrEmpty(expression) ? "" : expression; - string localVarStoreValuesMatch = /* lang=regex */ - @"((?'key'\$\S+)=(?'value'(""(.+?)(? match.Groups["key"].Value).ToArray(); - var varStoreValues = varStoreMatches - .Select((match) => match.Groups["value"].Value).ToArray(); - DebugWriter.WriteDebug(DebugLevel.I, "Keys: {0} [{1}], Values: {2} [{3}]", varStoreKeys.Length, string.Join(", ", varStoreKeys), varStoreValues.Length, string.Join(", ", varStoreValues)); - return (varStoreKeys, varStoreValues); - } - - } -} diff --git a/Terminaux/Shell/Shells/BaseShell.cs b/Terminaux/Shell/Shells/BaseShell.cs index d6b0bb098..1326fb78f 100644 --- a/Terminaux/Shell/Shells/BaseShell.cs +++ b/Terminaux/Shell/Shells/BaseShell.cs @@ -17,9 +17,6 @@ // along with this program. If not, see . // -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Exceptions; - namespace Terminaux.Shell.Shells { /// @@ -27,7 +24,6 @@ namespace Terminaux.Shell.Shells /// public abstract class BaseShell : IShell { - /// public virtual string ShellType { get; private set; } = ""; @@ -35,11 +31,6 @@ public abstract class BaseShell : IShell public virtual bool Bail { get; set; } /// - public virtual void InitializeShell(params object[] ShellArgs) - { - DebugWriter.WriteDebug(DebugLevel.F, "We shouldn't be here!!!"); - throw new KernelException(KernelExceptionType.NotImplementedYet); - } - + public abstract void InitializeShell(params object[] ShellArgs); } } diff --git a/Terminaux/Shell/Shells/BaseShellInfo.cs b/Terminaux/Shell/Shells/BaseShellInfo.cs index 330bffbd5..db7604b7b 100644 --- a/Terminaux/Shell/Shells/BaseShellInfo.cs +++ b/Terminaux/Shell/Shells/BaseShellInfo.cs @@ -17,23 +17,22 @@ // along with this program. If not, see . // -using Nitrocid.Shell.ShellBase.Arguments; using System.Collections.Generic; +using Terminaux.Shell.Arguments; using Terminaux.Shell.Commands; using Terminaux.Shell.Prompts; namespace Terminaux.Shell.Shells { /// - /// Shell information for both the KS shells and the custom shells made by mods + /// Shell information /// public abstract class BaseShellInfo : IShellInfo { - internal List modCommands = []; - internal List addonCommands = []; + internal List extraCommands = []; internal Dictionary customShellPresets = []; internal static CommandInfo fallbackNonSlashCommand = - new("slashreminder", /* Localizable */ "Reminder for the slash commands", + new("slashreminder", "Reminder for the slash commands", [ new CommandArgumentInfo() ], new SlashReminderCommand()); @@ -43,21 +42,20 @@ public abstract class BaseShellInfo : IShellInfo /// public virtual List Commands => []; /// - public virtual List ModCommands => modCommands; - /// public virtual Dictionary ShellPresets => []; /// public virtual Dictionary CustomShellPresets => customShellPresets; /// public virtual BaseShell? ShellBase => null; /// - public virtual PromptPresetBase CurrentPreset => - - PromptPresetManager.GetAllPresetsFromShell(ShellType)[PromptPresetManager.CurrentPresets[ShellType]]; - /// - public virtual bool AcceptsNetworkConnection => false; - /// - public virtual string NetworkConnectionType => ""; + public virtual PromptPresetBase CurrentPreset + { + get + { + var presets = PromptPresetManager.GetAllPresetsFromShell(ShellType); + return presets.Count > 0 ? presets[PromptPresetManager.CurrentPresets[ShellType]] : new PromptPresetBase(); + } + } /// public virtual bool OneLineWrap => false; /// diff --git a/Terminaux/Shell/Shells/IShellInfo.cs b/Terminaux/Shell/Shells/IShellInfo.cs index 4d99b450e..1ae9404d1 100644 --- a/Terminaux/Shell/Shells/IShellInfo.cs +++ b/Terminaux/Shell/Shells/IShellInfo.cs @@ -24,7 +24,7 @@ namespace Terminaux.Shell.Shells { /// - /// Shell information interface for both the KS shells and the custom shells made by mods + /// Shell information interface /// public interface IShellInfo { @@ -37,10 +37,6 @@ public interface IShellInfo /// List Commands { get; } /// - /// Mod commands - /// - List ModCommands { get; } - /// /// Built-in shell presets /// Dictionary ShellPresets { get; } @@ -57,14 +53,6 @@ public interface IShellInfo /// PromptPresetBase CurrentPreset { get; } /// - /// Whether the shell accepts network connection - /// - bool AcceptsNetworkConnection { get; } - /// - /// Network connection type defined for the shell (valid only on shells that have set to true) - /// - string NetworkConnectionType { get; } - /// /// Whether the shell uses one line for input /// bool OneLineWrap { get; } @@ -73,7 +61,7 @@ public interface IShellInfo /// bool SlashCommand { get; } /// - /// For shells that have enabled, this is the command that gets executed everytime we encounter text that doesn't start with the slash. + /// For shells that have enabled, this is the command that gets executed every time we encounter text that doesn't start with the slash. /// CommandInfo NonSlashCommandInfo { get; } } diff --git a/Terminaux/Shell/Shells/ShellExecuteInfo.cs b/Terminaux/Shell/Shells/ShellExecuteInfo.cs index 9133ebfd1..04ce8fd47 100644 --- a/Terminaux/Shell/Shells/ShellExecuteInfo.cs +++ b/Terminaux/Shell/Shells/ShellExecuteInfo.cs @@ -17,8 +17,7 @@ // along with this program. If not, see . // -using System.Collections.Generic; -using Nitrocid.Kernel.Threading; +using System.Threading; namespace Terminaux.Shell.Shells { @@ -27,12 +26,10 @@ namespace Terminaux.Shell.Shells /// public class ShellExecuteInfo { - - internal int LastErrorCode = 0; - internal readonly List AltCommandThreads = []; + internal bool interrupting = false; + internal Thread shellCommandThread; private readonly string shellType; private readonly BaseShell? shellBase; - private readonly KernelThread shellCommandThread; /// /// Shell type @@ -47,17 +44,7 @@ public class ShellExecuteInfo /// /// Shell command thread /// - public KernelThread ShellCommandThread => shellCommandThread; - - /// - /// Installs the values to a new instance of ShellInfo - /// - /// The shell type - /// Shell base class - /// Shell command thread - public ShellExecuteInfo(ShellType ShellType, BaseShell? ShellBase, KernelThread ShellCommandThread) : - this(ShellManager.GetShellTypeName(ShellType), ShellBase, ShellCommandThread) - { } + public Thread ShellCommandThread => shellCommandThread; /// /// Installs the values to a new instance of ShellInfo @@ -65,7 +52,7 @@ public ShellExecuteInfo(ShellType ShellType, BaseShell? ShellBase, KernelThread /// The shell type /// Shell base class /// Shell command thread - public ShellExecuteInfo(string ShellType, BaseShell? ShellBase, KernelThread ShellCommandThread) + public ShellExecuteInfo(string ShellType, BaseShell? ShellBase, Thread ShellCommandThread) { shellType = ShellType; shellBase = ShellBase; diff --git a/Terminaux/Shell/Shells/ShellManager.cs b/Terminaux/Shell/Shells/ShellManager.cs index 49fa2f5cc..14ca0e33d 100644 --- a/Terminaux/Shell/Shells/ShellManager.cs +++ b/Terminaux/Shell/Shells/ShellManager.cs @@ -19,53 +19,21 @@ using System; using System.Collections.Generic; -using System.IO; using System.Text; -using File = Nitrocid.Drivers.Console.Bases.File; -using FileIO = System.IO.File; -using Manipulation = Nitrocid.Files.Operations.Manipulation; -using System.Text.RegularExpressions; using System.Linq; using Terminaux.Reader; using System.Collections.ObjectModel; -using Newtonsoft.Json; -using Nitrocid.Kernel; -using Nitrocid.Kernel.Configuration; -using Nitrocid.Users; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Files; -using Nitrocid.Shell.ShellBase.Arguments; -using Nitrocid.Drivers; -using Nitrocid.Kernel.Threading; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Languages; -using Nitrocid.Kernel.Exceptions; -using Nitrocid.Drivers.Console; -using Nitrocid.Security.Permissions; -using Nitrocid.Drivers.Console.Bases; -using Nitrocid.Files.Paths; -using Nitrocid.Kernel.Events; -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.Files.Operations.Querying; -using Nitrocid.Kernel.Power; -using Nitrocid.Misc.Text.Probers.Regexp; -using Nitrocid.Shell.ShellBase.Switches; -using Nitrocid.Shell.ShellBase.Shells.Unified; -using Nitrocid.Shell.Shells.Admin; -using Nitrocid.Shell.Shells.UESH; -using Nitrocid.Shell.Shells.Text; -using Nitrocid.Shell.Shells.Hex; -using Nitrocid.Shell.Shells.Debug; using Textify.General; using Terminaux.Base; -using Nitrocid.ConsoleBase.Inputs; -using Terminaux.Base.Extensions; using Terminaux.Reader.History; using Terminaux.Shell.Arguments; -using Terminaux.Shell.Commands.ProcessExecution; -using Terminaux.Shell.Scripting; using Terminaux.Shell.Commands; using Terminaux.Shell.Prompts; +using Terminaux.Shell.Switches; +using Terminaux.Shell.Shells.Unified; +using Terminaux.Colors.Data; +using System.Threading; +using Terminaux.Writer.ConsoleWriters; namespace Terminaux.Shell.Shells { @@ -74,43 +42,17 @@ namespace Terminaux.Shell.Shells /// public static class ShellManager { - internal static List ShellStack = []; internal static string lastCommand = ""; - internal static KernelThread ProcessStartCommandThread = new("Executable Command Thread", false, (processParams) => ProcessExecutor.ExecuteProcess((ExecuteProcessThreadParameters?)processParams)); - internal static Dictionary> histories = new() - { - { "General", new() }, - { $"{ShellType.AdminShell}", new() }, - { $"{ShellType.DebugShell}", new() }, - { $"{ShellType.HexShell}", new() }, - { $"{ShellType.Shell}", new() }, - { $"{ShellType.TextShell}", new() }, - }; internal readonly static List unifiedCommandDict = [ - new CommandInfo("exec", /* Localizable */ "Executes an external process", - [ - new CommandArgumentInfo( - [ - new CommandArgumentPart(true, "process"), - new CommandArgumentPart(false, "args") - ], - [ - new SwitchInfo("forked", /* Localizable */ "Executes the process without interrupting the shell thread. A separate window will be created.", new SwitchOptions() - { - AcceptsValues = false - }) - ]) - ], new ExecUnifiedCommand()), - - new CommandInfo("exit", /* Localizable */ "Exits the shell if running on subshell", + new CommandInfo("exit", "Exits the shell if running on subshell", [ new CommandArgumentInfo() ], new ExitUnifiedCommand()), - new CommandInfo("findcmds", /* Localizable */ "Finds the available commands in the current shell type", + new CommandInfo("findcmds", "Finds the available commands in the current shell type", [ new CommandArgumentInfo( [ @@ -118,7 +60,7 @@ public static class ShellManager ], false) ], new FindCmdsUnifiedCommand()), - new CommandInfo("help", /* Localizable */ "Help page", + new CommandInfo("help", "Help page", [ new CommandArgumentInfo( [ @@ -128,90 +70,44 @@ public static class ShellManager }) ], [ - new SwitchInfo("general", /* Localizable */ "Shows general commands (default)", new SwitchOptions() + new SwitchInfo("general", "Shows general commands (default)", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("mod", /* Localizable */ "Shows mod commands", new SwitchOptions() + new SwitchInfo("mod", "Shows mod commands", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("alias", /* Localizable */ "Shows aliased commands", new SwitchOptions() + new SwitchInfo("alias", "Shows aliased commands", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("unified", /* Localizable */ "Shows unified commands", new SwitchOptions() + new SwitchInfo("unified", "Shows unified commands", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("addon", /* Localizable */ "Shows kernel addon commands", new SwitchOptions() + new SwitchInfo("extra", "Shows kernel extra commands", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("all", /* Localizable */ "Shows all commands", new SwitchOptions() + new SwitchInfo("all", "Shows all commands", new SwitchOptions() { AcceptsValues = false }), - new SwitchInfo("simplified", /* Localizable */ "Uses simplified help", new SwitchOptions() + new SwitchInfo("simplified", "Uses simplified help", new SwitchOptions() { AcceptsValues = false }), ], false) - ], new HelpUnifiedCommand(), CommandFlags.Wrappable), + ], new HelpUnifiedCommand()), - new CommandInfo("loadhistories", /* Localizable */ "Loads shell histories", - [ - new CommandArgumentInfo() - ], new LoadHistoriesUnifiedCommand()), - - new CommandInfo("presets", /* Localizable */ "Opens the shell preset library", + new CommandInfo("presets", "Opens the shell preset library", [ new CommandArgumentInfo() ], new PresetsUnifiedCommand()), - - new CommandInfo("repeat", /* Localizable */ "Repeats the last action or the specified command", - [ - new CommandArgumentInfo(new[] - { - new CommandArgumentPart(true, "times", new CommandArgumentPartOptions() - { - IsNumeric = true - }), - new CommandArgumentPart(false, "command"), - }) - ], new RepeatUnifiedCommand()), - - new CommandInfo("savehistories", /* Localizable */ "Saves shell histories", - [ - new CommandArgumentInfo() - ], new SaveHistoriesUnifiedCommand()), - - new CommandInfo("tip", /* Localizable */ "Shows a random kernel tip", - [ - new CommandArgumentInfo() - ], new TipUnifiedCommand()), - - new CommandInfo("wrap", /* Localizable */ "Wraps the console output", - [ - new CommandArgumentInfo(new[] - { - new CommandArgumentPart(true, "command", new CommandArgumentPartOptions() - { - AutoCompleter = (_) => CommandExecutor.GetWrappableCommands(CurrentShellType) - }) - }) - ], new WrapUnifiedCommand()), ]; - internal readonly static Dictionary availableShells = new() - { - { "Shell", new UESHShellInfo() }, - { "TextShell", new TextShellInfo() }, - { "HexShell", new HexShellInfo() }, - { "AdminShell", new AdminShellInfo() }, - { "DebugShell", new DebugShellInfo() } - }; - internal readonly static Dictionary availableCustomShells = []; + internal readonly static Dictionary availableShells = []; /// /// List of unified commands @@ -223,13 +119,13 @@ public static class ShellManager /// List of available shells /// public static ReadOnlyDictionary AvailableShells => - new(availableShells.Union(availableCustomShells).ToDictionary()); + new(availableShells); /// /// Current shell type /// public static string CurrentShellType => - ShellStack[^1].ShellType; + ShellStack[ShellStack.Count - 1].ShellType; /// /// Last shell type @@ -241,20 +137,17 @@ public static string LastShellType if (ShellStack.Count == 0) { // We don't have any shell. Return Shell. - DebugWriter.WriteDebug(DebugLevel.W, "Trying to call LastShellType on empty shell stack. Assuming UESH..."); return "Shell"; } else if (ShellStack.Count == 1) { // We only have one shell. Consider current as last. - DebugWriter.WriteDebug(DebugLevel.W, "Trying to call LastShellType on shell stack containing only one shell. Assuming curent..."); return CurrentShellType; } else { // We have more than one shell. Return the shell type for a shell before the last one. - var type = ShellStack[^2].ShellType; - DebugWriter.WriteDebug(DebugLevel.I, "Returning shell type {0} for last shell from the stack...", type); + var type = ShellStack[ShellStack.Count - 2].ShellType; return type; } } @@ -263,67 +156,31 @@ public static string LastShellType /// /// Inputs for command then parses a specified command. /// - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. + /// All new shells implemented should use this routine to allow effective and consistent line parsing. public static void GetLine() => - GetLine("", "", CurrentShellType, true, Config.MainConfig.SetTitleOnCommandExecution); + GetLine("", CurrentShellType, true); /// - /// Parses a specified command. + /// Inputs for command then parses a specified command. /// /// The full command string - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. + /// All new shells implemented should use this routine to allow effective and consistent line parsing. public static void GetLine(string FullCommand) => - GetLine(FullCommand, "", CurrentShellType, true, Config.MainConfig.SetTitleOnCommandExecution); - - /// - /// Parses a specified command. - /// - /// The full command string - /// Optional (non-)neutralized output path - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. - public static void GetLine(string FullCommand, string OutputPath = "") => - GetLine(FullCommand, OutputPath, CurrentShellType, true, Config.MainConfig.SetTitleOnCommandExecution); - - /// - /// Parses a specified command. - /// - /// The full command string - /// Optional (non-)neutralized output path - /// Shell type - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. - public static void GetLine(string FullCommand, string OutputPath = "", ShellType ShellType = ShellType.Shell) => - GetLine(FullCommand, OutputPath, GetShellTypeName(ShellType), true, Config.MainConfig.SetTitleOnCommandExecution); + GetLine(FullCommand, CurrentShellType, true); /// /// Parses a specified command. /// /// The full command string - /// Optional (non-)neutralized output path /// Shell type - /// Whether to restore the driver to the previous state - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. - public static void GetLine(string FullCommand, string OutputPath = "", string ShellType = "Shell", bool restoreDriver = true) => - GetLine(FullCommand, OutputPath, ShellType, restoreDriver, Config.MainConfig.SetTitleOnCommandExecution); - - /// - /// Parses a specified command. - /// - /// The full command string - /// Optional (non-)neutralized output path - /// Shell type - /// Whether to restore the driver to the previous state - /// Whether to set the console title - /// All new shells implemented either in KS or by mods should use this routine to allow effective and consistent line parsing. - internal static void GetLine(string FullCommand, string OutputPath = "", string ShellType = "Shell", bool restoreDriver = true, bool setTitle = true) + /// Whether to enable history support or not + /// All new shells implemented should use this routine to allow effective and consistent line parsing. + internal static void GetLine(string FullCommand, string ShellType = "Shell", bool enableHistory = true) { // Check for sanity if (string.IsNullOrEmpty(FullCommand)) FullCommand = ""; - // Variables - string? TargetFile = ""; - string TargetFileName = ""; - // Get the shell info var shellInfo = GetShellInfo(ShellType); @@ -333,9 +190,9 @@ internal static void GetLine(string FullCommand, string OutputPath = "", string Suggestions = (text, index, _) => CommandAutoComplete.GetSuggestions(text, index), SuggestionsDelimiters = [' '], TreatCtrlCAsInput = true, - InputForegroundColor = KernelColorTools.GetColor(KernelColorType.Input), + InputForegroundColor = ConsoleColors.Silver, HistoryName = ShellType, - HistoryEnabled = Config.MainConfig.InputHistoryEnabled, + HistoryEnabled = enableHistory, }; // Check to see if the full command string ends with the semicolon @@ -347,30 +204,16 @@ internal static void GetLine(string FullCommand, string OutputPath = "", string // Tell the user to provide the command StringBuilder commandBuilder = new(FullCommand); - // We need to put a synclock in the below steps, because the cancellation handlers seem to be taking their time to try to suppress the - // thread abort error messages. If the shell tried to write to the console while these handlers were still working, the command prompt - // would either be incomplete or not printed to the console at all. + // Populate the prompt string prompt = ""; - lock (CancellationHandlers.GetCancelSyncLock(ShellType)) - { - // Print a prompt - var preset = PromptPresetManager.GetCurrentPresetBaseFromShell(ShellType); - if (!string.IsNullOrEmpty(FullCommand)) - prompt = preset.PresetPromptCompletion; - else - prompt = preset.PresetPrompt; - } - - // Raise shell initialization event - EventsManager.FireEvent(EventType.ShellInitialized, ShellType); + var preset = PromptPresetManager.GetCurrentPresetBaseFromShell(ShellType); + if (!string.IsNullOrEmpty(FullCommand)) + prompt = preset.PresetPromptCompletion; + else + prompt = preset.PresetPrompt; // Wait for command - DebugWriter.WriteDebug(DebugLevel.I, "Waiting for command"); - string strcommand = - shellInfo.OneLineWrap ? - InputTools.ReadLineWrapped(prompt, "", settings) : - InputTools.ReadLine(prompt, "", settings); - DebugWriter.WriteDebug(DebugLevel.I, "Waited for command [{0}]", strcommand); + string strcommand = TermReader.Read(prompt, "", settings, oneLineWrap: shellInfo.OneLineWrap); if (strcommand == ";") strcommand = ""; @@ -387,12 +230,12 @@ internal static void GetLine(string FullCommand, string OutputPath = "", string // There are cases when the kernel panics or reboots in the middle of the command input. If reboot is requested, // ensure that we're really gone. - if (PowerManager.RebootRequested) + var ShellInstance = ShellStack[ShellStack.Count - 1]; + if (ShellInstance.interrupting) return; } // Check for a type of command - CancellationHandlers.AllowCancel(); var SplitCommands = FullCommand.Split(new[] { " ; " }, StringSplitOptions.RemoveEmptyEntries); var Commands = CommandManager.GetCommands(ShellType); for (int i = 0; i < SplitCommands.Length; i++) @@ -402,44 +245,19 @@ internal static void GetLine(string FullCommand, string OutputPath = "", string // Then, check to see if this shell uses the slash command if (shellInfo.SlashCommand) { - if (!Command.StartsWith('/')) + // Check if we need to remove the slash + if (!Command.StartsWith("/")) { // Not a slash command. Do things differently - var ShellInstance = ShellStack[^1]; - DebugWriter.WriteDebug(DebugLevel.I, "Non-slash cmd exec succeeded. Running with {0}", Command); + var ShellInstance = ShellStack[ShellStack.Count - 1]; var Params = new CommandExecutorParameters(Command, shellInfo.NonSlashCommandInfo ?? BaseShellInfo.fallbackNonSlashCommand, ShellType, ShellInstance); CommandExecutor.StartCommandThread(Params); - UESHVariables.SetVariable("UESHErrorCode", $"{ShellInstance.LastErrorCode}"); continue; } else - { - // Strip the slash - Command = Command[1..].Trim(); - } + Command = Command.Substring(1).Trim(); } - // Fire an event of PreExecuteCommand - EventsManager.FireEvent(EventType.PreExecuteCommand, ShellType, Command); - - // Initialize local UESH variables (if found) - string localVarStoreMatchRegex = /* lang=regex */ @"^\((.+)\)\s+"; - var localVarStoreMatch = RegexpTools.Match(Command, localVarStoreMatchRegex); - string varStoreString = localVarStoreMatch.Groups[1].Value; - DebugWriter.WriteDebug(DebugLevel.I, "varStoreString is: {0}", varStoreString); - string varStoreStringFull = localVarStoreMatch.Value; - var varStoreVars = UESHVariables.GetVariablesFrom(varStoreString); - - // First, check to see if we already have that variable. If we do, get its old value. - List<(string, string)> oldVarValues = []; - foreach (string varStoreKey in varStoreVars.varStoreKeys) - { - if (UESHVariables.Variables.ContainsKey(varStoreKey)) - oldVarValues.Add((varStoreKey, UESHVariables.GetVariable(varStoreKey))); - } - UESHVariables.InitializeVariablesFrom(varStoreString); - Command = Command[varStoreStringFull.Length..]; - // Check to see if the command is a comment if (!string.IsNullOrWhiteSpace(Command) && !Command.StartsWithAnyOf([" ", "#"])) { @@ -452,206 +270,38 @@ internal static void GetLine(string FullCommand, string OutputPath = "", string break; // Now, split the arguments - string arguments = string.Join(' ', words.Skip(1)); - - // Get the target file and path - TargetFile = RegexpTools.Unescape(commandName); - bool existsInPath = PathLookupTools.FileExistsInPath(commandName, ref TargetFile); - bool pathValid = Parsing.TryParsePath(TargetFile ?? ""); - if (!existsInPath || string.IsNullOrEmpty(TargetFile)) - TargetFile = FilesystemTools.NeutralizePath(commandName); - if (pathValid) - TargetFileName = Path.GetFileName(TargetFile); - DebugWriter.WriteDebug(DebugLevel.I, "Finished finalCommand: {0}", commandName); - DebugWriter.WriteDebug(DebugLevel.I, "Finished TargetFile: {0}", TargetFile); + string arguments = string.Join(" ", words.Skip(1)); // Reads command written by user try { - // Set title - if (setTitle) - ConsoleMisc.SetTitle($"{KernelReleaseInfo.ConsoleTitle} - {Command}"); - // Check the command bool exists = Commands.Any((ci) => ci.Command == commandName || ci.Aliases.Any((ai) => ai.Alias == commandName)); if (exists) { // Execute the command - DebugWriter.WriteDebug(DebugLevel.I, "Executing command"); var cmdInfo = Commands.Single((ci) => ci.Command == commandName || ci.Aliases.Any((ai) => ai.Alias == commandName)); - // Check to see if the command supports redirection - if (cmdInfo.Flags.HasFlag(CommandFlags.RedirectionSupported)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Redirection supported!"); - Command = InitializeRedirection(Command); - } - - // Check to see if the optional path is specified - if (!string.IsNullOrEmpty(OutputPath)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Output path provided!"); - InitializeOutputPathWriter(OutputPath); - } - if (!string.IsNullOrEmpty(commandName) || !commandName.StartsWithAnyOf([" ", "#"])) { - - // Check to see if a user is able to execute a command - if (ShellType == "Shell") - { - if (cmdInfo.Flags.HasFlag(CommandFlags.Strict)) - { - if (!PermissionsTools.IsPermissionGranted(PermissionTypes.RunStrictCommands) && - !UserManagement.CurrentUser.Flags.HasFlag(UserFlags.Administrator)) - { - DebugWriter.WriteDebug(DebugLevel.W, "Cmd exec {0} failed: adminList(signedinusrnm) is False, strictCmds.Contains({0}) is True", commandName); - TextWriters.Write(Translate.DoTranslation("You don't have permission to use {0}"), true, KernelColorType.Error, commandName); - UESHVariables.SetVariable("UESHErrorCode", "-4"); - break; - } - } - } - // Check the command before starting - if (KernelEntry.Maintenance & cmdInfo.Flags.HasFlag(CommandFlags.NoMaintenance)) - { - DebugWriter.WriteDebug(DebugLevel.W, "Cmd exec {0} failed: In maintenance mode. {0} is in NoMaintenanceCmds", commandName); - TextWriters.Write(Translate.DoTranslation("Shell message: The requested command {0} is not allowed to run in maintenance mode."), true, KernelColorType.Error, commandName); - UESHVariables.SetVariable("UESHErrorCode", "-3"); - } - else - { - var ShellInstance = ShellStack[^1]; - DebugWriter.WriteDebug(DebugLevel.I, "Cmd exec {0} succeeded. Running with {1}", commandName, Command); - var Params = new CommandExecutorParameters(Command, cmdInfo, ShellType, ShellInstance); - CommandExecutor.StartCommandThread(Params); - UESHVariables.SetVariable("UESHErrorCode", $"{ShellInstance.LastErrorCode}"); - } - } - } - else if (pathValid & ShellType == "Shell") - { - // If we're in the UESH shell, parse the script file or executable file - if (Checking.FileExists(TargetFile) & !TargetFile.EndsWith(".uesh")) - { - DebugWriter.WriteDebug(DebugLevel.I, "Cmd exec {0} succeeded because file is found.", commandName); - try - { - // Create a new instance of process - PermissionsTools.Demand(PermissionTypes.ExecuteProcesses); - if (pathValid) - { - var targetCommand = Command.Replace(TargetFileName, ""); - targetCommand = targetCommand.TrimStart('\0', ' '); - DebugWriter.WriteDebug(DebugLevel.I, "Command: {0}, Arguments: {1}", TargetFile, targetCommand); - var Params = new ExecuteProcessThreadParameters(TargetFile, targetCommand); - ProcessStartCommandThread.Start(Params); - ProcessStartCommandThread.Wait(); - ProcessStartCommandThread.Stop(); - UESHVariables.SetVariable("UESHErrorCode", "0"); - } - } - catch (Exception ex) - { - DebugWriter.WriteDebug(DebugLevel.E, "Failed to start process: {0}", ex.Message); - TextWriters.Write(Translate.DoTranslation("Failed to start \"{0}\": {1}"), true, KernelColorType.Error, commandName, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - if (ex is KernelException kex) - UESHVariables.SetVariable("UESHErrorCode", $"{KernelExceptionTools.GetErrorCode(kex)}"); - else - UESHVariables.SetVariable("UESHErrorCode", $"{ex.GetHashCode()}"); - } - } - else if (Checking.FileExists(TargetFile) & TargetFile.EndsWith(".uesh")) - { - try - { - PermissionsTools.Demand(PermissionTypes.ExecuteScripts); - DebugWriter.WriteDebug(DebugLevel.I, "Cmd exec {0} succeeded because it's a UESH script.", commandName); - UESHParse.Execute(TargetFile, arguments); - UESHVariables.SetVariable("UESHErrorCode", "0"); - } - catch (Exception ex) - { - TextWriters.Write(Translate.DoTranslation("Error trying to execute script: {0}"), true, KernelColorType.Error, ex.Message); - DebugWriter.WriteDebugStackTrace(ex); - if (ex is KernelException kex) - UESHVariables.SetVariable("UESHErrorCode", $"{KernelExceptionTools.GetErrorCode(kex)}"); - else - UESHVariables.SetVariable("UESHErrorCode", $"{ex.GetHashCode()}"); - } - } - else - { - DebugWriter.WriteDebug(DebugLevel.W, "Cmd exec {0} failed: command {0} not found parsing target file", commandName); - TextWriters.Write(Translate.DoTranslation("Shell message: The requested command {0} is not found. See 'help' for available commands."), true, KernelColorType.Error, commandName); - UESHVariables.SetVariable("UESHErrorCode", "-2"); + var ShellInstance = ShellStack[ShellStack.Count - 1]; + var Params = new CommandExecutorParameters(Command, cmdInfo, ShellType, ShellInstance); + CommandExecutor.StartCommandThread(Params); } } else - { - DebugWriter.WriteDebug(DebugLevel.W, "Cmd exec {0} failed: command {0} not found", commandName); - TextWriters.Write(Translate.DoTranslation("Shell message: The requested command {0} is not found. See 'help' for available commands."), true, KernelColorType.Error, commandName); - UESHVariables.SetVariable("UESHErrorCode", "-1"); - } + TextWriterRaw.WritePlain("Shell message: The requested command {0} is not found. See 'help' for available commands.", commandName); } catch (Exception ex) { - DebugWriter.WriteDebugStackTrace(ex); - TextWriters.Write(Translate.DoTranslation("Error trying to execute command.") + CharManager.NewLine + Translate.DoTranslation("Error {0}: {1}"), true, KernelColorType.Error, ex.GetType().FullName ?? "", ex.Message); - if (ex is KernelException kex) - UESHVariables.SetVariable("UESHErrorCode", $"{KernelExceptionTools.GetErrorCode(kex)}"); - else - UESHVariables.SetVariable("UESHErrorCode", $"{ex.GetHashCode()}"); + TextWriterRaw.WritePlain("Error trying to execute command." + CharManager.NewLine + "Error {0}: {1}", ex.GetType().FullName ?? "", ex.Message); } } - - // Fire an event of PostExecuteCommand and reset all local variables - var varStoreKeys = varStoreVars.varStoreKeys; - foreach (string varStoreKey in varStoreKeys) - UESHVariables.RemoveVariable(varStoreKey); - foreach (var varStoreKeyOld in oldVarValues) - { - string key = varStoreKeyOld.Item1; - string value = varStoreKeyOld.Item2; - UESHVariables.InitializeVariable(key); - UESHVariables.SetVariable(key, value); - } - EventsManager.FireEvent(EventType.PostExecuteCommand, ShellType, Command); - } - - // Restore console output to its original state if any - if (DriverHandler.CurrentConsoleDriverLocal.DriverName != "Default" && restoreDriver) - { - if (DriverHandler.CurrentConsoleDriverLocal is File writer) - writer.FilterVT = false; - if (DriverHandler.CurrentConsoleDriverLocal is FileSequence writerSeq) - writerSeq.FilterVT = false; - DriverHandler.EndLocalDriver(); } - - // Restore title and cancel possibility state - if (setTitle) - ConsoleMisc.SetTitle(KernelReleaseInfo.ConsoleTitle); - CancellationHandlers.InhibitCancel(); lastCommand = FullCommand; } - /// - /// Gets the shell type name - /// - /// Shell type enumeration - public static string GetShellTypeName(ShellType shellType) => - shellType.ToString(); - - /// - /// Gets the shell information instance - /// - /// Shell type from enum - public static BaseShellInfo GetShellInfo(ShellType shellType) => - GetShellInfo(GetShellTypeName(shellType)); - /// /// Gets the shell information instance /// @@ -659,14 +309,6 @@ public static BaseShellInfo GetShellInfo(ShellType shellType) => public static BaseShellInfo GetShellInfo(string shellType) => AvailableShells.TryGetValue(shellType, out BaseShellInfo? baseShellInfo) ? baseShellInfo : AvailableShells["Shell"]; - /// - /// Starts the shell - /// - /// The shell type - /// Arguments to pass to shell - public static void StartShell(ShellType ShellType, params object[] ShellArgs) => - StartShell(GetShellTypeName(ShellType), ShellArgs); - /// /// Starts the shell /// @@ -674,13 +316,42 @@ public static void StartShell(ShellType ShellType, params object[] ShellArgs) => /// Arguments to pass to shell public static void StartShell(string ShellType, params object[] ShellArgs) { - if (ShellStack.Count >= 1) + int shellCount = ShellStack.Count; + try { - // The shell stack has a mother shell. Start another shell. - StartShellInternal(ShellType, ShellArgs); + // Make a shell executor based on shell type to select a specific executor (if the shell type is not MESH, and if the new shell isn't a mother shell) + // Please note that the remote debug shell is not supported because it works on its own space, so it can't be interfaced using the standard IShell. + var ShellExecute = GetShellExecutor(ShellType) ?? + throw new TerminauxException($"Can't get shell executor for {ShellType}"); + + // Make a new instance of shell information + var ShellCommandThread = RegenerateCommandThread(ShellType); + var ShellInfo = new ShellExecuteInfo(ShellType, ShellExecute, ShellCommandThread); + + // Add a new shell to the shell stack to indicate that we have a new shell (a visitor)! + ShellStack.Add(ShellInfo); + if (!HistoryTools.IsHistoryRegistered(ShellType)) + HistoryTools.LoadFromInstance(new HistoryInfo(ShellType, [])); + + // Reset title in case we're going to another shell + ShellExecute.InitializeShell(ShellArgs); + } + catch (Exception ex) + { + // There is an exception trying to run the shell. Throw the message to the caller. + throw new TerminauxException("Failed trying to initialize shell", ex); + } + finally + { + // There is either an unknown shell error trying to be initialized or a shell has manually set Bail to true prior to exiting, like the JSON shell + // that sets this property when it fails to open the JSON file due to syntax error or something. If we haven't added the shell to the shell stack, + // do nothing. Else, purge that shell with KillShell(). Otherwise, we'll get another shell's commands in the wrong shell and other problems will + // occur until the ghost shell has exited either automatically or manually, so check to see if we have added the newly created shell to the shell + // stack and kill that faulted shell so that we can have the correct shell in the most recent shell, ^1, from the stack. + int newShellCount = ShellStack.Count; + if (newShellCount > shellCount) + KillShell(); } - else - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Shells can't start unless the mother shell has started.")); } /// @@ -688,12 +359,17 @@ public static void StartShell(string ShellType, params object[] ShellArgs) /// public static void KillShell() { - // We must have at least two shells to kill the last shell. Else, we will have zero shells running, making us look like we've logged out! - if (IsOnMotherShell()) - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Can not kill the mother shell!")); - - // Not a mother shell, so bail. - KillShellInternal(); + if (ShellStack.Count >= 1) + { + var shell = ShellStack[ShellStack.Count - 1]; + var shellBase = ShellStack[ShellStack.Count - 1].ShellBase; + if (shellBase is not null) + { + shell.interrupting = true; + shellBase.Bail = true; + } + PurgeShells(); + } } /// @@ -703,13 +379,6 @@ public static void PurgeShells() => // Remove these shells from the stack ShellStack.RemoveAll(x => x.ShellBase?.Bail ?? true); - /// - /// Gets the shell executor based on the shell type - /// - /// The requested shell type - public static BaseShell? GetShellExecutor(ShellType ShellType) => - GetShellExecutor(GetShellTypeName(ShellType)); - /// /// Gets the shell executor based on the shell type /// @@ -718,7 +387,7 @@ public static void PurgeShells() => GetShellInfo(ShellType).ShellBase; /// - /// Registers the custom shell. Should be called when mods start up. + /// Registers the custom shell /// /// The shell type /// The shell type information @@ -727,14 +396,13 @@ public static void RegisterShell(string ShellType, BaseShellInfo ShellTypeInfo) if (!ShellTypeExists(ShellType)) { // First, add the shell - availableCustomShells.Add(ShellType, ShellTypeInfo); + availableShells.Add(ShellType, ShellTypeInfo); // Then, add the default preset if the current preset is not found if (PromptPresetManager.CurrentPresets.ContainsKey(ShellType)) return; // Rare state. - DebugWriter.WriteDebug(DebugLevel.I, "Reached rare state or unconfigurable shell."); var presets = ShellTypeInfo.ShellPresets; var basePreset = new PromptPresetBase(); if (presets is not null) @@ -754,29 +422,21 @@ public static void RegisterShell(string ShellType, BaseShellInfo ShellTypeInfo) } /// - /// Unregisters the custom shell. Should be called when mods shut down. + /// Unregisters the custom shell /// /// The shell type public static void UnregisterShell(string ShellType) { - if (!IsShellBuiltin(ShellType)) + if (ShellTypeExists(ShellType)) { // First, remove the shell - availableCustomShells.Remove(ShellType); + availableShells.Remove(ShellType); // Then, remove the preset PromptPresetManager.CurrentPresets.Remove(ShellType); } } - /// - /// Is the shell pre-defined in Nitrocid KS? - /// - /// Shell type - /// If available in ShellType, then it's a built-in shell, thus returning true. Otherwise, false for custom shells. - public static bool IsShellBuiltin(string ShellType) => - availableShells.ContainsKey(ShellType); - /// /// Does the shell exist? /// @@ -785,234 +445,10 @@ public static bool IsShellBuiltin(string ShellType) => public static bool ShellTypeExists(string ShellType) => AvailableShells.ContainsKey(ShellType); - /// - /// Is the current shell a mother shell? - /// - /// True if the shell stack is at most one shell. False if running in the second shell or higher. - public static bool IsOnMotherShell() => - ShellStack.Count < 2; - - /// - /// Registers the addon shell. Should be called when addons start up. - /// - /// The shell type - /// The shell type information - internal static void RegisterAddonShell(string ShellType, BaseShellInfo ShellTypeInfo) - { - if (!ShellTypeExists(ShellType)) - { - // First, add the shell - availableShells.Add(ShellType, ShellTypeInfo); - - // Then, add the default preset if the current preset is not found - if (PromptPresetManager.CurrentPresets.ContainsKey(ShellType)) - return; - - // Rare state. - DebugWriter.WriteDebug(DebugLevel.I, "Reached rare state or unconfigurable shell."); - var presets = ShellTypeInfo.ShellPresets; - var basePreset = new PromptPresetBase(); - if (presets is not null) - { - // Add a default preset - if (presets.ContainsKey("Default")) - PromptPresetManager.CurrentPresets.Add(ShellType, "Default"); - else - PromptPresetManager.CurrentPresets.Add(ShellType, basePreset.PresetName); - } - else - { - // Make a base shell preset and set it as default. - PromptPresetManager.CurrentPresets.Add(ShellType, basePreset.PresetName); - } - } - } - - /// - /// Unregisters the addon shell. Should be called when addons shut down. - /// - /// The shell type - internal static void UnregisterAddonShell(string ShellType) - { - if (IsShellBuiltin(ShellType)) + internal static Thread RegenerateCommandThread(string ShellType) => + new((cmdThreadParams) => CommandExecutor.ExecuteCommand((CommandExecutorParameters?)cmdThreadParams)) { - // First, remove the shell - availableShells.Remove(ShellType); - - // Then, remove the preset - PromptPresetManager.CurrentPresets.Remove(ShellType); - } - } - - internal static void SaveHistories() - { - foreach (string history in histories.Keys) - { - if (HistoryTools.IsHistoryRegistered(history)) - histories[history] = [.. HistoryTools.GetHistoryEntries(history)]; - } - FileIO.WriteAllText(PathsManagement.ShellHistoriesPath, JsonConvert.SerializeObject(histories, Formatting.Indented)); - } - - internal static void LoadHistories() - { - string path = PathsManagement.ShellHistoriesPath; - if (!Checking.FileExists(path)) - return; - histories = JsonConvert.DeserializeObject>>(FileIO.ReadAllText(path)) ?? []; - foreach (string history in histories.Keys) - { - if (!HistoryTools.IsHistoryRegistered(history)) - HistoryTools.LoadFromInstance(new HistoryInfo(history, histories[history])); - else - HistoryTools.Switch(history, [.. histories[history]]); - } - } - - /// - /// Force starts the shell - /// - /// The shell type - /// Arguments to pass to shell - internal static void StartShellInternal(ShellType ShellType, params object[] ShellArgs) => - StartShellInternal(GetShellTypeName(ShellType), ShellArgs); - - /// - /// Force starts the shell - /// - /// The shell type - /// Arguments to pass to shell - internal static void StartShellInternal(string ShellType, params object[] ShellArgs) - { - int shellCount = ShellStack.Count; - try - { - // Make a shell executor based on shell type to select a specific executor (if the shell type is not UESH, and if the new shell isn't a mother shell) - // Please note that the remote debug shell is not supported because it works on its own space, so it can't be interfaced using the standard IShell. - var ShellExecute = GetShellExecutor(ShellType) ?? - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Can't get shell executor for") + $" {ShellType}"); - - // Make a new instance of shell information - var ShellCommandThread = new KernelThread($"{ShellType} Command Thread", false, (cmdThreadParams) => CommandExecutor.ExecuteCommand((CommandExecutorParameters?)cmdThreadParams)); - var ShellInfo = new ShellExecuteInfo(ShellType, ShellExecute, ShellCommandThread); - - // Add a new shell to the shell stack to indicate that we have a new shell (a visitor)! - ShellStack.Add(ShellInfo); - if (!HistoryTools.IsHistoryRegistered(ShellType)) - HistoryTools.LoadFromInstance(new HistoryInfo(ShellType, [])); - - // Reset title in case we're going to another shell - ConsoleMisc.SetTitle(KernelReleaseInfo.ConsoleTitle); - ShellExecute.InitializeShell(ShellArgs); - } - catch (Exception ex) - { - // There is an exception trying to run the shell. Throw the message to the debugger and to the caller. - DebugWriter.WriteDebug(DebugLevel.E, "Failed initializing shell!!! Type: {0}, Message: {1}", ShellType, ex.Message); - DebugWriter.WriteDebug(DebugLevel.E, "Additional info: Args: {0} [{1}], Shell Stack: {2} shells, shellCount: {3} shells", ShellArgs.Length, string.Join(", ", ShellArgs), ShellStack.Count, shellCount); - DebugWriter.WriteDebug(DebugLevel.E, "This shell needs to be killed in order for the shell manager to proceed. Passing exception to caller..."); - DebugWriter.WriteDebugStackTrace(ex); - DebugWriter.WriteDebug(DebugLevel.E, "If you don't see \"Purge\" from {0} after few lines, this indicates that we're in a seriously corrupted state.", nameof(StartShellInternal)); - throw new KernelException(KernelExceptionType.ShellOperation, Translate.DoTranslation("Failed trying to initialize shell"), ex); - } - finally - { - // There is either an unknown shell error trying to be initialized or a shell has manually set Bail to true prior to exiting, like the JSON shell - // that sets this property when it fails to open the JSON file due to syntax error or something. If we haven't added the shell to the shell stack, - // do nothing. Else, purge that shell with KillShell(). Otherwise, we'll get another shell's commands in the wrong shell and other problems will - // occur until the ghost shell has exited either automatically or manually, so check to see if we have added the newly created shell to the shell - // stack and kill that faulted shell so that we can have the correct shell in the most recent shell, ^1, from the stack. - int newShellCount = ShellStack.Count; - DebugWriter.WriteDebug(DebugLevel.I, "Purge: newShellCount: {0} shells, shellCount: {1} shells", newShellCount, shellCount); - if (newShellCount > shellCount) - KillShellInternal(); - - // Terminaux has introduced recent changes surrounding the history feature of the reader that allows it to save and load custom histories, so we - // need to make use of it to be able to save histories in one file. - SaveHistories(); - } - } - - /// - /// Force kills the last running shell - /// - internal static void KillShellInternal() - { - if (ShellStack.Count >= 1) - { - var shellBase = ShellStack[^1].ShellBase; - if (shellBase is not null) - shellBase.Bail = true; - PurgeShells(); - } - } - - /// - /// Kills all the shells - /// - internal static void KillAllShells() - { - for (int i = ShellStack.Count - 1; i >= 0; i--) - { - var shellBase = ShellStack[i].ShellBase; - if (shellBase is not null) - shellBase.Bail = true; - } - PurgeShells(); - } - - /// - /// Initializes the redirection - /// - private static string InitializeRedirection(string Command) - { - // If requested command has output redirection sign after arguments, remove it from final command string and set output to that file - string RedirectionPattern = /*lang=regex*/ @"(?:( (?:>>|>>>) )(.+?))+$"; - if (RegexpTools.IsMatch(Command, RedirectionPattern)) - { - var outputMatch = Regex.Match(Command, RedirectionPattern); - var outputFiles = outputMatch.Groups[2].Captures.Select((cap) => cap.Value).ToArray(); - var outputFileModes = outputMatch.Groups[1].Captures.Select((cap) => cap.Value).ToArray(); - List filePaths = []; - for (int i = 0; i < outputFiles.Length; i++) - { - string outputFile = outputFiles[i]; - bool isOverwrite = outputFileModes[i] != " >>> "; - string OutputFilePath = FilesystemTools.NeutralizePath(outputFile); - DebugWriter.WriteDebug(DebugLevel.I, "Output redirection found for file {1} with overwrite mode [{0}].", isOverwrite, OutputFilePath); - if (isOverwrite) - Manipulation.ClearFile(OutputFilePath); - filePaths.Add(OutputFilePath); - } - DriverHandler.BeginLocalDriver("FileSequence"); - ((FileSequence)DriverHandler.CurrentConsoleDriverLocal).PathsToWrite = [.. filePaths]; - ((FileSequence)DriverHandler.CurrentConsoleDriverLocal).FilterVT = true; - Command = Command.RemoveSuffix(outputMatch.Value); - } - else if (Command.EndsWith(" |SILENT|")) - { - DebugWriter.WriteDebug(DebugLevel.I, "Silence found. Redirecting to null writer..."); - DriverHandler.BeginLocalDriver("Null"); - Command = Command.RemoveSuffix(" |SILENT|"); - } - - return Command; - } - - /// - /// Initializes the optional file path writer - /// - private static void InitializeOutputPathWriter(string OutputPath) - { - // Checks to see if the user provided optional path - if (!string.IsNullOrWhiteSpace(OutputPath)) - { - DebugWriter.WriteDebug(DebugLevel.I, "Optional output redirection found using OutputPath ({0}).", OutputPath); - OutputPath = FilesystemTools.NeutralizePath(OutputPath); - DriverHandler.BeginLocalDriver("File"); - ((File)DriverHandler.CurrentConsoleDriverLocal).PathToWrite = OutputPath; - } - } - + Name = $"{ShellType} Command Thread" + }; } } diff --git a/Terminaux/Shell/Shells/ShellType.cs b/Terminaux/Shell/Shells/ShellType.cs deleted file mode 100644 index f5910b8f7..000000000 --- a/Terminaux/Shell/Shells/ShellType.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -namespace Terminaux.Shell.Shells -{ - /// - /// Shell type enumeration - /// - public enum ShellType - { - /// - /// Normal UESH shell - /// - Shell, - /// - /// Text shell - /// - TextShell, - /// - /// Hex shell - /// - HexShell, - /// - /// Kernel administration shell - /// - AdminShell, - /// - /// Kernel debug shell - /// - DebugShell - } -} diff --git a/Terminaux/Shell/Shells/Unified/Exec.cs b/Terminaux/Shell/Shells/Unified/Exec.cs deleted file mode 100644 index 6b7e0ab22..000000000 --- a/Terminaux/Shell/Shells/Unified/Exec.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using System.Linq; -using Terminaux.Shell.Commands; -using Terminaux.Shell.Commands.ProcessExecution; -using Terminaux.Shell.Switches; - -namespace Terminaux.Shell.Shells.Unified -{ - /// - /// Executes an external command - /// - /// - /// If you need to take a look at a process output, it's wise to use this command. - /// - class ExecUnifiedCommand : BaseCommand, ICommand - { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - string command = parameters.ArgumentsList[0]; - string arguments = string.Join(' ', parameters.ArgumentsList.Skip(1).ToArray()); - if (SwitchManager.ContainsSwitch(parameters.SwitchesList, "-forked")) - { - ProcessExecutor.ExecuteProcessForked(command, arguments); - return 0; - } - return ProcessExecutor.ExecuteProcess(command, arguments); - } - - } -} diff --git a/Terminaux/Shell/Shells/Unified/Exit.cs b/Terminaux/Shell/Shells/Unified/Exit.cs index 2566d0f11..7d95fbd63 100644 --- a/Terminaux/Shell/Shells/Unified/Exit.cs +++ b/Terminaux/Shell/Shells/Unified/Exit.cs @@ -17,9 +17,7 @@ // along with this program. If not, see . // -using Nitrocid.Kernel.Configuration; using Terminaux.Shell.Commands; -using Terminaux.Shell.Shells; namespace Terminaux.Shell.Shells.Unified { @@ -27,21 +25,11 @@ namespace Terminaux.Shell.Shells.Unified /// Exits the subshell /// /// - /// If the UESH shell is a subshell, you can exit it. However, you can't use this command to log out of your account, because it can't exit the mother shell. The only to exit it is to use the logout command. + /// If the MESH shell is a subshell, you can exit it. However, you can't use this command to log out of your account, because it can't exit the mother shell. The only to exit it is to use the logout command. /// class ExitUnifiedCommand : BaseCommand, ICommand { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - if (ShellManager.IsOnMotherShell() && Config.MainConfig.EnableHomepage) - { - // User requested to go back to The Nitrocid Homepage - ShellManager.KillShellInternal(); - return 0; - } + public override void Execute(CommandParameters parameters) => ShellManager.KillShell(); - return 0; - } } } diff --git a/Terminaux/Shell/Shells/Unified/FindCmds.cs b/Terminaux/Shell/Shells/Unified/FindCmds.cs index 5d9daff3f..2ed6643a4 100644 --- a/Terminaux/Shell/Shells/Unified/FindCmds.cs +++ b/Terminaux/Shell/Shells/Unified/FindCmds.cs @@ -17,11 +17,8 @@ // along with this program. If not, see . // -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Languages; using Terminaux.Shell.Commands; -using Terminaux.Shell.Shells; +using Terminaux.Writer.ConsoleWriters; namespace Terminaux.Shell.Shells.Unified { @@ -34,17 +31,16 @@ namespace Terminaux.Shell.Shells.Unified class FindCmdsUnifiedCommand : BaseCommand, ICommand { - public override int Execute(CommandParameters parameters, ref string variableValue) + public override void Execute(CommandParameters parameters) { var commands = CommandManager.FindCommands(parameters.ArgumentsList[0], ShellManager.CurrentShellType); foreach (var command in commands) { - TextWriters.Write("- ", false, KernelColorType.ListEntry); - TextWriters.Write(command.Command, KernelColorType.ListValue); + TextWriterRaw.WritePlain("- ", false); + TextWriterRaw.WritePlain(command.Command); } if (commands.Length == 0) - TextWriters.Write(Translate.DoTranslation("No commands found."), KernelColorType.Error); - return 0; + TextWriterRaw.WritePlain("No commands found."); } } diff --git a/Terminaux/Shell/Shells/Unified/Help.cs b/Terminaux/Shell/Shells/Unified/Help.cs index cecee3d6e..c835efc43 100644 --- a/Terminaux/Shell/Shells/Unified/Help.cs +++ b/Terminaux/Shell/Shells/Unified/Help.cs @@ -32,10 +32,11 @@ namespace Terminaux.Shell.Shells.Unified class HelpUnifiedCommand : BaseCommand, ICommand { - public override int Execute(CommandParameters parameters, ref string variableValue) + public override void Execute(CommandParameters parameters) { // Determine which type to show bool useSimplified = SwitchManager.ContainsSwitch(parameters.SwitchesList, "-simplified"); + bool showCount = SwitchManager.ContainsSwitch(parameters.SwitchesList, "-count"); bool showGeneral = parameters.SwitchesList.Length == 0 || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-general") || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-all"); bool showMod = parameters.SwitchesList.Length > 0 && @@ -44,15 +45,14 @@ public override int Execute(CommandParameters parameters, ref string variableVal (SwitchManager.ContainsSwitch(parameters.SwitchesList, "-alias") || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-all")); bool showUnified = parameters.SwitchesList.Length > 0 && (SwitchManager.ContainsSwitch(parameters.SwitchesList, "-unified") || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-all")); - bool showAddon = parameters.SwitchesList.Length > 0 && - (SwitchManager.ContainsSwitch(parameters.SwitchesList, "-addon") || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-all")); + bool showExtra = parameters.SwitchesList.Length > 0 && + (SwitchManager.ContainsSwitch(parameters.SwitchesList, "-extra") || SwitchManager.ContainsSwitch(parameters.SwitchesList, "-all")); // Now, show the help if (string.IsNullOrWhiteSpace(parameters.ArgumentsText)) - HelpPrint.ShowHelpExtended(useSimplified, showGeneral, showMod, showAlias, showUnified, showAddon); + HelpPrint.ShowHelpExtended(useSimplified, showGeneral, showAlias, showUnified, showExtra, showCount); else HelpPrint.ShowHelpExtended(parameters.ArgumentsList[0], useSimplified); - return 0; } } diff --git a/Terminaux/Shell/Shells/Unified/LoadHistories.cs b/Terminaux/Shell/Shells/Unified/LoadHistories.cs deleted file mode 100644 index 052117993..000000000 --- a/Terminaux/Shell/Shells/Unified/LoadHistories.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Shell.Commands; -using Terminaux.Shell.Shells; - -namespace Terminaux.Shell.Shells.Unified -{ - /// - /// Loads shell histories - /// - /// - /// You can use this command to load shell histories. - /// - class LoadHistoriesUnifiedCommand : BaseCommand, ICommand - { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - ShellManager.LoadHistories(); - return 0; - } - - } -} diff --git a/Terminaux/Shell/Shells/Unified/Presets.cs b/Terminaux/Shell/Shells/Unified/Presets.cs index f3b7dff51..7e856dc9f 100644 --- a/Terminaux/Shell/Shells/Unified/Presets.cs +++ b/Terminaux/Shell/Shells/Unified/Presets.cs @@ -30,11 +30,7 @@ namespace Terminaux.Shell.Shells.Unified /// class PresetsUnifiedCommand : BaseCommand, ICommand { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { + public override void Execute(CommandParameters parameters) => PromptPresetManager.PromptForPresets(); - return 0; - } } } diff --git a/Terminaux/Shell/Shells/Unified/Repeat.cs b/Terminaux/Shell/Shells/Unified/Repeat.cs deleted file mode 100644 index c83c301b3..000000000 --- a/Terminaux/Shell/Shells/Unified/Repeat.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Kernel.Debugging; -using Nitrocid.Kernel.Threading; -using Nitrocid.Languages; -using Terminaux.Shell.Arguments; -using Terminaux.Shell.Commands; -using Terminaux.Shell.Shells; - -namespace Terminaux.Shell.Shells.Unified -{ - /// - /// Repeats a command - /// - /// - /// You can repeat either the last command entered or the specified command. - /// - class RepeatUnifiedCommand : BaseCommand, ICommand - { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - string timesString = parameters.ArgumentsList[0]; - bool valid = uint.TryParse(timesString, out uint times); - if (!valid) - { - TextWriters.Write(Translate.DoTranslation("Invalid number of times."), true, KernelColorType.Error); - return 18; - } - - // Get the command to be executed - string lastCommand = ShellManager.lastCommand; - if (parameters.ArgumentsList.Length > 1) - lastCommand = parameters.ArgumentsList[1]; - - // Check to see if we're trying to call repeat - var argumentInfo = ArgumentsParser.ParseShellCommandArguments(lastCommand, ShellManager.CurrentShellType).total[0]; - if (argumentInfo.Command == "repeat") - { - TextWriters.Write(Translate.DoTranslation("Can't repeat self."), true, KernelColorType.Error); - return 19; - } - - // First, initialize the alternative command thread - var AltThreads = ShellManager.ShellStack[^1].AltCommandThreads; - if (AltThreads.Count == 0 || AltThreads[^1].IsAlive) - { - DebugWriter.WriteDebug(DebugLevel.I, "Making alt thread for repeated command {0}...", lastCommand); - var WrappedCommand = new KernelThread($"Repeated Shell Command Thread", false, (cmdThreadParams) => CommandExecutor.ExecuteCommand((CommandExecutorParameters?)cmdThreadParams)); - ShellManager.ShellStack[^1].AltCommandThreads.Add(WrappedCommand); - } - - // Now, execute the command n times - for (uint i = 1; i <= times; i++) - ShellManager.GetLine(lastCommand); - return 0; - } - - } -} diff --git a/Terminaux/Shell/Shells/Unified/Tip.cs b/Terminaux/Shell/Shells/Unified/Tip.cs deleted file mode 100644 index 0165d1ccf..000000000 --- a/Terminaux/Shell/Shells/Unified/Tip.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Nitrocid.ConsoleBase.Colors; -using Nitrocid.ConsoleBase.Writers; -using Nitrocid.Languages; -using Nitrocid.ConsoleBase.Writers.MiscWriters; -using Terminaux.Shell.Commands; - -namespace Terminaux.Shell.Shells.Unified -{ - /// - /// Gets a random tip - /// - /// - /// You can learn more about what the kernel can do using this command to get a random tip. - /// - class TipUnifiedCommand : BaseCommand, ICommand - { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - string tip = WelcomeMessage.GetRandomTip(); - TextWriters.Write( - "* " + Translate.DoTranslation("Pro tip: Did you know") + " " + tip, true, KernelColorType.Tip); - return 0; - } - - } -} diff --git a/Terminaux/Shell/Shells/Unified/Wrap.cs b/Terminaux/Shell/Shells/Unified/Wrap.cs deleted file mode 100644 index d03d00b3a..000000000 --- a/Terminaux/Shell/Shells/Unified/Wrap.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Terminaux Copyright (C) 2023-2024 Aptivi -// -// This file is part of Terminaux -// -// Terminaux is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Terminaux is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY, without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -using Terminaux.Writer.ConsoleWriters; -using Nitrocid.Languages; -using Terminaux.Shell.Shells; -using Terminaux.Shell.Commands; - -namespace Terminaux.Shell.Shells.Unified -{ - /// - /// Wraps a command - /// - /// - /// You can wrap a command so it stops outputting until you press a key if the console has printed lines that exceed the console window height. Only the commands that are explicitly set to be wrappable can be used with this command. - /// - class WrapUnifiedCommand : BaseCommand, ICommand - { - - public override int Execute(CommandParameters parameters, ref string variableValue) - { - CommandExecutor.ExecuteCommandWrapped(parameters.ArgumentsText); - return 0; - } - - public override void HelpHelper() - { - // Print the wrappable commands along with help description - var currentShell = ShellManager.ShellStack[^1]; - var currentType = currentShell.ShellType; - var WrappableCmds = CommandExecutor.GetWrappableCommands(currentType); - TextWriterColor.Write(Translate.DoTranslation("Wrappable commands:")); - ListWriterColor.WriteList(WrappableCmds); - } - - } -} diff --git a/Terminaux/Shell/Switches/SwitchInfo.cs b/Terminaux/Shell/Switches/SwitchInfo.cs index 885897b7e..85be3666b 100644 --- a/Terminaux/Shell/Switches/SwitchInfo.cs +++ b/Terminaux/Shell/Switches/SwitchInfo.cs @@ -37,8 +37,6 @@ // along with this program. If not, see . // -using Nitrocid.Languages; - namespace Terminaux.Shell.Switches { /// @@ -52,7 +50,7 @@ public class SwitchInfo /// public string SwitchName { get; private set; } /// - /// The untranslated help definition of this switch. Translated by + /// The help definition of this switch /// public string HelpDefinition { get; private set; } /// @@ -140,11 +138,5 @@ public SwitchInfo(string Switch, string HelpDefinition, bool IsRequired = false, IsNumeric = IsNumeric, }; } - - /// - /// Gets the translated version of help entry (KS built-in switches only) - /// - public string GetTranslatedHelpEntry() => - Translate.DoTranslation(HelpDefinition); } } diff --git a/Terminaux/Shell/Switches/SwitchManager.cs b/Terminaux/Shell/Switches/SwitchManager.cs index be051bfb9..3948c3a92 100644 --- a/Terminaux/Shell/Switches/SwitchManager.cs +++ b/Terminaux/Shell/Switches/SwitchManager.cs @@ -55,8 +55,8 @@ public static class SwitchManager else { // Get switch name and value. If the equal sign is at the end, the value is an empty value. - switchName = @switch[..switchIndex]; - switchValue = switchIndex != @switch.Length - 1 ? @switch[(switchIndex + 1)..] : ""; + switchName = @switch.Substring(0, switchIndex); + switchValue = switchIndex != @switch.Length - 1 ? @switch.Substring(switchIndex + 1) : ""; } // Add the values to the list diff --git a/Terminaux/Terminaux.csproj b/Terminaux/Terminaux.csproj index 426a6a22e..fc31c2268 100644 --- a/Terminaux/Terminaux.csproj +++ b/Terminaux/Terminaux.csproj @@ -48,8 +48,8 @@ - - + +