From 3789492de34995a4e7aeac8ccbe1304e9379c5ff Mon Sep 17 00:00:00 2001 From: Jacob Schmidt Date: Fri, 27 Feb 2026 19:52:27 -0600 Subject: [PATCH] Refactor DevTool constructors and include WebGateway in solution --- Journal.DevTool/Program.cs | 6 ++--- Journal.DevTool/Tui/App.cs | 26 +++++++------------ Journal.DevTool/Tui/Theme.cs | 36 +++++++++++++------------- Journal.DevTool/Tui/ToolchainScreen.cs | 20 +++++--------- Journal.DevTool/Tui/WorkspaceScreen.cs | 15 +++-------- Journal.slnx | 1 + 6 files changed, 42 insertions(+), 62 deletions(-) diff --git a/Journal.DevTool/Program.cs b/Journal.DevTool/Program.cs index a132fc3..756f812 100644 --- a/Journal.DevTool/Program.cs +++ b/Journal.DevTool/Program.cs @@ -5,7 +5,7 @@ using Spectre.Console; // ── Workspace + project discovery ──────────────────────────────────────────── var workspaceResult = WorkspaceLoader.FindAndLoad(); -var projectResult = ConfigLoader.FindAndLoad(); +var projectResult = ConfigLoader.FindAndLoad(); if (projectResult is null) { @@ -17,7 +17,7 @@ if (projectResult is null) // ── Main run loop (handles workspace project switching) ─────────────────────── var (currentConfig, currentRoot) = projectResult.Value; -var (workspace, workspaceRoot) = workspaceResult.HasValue +var (workspace, workspaceRoot) = workspaceResult.HasValue ? (workspaceResult.Value.Config, workspaceResult.Value.WorkspaceRoot) : ((WorkspaceConfig?)null, (string?)null); @@ -25,7 +25,7 @@ try { while (true) { - var app = new App(currentConfig, currentRoot, workspace, workspaceRoot); + var app = new App(currentConfig, currentRoot, workspace, workspaceRoot); var result = await app.RunAsync(); if (result.Reason == AppExitReason.Quit) diff --git a/Journal.DevTool/Tui/App.cs b/Journal.DevTool/Tui/App.cs index 3ad0118..36abb65 100644 --- a/Journal.DevTool/Tui/App.cs +++ b/Journal.DevTool/Tui/App.cs @@ -10,28 +10,20 @@ internal sealed record MenuItem(string Display, string Value); public enum AppExitReason { Quit, SwitchProject } public sealed record AppResult(AppExitReason Reason, string? NewProjectRoot = null); -public sealed class App +public sealed class App( + DevToolConfig config, + string projectRoot, + WorkspaceConfig? workspace = null, + string? workspaceRoot = null) { - private DevToolConfig _config; - private string _projectRoot; - private readonly WorkspaceConfig? _workspace; - private readonly string? _workspaceRoot; + private DevToolConfig _config = config; + private string _projectRoot = projectRoot; + private readonly WorkspaceConfig? _workspace = workspace; + private readonly string? _workspaceRoot = workspaceRoot; private IReadOnlyDictionary TargetMap => _config.Targets.ToDictionary(t => t.Id, StringComparer.OrdinalIgnoreCase); - public App( - DevToolConfig config, - string projectRoot, - WorkspaceConfig? workspace = null, - string? workspaceRoot = null) - { - _config = config; - _projectRoot = projectRoot; - _workspace = workspace; - _workspaceRoot = workspaceRoot; - } - public async Task RunAsync() { while (true) diff --git a/Journal.DevTool/Tui/Theme.cs b/Journal.DevTool/Tui/Theme.cs index 12afd42..3593e86 100644 --- a/Journal.DevTool/Tui/Theme.cs +++ b/Journal.DevTool/Tui/Theme.cs @@ -10,34 +10,34 @@ namespace Sdt.Tui; internal static class Theme { // ── Hex colour constants (use in Spectre markup strings) ───────────────── - public const string Green = "#00ff41"; // primary phosphor — all normal text - public const string GreenDim = "#005c1b"; // muted — borders, secondary info - public const string GreenBold = "#a8ff90"; // bright — selections, emphasis - public const string Amber = "#ffb300"; // warnings / group titles - public const string Red = "#ff4040"; // errors - public const string Ghost = "#003d12"; // near-invisible — decorative scanlines + public const string Green = "#00ff41"; // primary phosphor — all normal text + public const string GreenDim = "#005c1b"; // muted — borders, secondary info + public const string GreenBold = "#a8ff90"; // bright — selections, emphasis + public const string Amber = "#ffb300"; // warnings / group titles + public const string Red = "#ff4040"; // errors + public const string Ghost = "#003d12"; // near-invisible — decorative scanlines // ── Spectre Color instances (for FigletText, Rule styles, etc.) ────────── - public static readonly Color GreenColor = new(0, 255, 65); - public static readonly Color GreenDimColor = new(0, 92, 27); + public static readonly Color GreenColor = new(0, 255, 65); + public static readonly Color GreenDimColor = new(0, 92, 27); public static readonly Color GreenBoldColor = new(168, 255, 144); - public static readonly Color AmberColor = new(255, 179, 0); - public static readonly Color RedColor = new(255, 64, 64); + public static readonly Color AmberColor = new(255, 179, 0); + public static readonly Color RedColor = new(255, 64, 64); // ── Pre-built Style objects ─────────────────────────────────────────────── - public static readonly Style PrimaryStyle = new(GreenColor); - public static readonly Style DimStyle = new(GreenDimColor); - public static readonly Style BrightStyle = new(GreenBoldColor, decoration: Decoration.Bold); - public static readonly Style AmberStyle = new(AmberColor); - public static readonly Style RedStyle = new(RedColor, decoration: Decoration.Bold); + public static readonly Style PrimaryStyle = new(GreenColor); + public static readonly Style DimStyle = new(GreenDimColor); + public static readonly Style BrightStyle = new(GreenBoldColor, decoration: Decoration.Bold); + public static readonly Style AmberStyle = new(AmberColor); + public static readonly Style RedStyle = new(RedColor, decoration: Decoration.Bold); // ── Markup helper methods (auto-escape user content) ───────────────────── - public static string G(string t) => $"[{Green}]{Markup.Escape(t)}[/]"; + public static string G(string t) => $"[{Green}]{Markup.Escape(t)}[/]"; public static string Faint(string t) => $"[{GreenDim}]{Markup.Escape(t)}[/]"; public static string Bold(string t) => $"[bold {GreenBold}]{Markup.Escape(t)}[/]"; public static string Warn(string t) => $"[{Amber}]{Markup.Escape(t)}[/]"; - public static string Err(string t) => $"[bold {Red}]{Markup.Escape(t)}[/]"; - public static string Ok(string t) => $"[bold {Green}]✓ {Markup.Escape(t)}[/]"; + public static string Err(string t) => $"[bold {Red}]{Markup.Escape(t)}[/]"; + public static string Ok(string t) => $"[bold {Green}]✓ {Markup.Escape(t)}[/]"; public static string Fail(string t) => $"[bold {Red}]✗ {Markup.Escape(t)}[/]"; // ── Shared UI components ────────────────────────────────────────────────── diff --git a/Journal.DevTool/Tui/ToolchainScreen.cs b/Journal.DevTool/Tui/ToolchainScreen.cs index cb3db4d..96a8ec4 100644 --- a/Journal.DevTool/Tui/ToolchainScreen.cs +++ b/Journal.DevTool/Tui/ToolchainScreen.cs @@ -5,16 +5,10 @@ using Spectre.Console; namespace Sdt.Tui; -public sealed class ToolchainScreen +public sealed class ToolchainScreen(DevToolConfig config, string projectRoot) { - private readonly DevToolConfig _config; - private readonly string _projectRoot; - - public ToolchainScreen(DevToolConfig config, string projectRoot) - { - _config = config; - _projectRoot = projectRoot; - } + private readonly DevToolConfig _config = config; + private readonly string _projectRoot = projectRoot; public async Task RunAsync() { @@ -83,8 +77,8 @@ public sealed class ToolchainScreen { switch (action) { - case "py:check": await CheckPythonAsync(tc.Python!); break; - case "py:venv": await CreateVenvAsync(tc.Python!); break; + case "py:check": await CheckPythonAsync(tc.Python!); break; + case "py:venv": await CreateVenvAsync(tc.Python!); break; case "py:install": await InstallProfileAsync(tc.Python!); break; case "py:upgradepip": await UpgradePipAsync(tc.Python!); break; case "node:check": await CheckNodeAsync(tc.Node!); break; @@ -208,7 +202,7 @@ public sealed class ToolchainScreen AnsiConsole.MarkupLine(Theme.Faint($"Post-install: {cmd}")); var parts = cmd.Split(' ', 2); var postArgs = parts.Length > 1 ? parts[1].Split(' ') : Array.Empty(); - await RunLiveAsync(venvPy, ["-m", ..postArgs], _projectRoot); + await RunLiveAsync(venvPy, ["-m", .. postArgs], _projectRoot); } } @@ -263,7 +257,7 @@ public sealed class ToolchainScreen // ── Helpers ─────────────────────────────────────────────────────────────── - private string ResolvePythonExe(PythonToolchain py) + private static string ResolvePythonExe(PythonToolchain py) { if (OperatingSystem.IsWindows() && !string.IsNullOrWhiteSpace(py.WindowsExecutable)) return py.WindowsExecutable; diff --git a/Journal.DevTool/Tui/WorkspaceScreen.cs b/Journal.DevTool/Tui/WorkspaceScreen.cs index a7c694c..38d6a37 100644 --- a/Journal.DevTool/Tui/WorkspaceScreen.cs +++ b/Journal.DevTool/Tui/WorkspaceScreen.cs @@ -3,18 +3,11 @@ using Spectre.Console; namespace Sdt.Tui; -public sealed class WorkspaceScreen +public sealed class WorkspaceScreen(WorkspaceConfig workspace, string workspaceRoot, string currentProjectRoot) { - private readonly WorkspaceConfig _workspace; - private readonly string _workspaceRoot; - private readonly string _currentProjectRoot; - - public WorkspaceScreen(WorkspaceConfig workspace, string workspaceRoot, string currentProjectRoot) - { - _workspace = workspace; - _workspaceRoot = workspaceRoot; - _currentProjectRoot = currentProjectRoot; - } + private readonly WorkspaceConfig _workspace = workspace; + private readonly string _workspaceRoot = workspaceRoot; + private readonly string _currentProjectRoot = currentProjectRoot; /// /// Shows the project switcher. Returns the absolute path to the selected project root, diff --git a/Journal.slnx b/Journal.slnx index 83e23b7..090dfed 100644 --- a/Journal.slnx +++ b/Journal.slnx @@ -3,4 +3,5 @@ +