Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4b5e800
Initial plan
Copilot Oct 5, 2025
7510449
Remove legacy drivers and reorganize v2 architecture
Copilot Oct 5, 2025
39c5f07
Extract Windows key helper utilities and fix build
Copilot Oct 5, 2025
f619aa3
Fix all test references to legacy drivers
Copilot Oct 5, 2025
fb9430a
Update documentation to reflect new driver architecture
Copilot Oct 5, 2025
a1314f2
Remove V2.cd diagram file
Copilot Oct 5, 2025
c111028
Fix test failures: support legacy drivers and update exception handling
Copilot Oct 5, 2025
c3f9780
updated driver names
tig Oct 5, 2025
7d11fc8
Move V2 tests from ConsoleDrivers/V2 to proper locations
Copilot Oct 5, 2025
f7b25da
Rename ApplicationV2 to ModernApplicationImpl to remove v2 terminology
Copilot Oct 6, 2025
2a87f66
Remove V2 terminology from test drivers and FakeDriver classes
Copilot Oct 6, 2025
c993810
Merge ModernApplicationImpl into ApplicationImpl and move to App folder
Copilot Oct 6, 2025
bb2a0ba
Create modern FakeDriver with component factory architecture in Termi…
Copilot Oct 6, 2025
b833c63
Refactor: Move non-platform-dependent code from /Drivers to /App
Copilot Oct 6, 2025
9dc92ee
Code cleanup and org
tig Oct 6, 2025
70d37ae
Unit test reorg
tig Oct 6, 2025
4d203ce
Refactor MainLoop architecture: rename classes and enhance documentat…
Copilot Oct 6, 2025
c6597a9
Merge branch 'copilot/fix-b6590cf0-cec4-462a-98d6-a1f9b6313715' of ti…
tig Oct 6, 2025
08fd6e2
Add comprehensive FakeDriver tests (WIP - some tests need fixes)
Copilot Oct 6, 2025
82af5c5
Merge branch 'copilot/fix-b6590cf0-cec4-462a-98d6-a1f9b6313715' of ti…
tig Oct 6, 2025
ae06831
Fixed FakeDriver build failures
tig Oct 6, 2025
0cb64b3
Fix all FakeDriver test failures - Application.Top creation and clipb…
Copilot Oct 6, 2025
d100179
Fixed FakeDriver build failures2
tig Oct 6, 2025
e562c44
Merge branch 'copilot/fix-b6590cf0-cec4-462a-98d6-a1f9b6313715' of ti…
tig Oct 6, 2025
483b458
Remove hanging legacy FakeDriver tests that use Console.MockKeyPresses
Copilot Oct 6, 2025
313b1f4
Merge branch 'copilot/fix-b6590cf0-cec4-462a-98d6-a1f9b6313715' of ti…
tig Oct 6, 2025
04ae514
Fixed some tests
tig Oct 6, 2025
f93cdbd
Fixed more tests
tig Oct 6, 2025
1df66e6
Fixed more tests
tig Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Examples/Example/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
using Attribute = Terminal.Gui.Drawing.Attribute;

// Override the default configuration for the application to use the Light theme
ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }""";
//ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }""";
ConfigurationManager.Enable(ConfigLocations.All);



Application.Run<ExampleWindow> ().Dispose ();

// Before the application exits, reset Terminal.Gui for clean shutdown
Expand Down Expand Up @@ -89,5 +91,22 @@ public ExampleWindow ()

// Add the views to the Window
Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);

ListView lv = new ListView ()
{
Y = Pos.AnchorEnd(),
Height= Dim.Auto(),
Width = Dim.Auto()
};
lv.SetSource (["One", "Two", "Three", "Four"]);
Add (lv);
}

public override void EndInit ()
{
base.EndInit ();
// Set the theme to "Anders" if it exists, otherwise use "Default"
ThemeManager.Theme = ThemeManager.GetThemeNames ().FirstOrDefault (x => x == "Anders") ?? "Default";
}
}

90 changes: 22 additions & 68 deletions Examples/UICatalog/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,30 @@
"commandName": "Project",
"commandLineArgs": "--debug-log-level Debug"
},
"UICatalog --driver NetDriver": {
"UICatalog --driver windows": {
"commandName": "Project",
"commandLineArgs": "--driver NetDriver"
"commandLineArgs": "--driver windows -dl Trace"
},
"UICatalog --driver WindowsDriver": {
"UICatalog --driver dotnet": {
"commandName": "Project",
"commandLineArgs": "--driver WindowsDriver"
},
"UICatalog --driver v2": {
"commandName": "Project",
"commandLineArgs": "--driver v2 -dl Trace"
},
"UICatalog --driver v2win": {
"commandName": "Project",
"commandLineArgs": "--driver v2win -dl Trace"
},
"UICatalog --driver v2net": {
"commandName": "Project",
"commandLineArgs": "--driver v2net -dl Trace"
"commandLineArgs": "--driver dotnet -dl Trace"
},
"WSL: UICatalog": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll",
"distributionName": ""
},
"WSL: UICatalog --driver NetDriver": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver NetDriver",
"distributionName": ""
},
"WSL: UICatalog --driver v2": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2",
"distributionName": ""
},
"WSL: UICatalog --driver v2unix": {
"WSL: UICatalog --driver dotnet": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2unix",
"commandLineArgs": "dotnet UICatalog.dll --driver dotnet",
"distributionName": ""
},
"WSL: UICatalog --driver v2net": {
"WSL: UICatalog --driver unix": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2net",
"commandLineArgs": "dotnet UICatalog.dll --driver unix",
"distributionName": ""
},
"WSL-Gnome: UICatalog": {
Expand All @@ -60,68 +36,46 @@
"commandLineArgs": "bash -c 'while [ ! -e \"$XDG_RUNTIME_DIR/bus\" ]; do sleep 0.1; done; gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll; exec bash\"'",
"distributionName": ""
},
"WSL-Gnome: UICatalog --driver NetDriver": {
"WSL-Gnome: UICatalog --driver dotnet": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "bash -c 'while [ ! -e \"$XDG_RUNTIME_DIR/bus\" ]; do sleep 0.1; done; gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver NetDriver; exec bash\"'",
"commandLineArgs": "bash -c 'while [ ! -e \"$XDG_RUNTIME_DIR/bus\" ]; do sleep 0.1; done; gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver dotnet; exec bash\"'",
"distributionName": ""
},
"WSL-Gnome: UICatalog --driver v2": {
"WSL-Gnome: UICatalog --driver unix": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "bash -c 'dbus-run-session -- gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver v2; exec bash\"'",
"distributionName": ""
},
"WSL-Gnome: UICatalog --driver v2unix": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "bash -c 'dbus-run-session -- gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver v2unix; exec bash\"'",
"distributionName": ""
},
"WSL-Gnome: UICatalog --driver v2net": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "bash -c 'dbus-run-session -- gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver v2net; exec bash\"'",
"commandLineArgs": "bash -c 'dbus-run-session -- gnome-terminal --wait -- bash -l -c \"dotnet UICatalog.dll --driver unix; exec bash\"'",
"distributionName": ""
},
"Benchmark All": {
"commandName": "Project",
"commandLineArgs": "--benchmark"
},
"Benchmark All --driver NetDriver": {
"commandName": "Project",
"commandLineArgs": "--driver NetDriver --benchmark"
},
"Benchmark All --driver v2win": {
"Benchmark All --driver dotnet": {
"commandName": "Project",
"commandLineArgs": "--driver v2win --benchmark"
"commandLineArgs": "--driver dotnet --benchmark"
},
"Benchmark All --driver v2net": {
"Benchmark All --driver windows": {
"commandName": "Project",
"commandLineArgs": "--driver v2net --benchmark"
"commandLineArgs": "--driver windows --benchmark"
},
"WSL: Benchmark All": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --benchmark",
"distributionName": ""
},
"WSL: Benchmark All --driver v2": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2 --benchmark",
"distributionName": ""
},
"WSL: Benchmark All --driver v2unix": {
"WSL: Benchmark All --driver unix": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2unix --benchmark",
"commandLineArgs": "dotnet UICatalog.dll --driver unix --benchmark",
"distributionName": ""
},
"WSL: Benchmark All --driver v2net": {
"WSL: Benchmark All --driver dotnet": {
"commandName": "Executable",
"executablePath": "wsl",
"commandLineArgs": "dotnet UICatalog.dll --driver v2net --benchmark",
"commandLineArgs": "dotnet UICatalog.dll --driver dotnet --benchmark",
"distributionName": ""
},
"Docker": {
Expand All @@ -135,9 +89,9 @@
"commandName": "Project",
"commandLineArgs": "--disable-cm\r\n"
},
"UICatalog --disable-cm --driver v2win": {
"UICatalog --disable-cm --driver windows": {
"commandName": "Project",
"commandLineArgs": "--disable-cm --driver v2win"
"commandLineArgs": "--disable-cm --driver windows"
},
"Themes": {
"commandName": "Project",
Expand Down
51 changes: 38 additions & 13 deletions Examples/UICatalog/UICatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -76,12 +77,25 @@ private static int Main (string [] args)
// Process command line args

// If no driver is provided, the default driver is used.
Option<string> driverOption = new Option<string> ("--driver", "The IConsoleDriver to use.").FromAmong (
Application.GetDriverTypes ().Item2.ToArray ()!
);
// Get allowed driver names
string? [] allowedDrivers = Application.GetDriverTypes ().Item2.ToArray ();

Option<string> driverOption = new Option<string> ("--driver", "The IConsoleDriver to use.")
.FromAmong (allowedDrivers!);
driverOption.SetDefaultValue (string.Empty);
driverOption.AddAlias ("-d");
driverOption.AddAlias ("--d");

// Add validator separately (not chained)
driverOption.AddValidator (result =>
{
var value = result.GetValueOrDefault<string> ();
if (result.Tokens.Count > 0 && !allowedDrivers.Contains (value))
{
result.ErrorMessage = $"Invalid driver name '{value}'. Allowed values: {string.Join (", ", allowedDrivers)}";
}
});

// Configuration Management
Option<bool> disableConfigManagement = new (
"--disable-cm",
Expand Down Expand Up @@ -163,6 +177,17 @@ private static int Main (string [] args)
return 0;
}

var parseResult = parser.Parse (args);

if (parseResult.Errors.Count > 0)
{
foreach (var error in parseResult.Errors)
{
Console.Error.WriteLine (error.Message);
}
return 1; // Non-zero exit code for error
}

Scenario.BenchmarkTimeout = Options.BenchmarkTimeout;

Logging.Logger = CreateLogger ();
Expand All @@ -175,16 +200,16 @@ private static int Main (string [] args)
public static LogEventLevel LogLevelToLogEventLevel (LogLevel logLevel)
{
return logLevel switch
{
LogLevel.Trace => LogEventLevel.Verbose,
LogLevel.Debug => LogEventLevel.Debug,
LogLevel.Information => LogEventLevel.Information,
LogLevel.Warning => LogEventLevel.Warning,
LogLevel.Error => LogEventLevel.Error,
LogLevel.Critical => LogEventLevel.Fatal,
LogLevel.None => LogEventLevel.Fatal, // Default to Fatal if None is specified
_ => LogEventLevel.Fatal // Default to Information for any unspecified LogLevel
};
{
LogLevel.Trace => LogEventLevel.Verbose,
LogLevel.Debug => LogEventLevel.Debug,
LogLevel.Information => LogEventLevel.Information,
LogLevel.Warning => LogEventLevel.Warning,
LogLevel.Error => LogEventLevel.Error,
LogLevel.Critical => LogEventLevel.Fatal,
LogLevel.None => LogEventLevel.Fatal, // Default to Fatal if None is specified
_ => LogEventLevel.Fatal // Default to Information for any unspecified LogLevel
};
}

private static ILogger CreateLogger ()
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/App/Application.Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static partial class Application // Driver abstractions

// BUGBUG: ForceDriver should be nullable.
/// <summary>
/// Forces the use of the specified driver (one of "fake", "ansi", "curses", "net", or "windows"). If not
/// Forces the use of the specified driver (one of "fake", "dotnet", "windows", or "unix"). If not
/// specified, the driver is selected based on the platform.
/// </summary>
/// <remarks>
Expand Down
81 changes: 44 additions & 37 deletions Terminal.Gui/App/Application.Initialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,34 @@ public static partial class Application // Initialization (Init/Shutdown)
/// <paramref name="driverName"/> are specified the default driver for the platform will be used.
/// </param>
/// <param name="driverName">
/// The short name (e.g. "net", "windows", "ansi", "fake", or "curses") of the
/// The short name (e.g. "dotnet", "windows", "unix", or "fake") of the
/// <see cref="IConsoleDriver"/> to use. If neither <paramref name="driver"/> or <paramref name="driverName"/> are
/// specified the default driver for the platform will be used.
/// </param>
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static void Init (IConsoleDriver? driver = null, string? driverName = null)
{
// Check if this is a request for a legacy driver (like FakeDriver)
// that isn't supported by the modern application architecture
if (driver is null)
{
var driverNameToCheck = string.IsNullOrWhiteSpace (driverName) ? ForceDriver : driverName;
if (!string.IsNullOrEmpty (driverNameToCheck))
{
(List<Type?> drivers, List<string?> driverTypeNames) = GetDriverTypes ();
Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (driverNameToCheck, StringComparison.InvariantCultureIgnoreCase));

// If it's a legacy IConsoleDriver (not a Facade), use InternalInit which supports legacy drivers
if (driverType is { } && !typeof (IConsoleDriverFacade).IsAssignableFrom (driverType))
{
InternalInit (driver, driverName);
return;
}
}
}

// Otherwise delegate to the ApplicationImpl instance (which uses the modern architecture)
ApplicationImpl.Instance.Init (driver, driverName);
}

Expand Down Expand Up @@ -90,44 +110,31 @@ internal static void InternalInit (
ForceDriver = driverName;
}

// Check if we need to use a legacy driver (like FakeDriver)
// or go through the modern application architecture
if (Driver is null)
{
PlatformID p = Environment.OSVersion.Platform;

if (string.IsNullOrEmpty (ForceDriver))
{
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
{
Driver = new WindowsDriver ();
}
else
{
Driver = new CursesDriver ();
}
}
else
//// Try to find a legacy IConsoleDriver type that matches the driver name
//bool useLegacyDriver = false;
//if (!string.IsNullOrEmpty (ForceDriver))
//{
// (List<Type?> drivers, List<string?> driverTypeNames) = GetDriverTypes ();
// Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));

// if (driverType is { } && !typeof (IConsoleDriverFacade).IsAssignableFrom (driverType))
// {
// // This is a legacy driver (not a ConsoleDriverFacade)
// Driver = (IConsoleDriver)Activator.CreateInstance (driverType)!;
// useLegacyDriver = true;
// }
//}

//// Use the modern application architecture
//if (!useLegacyDriver)
{
(List<Type?> drivers, List<string?> driverTypeNames) = GetDriverTypes ();
Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));

if (driverType is { })
{
Driver = (IConsoleDriver)Activator.CreateInstance (driverType)!;
}
else if (ForceDriver?.StartsWith ("v2") ?? false)
{
ApplicationImpl.ChangeInstance (new ApplicationV2 ());
ApplicationImpl.Instance.Init (driver, ForceDriver);
Debug.Assert (Driver is { });

return;
}
else
{
throw new ArgumentException (
$"Invalid driver name: {ForceDriver}. Valid names are {string.Join (", ", drivers.Select (t => t!.Name))}"
);
}
ApplicationImpl.Instance.Init (driver, driverName);
Debug.Assert (Driver is { });
return;
}
}

Expand Down Expand Up @@ -217,7 +224,7 @@ public static (List<Type?>, List<string?>) GetDriverTypes ()
List<string?> driverTypeNames = driverTypes
.Where (d => !typeof (IConsoleDriverFacade).IsAssignableFrom (d))
.Select (d => d!.Name)
.Union (["v2", "v2win", "v2net", "v2unix"])
.Union (["dotnet", "windows", "unix", "fake"])
.ToList ()!;

return (driverTypes, driverTypeNames);
Expand Down
Loading
Loading