Updated with main.

This commit is contained in:
That_One_Nerd 2023-04-25 17:30:49 -04:00
commit 3f5319adc0
8 changed files with 352 additions and 13 deletions

View File

@ -1,12 +1,14 @@
global using Nerd_STF.Mathematics; global using Nerd_STF.Mathematics;
global using Newtonsoft.Json;
global using SharpCompress.Archives.Rar; global using SharpCompress.Archives.Rar;
global using SharpCompress.Archives.SevenZip; global using SharpCompress.Archives.SevenZip;
global using SharpCompress.Readers; global using SharpCompress.Readers;
global using SrcMod.Shell;
global using SrcMod.Shell.Interop; global using SrcMod.Shell.Interop;
global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.Modules.ObjectModels;
global using SrcMod.Shell.ObjectModels;
global using System; global using System;
global using System.Collections.Generic; global using System.Collections.Generic;
global using System.ComponentModel;
global using System.Diagnostics; global using System.Diagnostics;
global using System.Formats.Tar; global using System.Formats.Tar;
global using System.IO; global using System.IO;

View File

@ -0,0 +1,194 @@
namespace SrcMod.Shell.Modules;
[Module("config")]
public static class ConfigModule
{
[Command("display")]
[Command("list")]
public static void DisplayConfig(ConfigDisplayMode mode = ConfigDisplayMode.All)
{
switch (mode)
{
case ConfigDisplayMode.Raw:
DisplayConfigRaw();
break;
case ConfigDisplayMode.All:
DisplayConfigAll();
break;
case ConfigDisplayMode.GameDirectories:
DisplayConfigGameDirectories();
break;
case ConfigDisplayMode.RunUnsafeCommands:
DisplayConfigUnsafeCommands();
break;
}
}
[Command("add")]
[Command("append")]
public static void AppendConfigVariable(string name, string value)
{
Config config = Config.LoadedConfig;
switch (name.Trim().ToLower())
{
case "gamedirectories":
config.GameDirectories = config.GameDirectories.Append(value).ToArray();
break;
case "rununsafecommands":
throw new($"The config variable \"{name}\" is a single variable and cannot be appended to.");
default: throw new($"Unknown config variable \"{name}\"");
}
Config.LoadedConfig = config;
}
[Command("delete")]
[Command("remove")]
public static void RemoveConfigVariable(string name, string value)
{
Config config = Config.LoadedConfig;
switch (name.Trim().ToLower())
{
case "gamedirectories":
config.GameDirectories = config.GameDirectories
.Where(x => x.Trim().ToLower() != value.Trim().ToLower())
.ToArray();
break;
case "rununsafecommands":
throw new($"The config variable \"{name}\" is a single variable and cannot be appended to.");
default: throw new($"Unknown config variable \"{name}\"");
}
Config.LoadedConfig = config;
}
[Command("reset")]
public static void ResetConfig(string name = "all")
{
Config config = Config.LoadedConfig;
switch (name.Trim().ToLower())
{
case "gamedirectories":
config.GameDirectories = Config.Defaults.GameDirectories;
break;
case "rununsafecommands":
config.RunUnsafeCommands = Config.Defaults.RunUnsafeCommands;
break;
case "all":
config = Config.Defaults;
break;
default: throw new($"Unknown config variable \"{name}\"");
}
Config.LoadedConfig = config;
}
[Command("set")]
public static void SetConfigVariable(string name, string value)
{
Config config = Config.LoadedConfig;
switch (name.Trim().ToLower())
{
case "gamedirectories":
throw new($"The config variable \"{name}\" is a list and must be added or removed to.");
case "rununsafecommands":
if (int.TryParse(value, out int intRes))
{
AskMode mode = (AskMode)intRes;
if (!Enum.IsDefined(mode)) throw new($"(AskMode){value} is not a valid AskMode.");
config.RunUnsafeCommands = mode;
}
else if (Enum.TryParse(value, true, out AskMode modeRes))
{
if (!Enum.IsDefined(modeRes)) throw new($"\"{value}\" is not a valid AskMode.");
config.RunUnsafeCommands = modeRes;
}
else throw new($"\"{value}\" is not a valid AskMode.");
break;
default: throw new($"Unknown config variable \"{name}\"");
}
Config.LoadedConfig = config;
}
private static void DisplayConfigAll()
{
DisplayConfigGameDirectories();
DisplayConfigUnsafeCommands();
}
private static void DisplayConfigRaw()
{
// This is definitely a bit inefficient, but shouldn't be too much of an issue.
MemoryStream ms = new();
StreamWriter writer = new(ms, leaveOpen: true);
JsonTextWriter jsonWriter = new(writer);
Serializer.Serialize(jsonWriter, Config.LoadedConfig);
jsonWriter.Close();
writer.Close();
ms.Position = 0;
StreamReader reader = new(ms);
string msg = reader.ReadToEnd();
Write(msg);
reader.Close();
ms.Close();
}
private static void DisplayConfigGameDirectories()
{
Write("Steam Game Directories: ", null, false);
if (Config.LoadedConfig.GameDirectories is null || Config.LoadedConfig.GameDirectories.Length <= 0)
Write("None", ConsoleColor.DarkGray);
else
{
Write("[", ConsoleColor.DarkGray);
for (int i = 0; i < Config.LoadedConfig.GameDirectories.Length; i++)
{
Write(" \"", ConsoleColor.DarkGray, false);
Write(Config.LoadedConfig.GameDirectories[i], ConsoleColor.White, false);
if (i < Config.LoadedConfig.GameDirectories.Length - 1) Write("\",", ConsoleColor.DarkGray);
else Write("\"", ConsoleColor.DarkGray);
}
Write("]", ConsoleColor.DarkGray);
}
}
private static void DisplayConfigUnsafeCommands()
{
Write("Run Unsafe Commands: ", null, false);
ConsoleColor color = Config.LoadedConfig.RunUnsafeCommands switch
{
AskMode.Never => ConsoleColor.Red,
AskMode.Always => ConsoleColor.Green,
AskMode.Ask or _ => ConsoleColor.DarkGray
};
Write(Config.LoadedConfig.RunUnsafeCommands, color);
}
public enum ConfigDisplayMode
{
Raw,
All,
GameDirectories,
RunUnsafeCommands
}
}

View File

@ -0,0 +1,8 @@
namespace SrcMod.Shell.ObjectModels;
public enum AskMode : sbyte
{
Never = -1,
Ask = 0,
Always = 1
}

View File

@ -0,0 +1,86 @@
namespace SrcMod.Shell.ObjectModels;
public struct Config
{
public const string FilePath = "config.json";
public static readonly Config Defaults;
public static Config LoadedConfig
{
get => p_applied;
set
{
p_applied = value;
p_changes = p_applied.GetChanges(Defaults);
}
}
private static Config p_applied;
private static ConfigChanges? p_changes;
static Config()
{
Defaults = new()
{
GameDirectories = Array.Empty<string>(),
RunUnsafeCommands = AskMode.Ask
};
}
public string[] GameDirectories;
public AskMode RunUnsafeCommands;
public Config ApplyChanges(ConfigChanges changes) => this with
{
GameDirectories = GameDirectories.Union(changes.GameDirectories ?? Array.Empty<string>()).ToArray(),
RunUnsafeCommands = changes.RunUnsafeCommands ?? RunUnsafeCommands
};
public ConfigChanges GetChanges(Config? baseConfig = null)
{
Config reference = baseConfig ?? Defaults;
ConfigChanges changes = new()
{
GameDirectories = reference.GameDirectories == GameDirectories ? null :
GameDirectories.Where(x => !reference.GameDirectories.Contains(x)).ToArray(),
RunUnsafeCommands = reference.RunUnsafeCommands == RunUnsafeCommands ? null : RunUnsafeCommands
};
return changes;
}
public static void LoadConfig(string basePath)
{
string fullPath = Path.Combine(basePath, FilePath);
if (!File.Exists(fullPath))
{
p_applied = Defaults;
p_changes = null;
return;
}
StreamReader reader = new(fullPath);
JsonTextReader jsonReader = new(reader);
p_changes = Serializer.Deserialize<ConfigChanges?>(jsonReader);
jsonReader.Close();
reader.Close();
p_applied = p_changes is null ? Defaults : Defaults.ApplyChanges(p_changes.Value);
}
public static void SaveConfig(string basePath)
{
string fullPath = Path.Combine(basePath, FilePath);
if (p_changes is null || !p_changes.Value.HasChange)
{
if (File.Exists(fullPath)) File.Delete(fullPath);
return;
}
StreamWriter writer = new(fullPath);
JsonTextWriter jsonWriter = new(writer);
Serializer.Serialize(jsonWriter, p_changes);
jsonWriter.Close();
writer.Close();
}
}

View File

@ -0,0 +1,10 @@
namespace SrcMod.Shell.ObjectModels;
public record struct ConfigChanges
{
[JsonIgnore]
public bool HasChange => GameDirectories is not null || RunUnsafeCommands is not null;
public string[]? GameDirectories;
public AskMode? RunUnsafeCommands;
}

View File

@ -1,12 +1,10 @@
using System.ComponentModel; namespace SrcMod.Shell;
namespace SrcMod.Shell;
public class Shell public class Shell
{ {
public const string Author = "That_One_Nerd"; public const string Author = "That_One_Nerd";
public const string Name = "SrcMod"; public const string Name = "SrcMod";
public const string Version = "Alpha 0.3.2"; public const string Version = "Alpha 0.3.3";
public readonly string? ShellDirectory; public readonly string? ShellDirectory;
@ -50,6 +48,10 @@ public class Shell
WorkingDirectory = Directory.GetCurrentDirectory(); WorkingDirectory = Directory.GetCurrentDirectory();
// Load config.
if (ShellDirectory is null) Write("[WARNING] Could not load config from shell location. Defaults will be used.");
else Config.LoadConfig(ShellDirectory);
// Load modules and commands. // Load modules and commands.
List<Assembly?> possibleAsms = new() List<Assembly?> possibleAsms = new()
{ {
@ -274,6 +276,9 @@ public class Shell
activeCommand = null; activeCommand = null;
} }
if (ShellDirectory is null) Write("[WARNING] Could not save config to shell location. Any changes will be ignored.");
else Config.SaveConfig(ShellDirectory);
ReloadDirectoryInfo(); ReloadDirectoryInfo();
return; return;
} }

View File

@ -13,6 +13,7 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ApplicationIcon>Logo.ico</ApplicationIcon> <ApplicationIcon>Logo.ico</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWin32Manifest>true</NoWin32Manifest>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -31,6 +32,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Nerd_STF" Version="2.3.2" /> <PackageReference Include="Nerd_STF" Version="2.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SharpCompress" Version="0.33.0" /> <PackageReference Include="SharpCompress" Version="0.33.0" />
</ItemGroup> </ItemGroup>

View File

@ -2,6 +2,17 @@
public static class Tools public static class Tools
{ {
public static JsonSerializer Serializer { get; private set; }
static Tools()
{
Serializer = JsonSerializer.Create(new()
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
});
}
public static void DisplayWithPages(IEnumerable<string> lines, ConsoleColor? color = null) public static void DisplayWithPages(IEnumerable<string> lines, ConsoleColor? color = null)
{ {
int written = 0; int written = 0;
@ -82,15 +93,36 @@ public static class Tools
public static bool ValidateUnsafe() public static bool ValidateUnsafe()
{ {
Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false); switch (Config.LoadedConfig.RunUnsafeCommands)
{
case AskMode.Always:
Write("[INFO] The shell has been configured to always run unsafe commands. " +
"This can be changed in the config.", ConsoleColor.DarkGray);
return true;
Console.ForegroundColor = ConsoleColor.Yellow; case AskMode.Never:
Console.CursorVisible = true; Write("[ERROR] The shell has been configured to never run unsafe commands. " +
string result = Console.ReadLine()!.Trim().ToLower(); "This can be changed in the config.", ConsoleColor.Red);
Console.CursorVisible = false; return false;
Console.ResetColor();
return result == "y" || result == "yes" || result == "t" || case AskMode.Ask or _:
result == "true" || result == "p" || result == "proceed"; Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false);
Int2 start = (Console.CursorLeft, Console.CursorTop);
Write("\nTip: You can disable this dialog in the config.", ConsoleColor.DarkGray);
int finish = Console.CursorTop;
Console.SetCursorPosition(start.x, start.y);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.CursorVisible = true;
string result = Console.ReadLine()!.Trim().ToLower();
Console.CursorVisible = false;
Console.ResetColor();
Console.SetCursorPosition(0, finish);
return result == "y" || result == "yes" || result == "t" ||
result == "true" || result == "p" || result == "proceed";
}
} }
} }