Skip to content

Commit 8aec052

Browse files
tigBDispCopilottznindCopilot
authored
Fixes #4274 - v2win vsdebugconsole issue CM related UnitTest failures (#4287)
* Fixes #4274. Using Windows Host Console v2win is rendering window size badly using VSDebugConsole.exe * Fixes #4259. Our wcwidth library is out of date (#4281) * Update package versions and remove hack code from RuneExtensions Updated several package versions in `Directory.Packages.props`, including `JetBrains.Annotations`, `Microsoft.Extensions.Logging.Abstractions`, `System.IO.Abstractions`, and `Wcwidth`. Refactored methods in `RuneExtensions.cs`: - Simplified `GetColumns` by removing special Unicode handling. - Renamed constants to follow naming conventions. - Improved logic and readability in `DecodeSurrogatePair`, `Encode`, and `GetEncodingLength`. - Streamlined `IsSurrogatePair` and `MakePrintable` for clarity and efficiency. * Update package version ranges for flexibility Updated the `JetBrains.Annotations` package to use a version range starting from `2025.2.2` to allow future updates. Adjusted the `Microsoft.Extensions.Logging.Abstractions` package to a version range `[9.0.0,10)` for compatibility. Changed `System.IO.Abstractions` to a range `[22.0.16,23)` and `Wcwidth` to `[3.0.0,)` to enable future updates within specified ranges. * Remove legacy drivers, simplify architecture, and reorganize codebase structure (#4270) * Initial plan * Remove legacy drivers and reorganize v2 architecture Co-authored-by: tig <[email protected]> * Extract Windows key helper utilities and fix build Co-authored-by: tig <[email protected]> * Fix all test references to legacy drivers Co-authored-by: tig <[email protected]> * Update documentation to reflect new driver architecture Co-authored-by: tig <[email protected]> * Remove V2.cd diagram file Co-authored-by: tig <[email protected]> * Fix test failures: support legacy drivers and update exception handling Co-authored-by: tig <[email protected]> * updated driver names * Move V2 tests from ConsoleDrivers/V2 to proper locations Co-authored-by: tig <[email protected]> * Rename ApplicationV2 to ModernApplicationImpl to remove v2 terminology Co-authored-by: tig <[email protected]> * Remove V2 terminology from test drivers and FakeDriver classes Co-authored-by: tig <[email protected]> * Merge ModernApplicationImpl into ApplicationImpl and move to App folder Co-authored-by: tig <[email protected]> * Create modern FakeDriver with component factory architecture in Terminal.Gui project Co-authored-by: tig <[email protected]> * Refactor: Move non-platform-dependent code from /Drivers to /App Co-authored-by: tig <[email protected]> * Code cleanup and org * Unit test reorg * Refactor MainLoop architecture: rename classes and enhance documentation for clarity Co-authored-by: tig <[email protected]> * Add comprehensive FakeDriver tests (WIP - some tests need fixes) Co-authored-by: tig <[email protected]> * Fixed FakeDriver build failures * Fix all FakeDriver test failures - Application.Top creation and clipboard behaviors Co-authored-by: tig <[email protected]> * Fixed FakeDriver build failures2 * Remove hanging legacy FakeDriver tests that use Console.MockKeyPresses Co-authored-by: tig <[email protected]> * Fixed some tests * Fixed more tests * Fixed more tests * Fix bad copilot (#4277) * Update Terminal.Gui/Drivers/FakeDriver/FakeConsoleOutput.cs Co-authored-by: Copilot <[email protected]> * Refactor Application Init and Update Tests Refactored `Application.Init` to improve initialization logic: - Added fallback to `ForceDriver` when `driverName` is null. - Changed repeated `Init` calls to throw `InvalidOperationException`. - Updated `_driverName` assignment logic for robustness. Enhanced `IConsoleDriver` with detailed remarks on implementations. Revised test cases to align with updated `Application.Init` behavior: - Replaced `FakeDriver` with `null` and `driverName: "fake"`. - Skipped or commented out tests incompatible with new logic. - Improved formatting and removed redundant setup code. Improved code style and consistency across the codebase: - Standardized parameter formatting and spacing. - Removed outdated comments and unused code. General cleanup to enhance readability and maintainability. * Warp fix copilot (#4278) * More fixes (#4279) * Fixes/works around test failures and temporarily disable failing test Updated `FakeDriver` to set `RunningUnitTests` to `true` and initialize dimensions using `FakeConsole`. Modified `TestRespondersDisposedAttribute` to set `ConsoleDriver.RunningUnitTests` in the `Before` method, ensuring proper behavior during unit tests. Temporarily disabled the `Button_CanFocus_False_Raises_Accepted_Correctly` test in `ViewCommandTests` by adding a `Skip` parameter to the `[Fact]` attribute, referencing issue #4270. * Allow all tests to run despite failures in UnitTests Modified the `dotnet test` command in the `Run UnitTestsParallelizable` step to set `xunit.stopOnFail` to `false`. This ensures that the test runner does not stop execution on the first failure, allowing all tests to execute regardless of individual test outcomes. * Refactor ApplicationScreenTests for cleaner setup/teardown Refactored `ClearContents_Called_When_Top_Frame_Changes` test: - Added `[AutoInitShutdown]` attribute for automatic lifecycle management. - Replaced manual `Application.Init` and `Application.Top` setup with `Application.Begin` and `RunState`. - Simplified event handling by defining `ClearedContents` handler inline. - Removed explicit cleanup logic, relying on `Application.End` for teardown. Updated `using` directives to include `UnitTests` namespace. * Attempt to fix intermittent local test failures. Update ApplicationImpl initialization parameter Changed the second parameter of the `impl.Init` method in the `FakeApplicationFactory` class from `"dotnet"` to `"fake"`. * Code cleanup to cause Action to re-run. * Stop tests on first failure in UnitTestsParallelizable Updated the `dotnet test` command in `unit-tests.yml` to set the `xunit.stopOnFail` parameter to `true`. This change ensures that test execution halts immediately upon encountering a failure, allowing quicker identification and resolution of issues. Note that this may prevent the full test suite from running in the event of a failure. * Allow all tests to run despite failures in CI Updated `unit-tests.yml` to set `xunit.stopOnFail` to `false` in both `Run UnitTests` and `Run UnitTestsParallelizable` steps. This ensures that the test runner does not stop execution on the first test failure, allowing all tests to complete even if some fail. * Enhance RuneExtensions docs and update user dictionary Updated the `<remarks>` section in `RuneExtensions.GetColumns` to include details about the `wcwidth` implementation and improved readability with `<para>` tags. Added `wcwidth` to the user dictionary in `Terminal.sln.DotSettings` to avoid spelling errors. * Improve XML doc formatting in RuneExtensions.cs Updated the remarks section of the `GetColumns` method in the `RuneExtensions` class to enhance readability by reformatting and properly indenting `<para>` tags. The content remains unchanged, describing the method's implementation via `wcwidth` and its role as a Terminal.Gui extension for `System.Text.Rune`. * Refactor drivers and improve clipboard handling Replaced legacy drivers (`CursesDriver`, `NetDriver`) with `UnixDriver` and `DotNetDriver` across the codebase, including comments, method names, and test cases. Updated documentation and remarks to reflect the new driver names and platforms. Revamped clipboard handling with new platform-specific implementations: `UnixClipboard` for Unix, `MacOSXClipboard` for macOS, and `WSLClipboard` for Linux under WSL. Removed the old `CursesClipboard` and consolidated clipboard logic. Updated test cases to align with the new drivers and clipboard implementations. Improved naming consistency and cleaned up redundant code. Updated the README and documentation to reflect these changes. * Remove `PlatformColor` from `Attribute` struct This commit removes the `PlatformColor` property from the `Attribute` struct, simplifying the codebase by eliminating platform-specific color handling. The following changes were made: - Removed `PlatformColor` from the `Attribute` struct, including its initialization, usage, and related comments. - Updated constructors to no longer initialize or use `PlatformColor`. - Modified `Equals` and `GetHashCode` methods to exclude `PlatformColor`. - Updated `UnixComponentFactory` documentation to remove references to "v2unix." - Renamed `v2TestDriver` to `testDriver` in the `With` class for clarity. - Removed `PlatformColor` references in `DriverAssert` and related error messages. - Deleted test cases in `AttributeTests` that relied on `PlatformColor`. - Cleaned up comments and TODOs related to `PlatformColor` and `UnixDriver`. These changes reflect a shift away from platform-dependent color management, improving code clarity and reducing complexity. Remove `PlatformColor` and simplify `Attribute` logic The `PlatformColor` property has been removed from the `Attribute` struct, along with its associated logic, simplifying the codebase and eliminating platform-specific dependencies. Constructors, equality checks, and hash code generation in `Attribute` have been updated accordingly. The `CurrentAttribute` property in `ConsoleDriver` and `OutputBuffer` has been simplified, removing dependencies on `Application.Driver`. The `MakeColor` method logic has been removed or simplified in related classes. Tests in `AttributeTests` have been refactored to reflect these changes, focusing on `Foreground`, `Background`, and `Style`. Unix-specific logic tied to `PlatformColor` has been eliminated. Additional updates include renaming parameters in the `With` class for clarity, simplifying `DriverAssert` output, and performing minor code cleanups to improve readability and maintainability. * Refactor Terminal.Gui driver architecture for v2 Updated documentation to reflect the new modular driver architecture in Terminal.Gui v2. - Revised `namespace-drivers.md` to include new components (`IConsoleInput`, `IConsoleOutput`, `IInputProcessor`, `IOutputBuffer`, `IWindowSizeMonitor`) and terminal size monitoring. - Replaced "Key Components" with "Architecture Overview" and added details on the **Component Factory** pattern. - Documented the four driver implementations (`DotNetDriver`, `WindowsDriver`, `UnixDriver`, `FakeDriver`) and their platform-specific optimizations. - Added a "Threading Model" section to explain the multi-threaded design for responsive input handling. - Updated examples to demonstrate driver capabilities and explicit driver selection. In `drivers.md`: - Expanded the "Overview" to emphasize the modular, component-based architecture. - Reorganized "Drivers" into "Available Drivers" and added details on `FakeDriver` for unit testing. - Added sections on "Initialization Flow," "Shutdown Flow," and platform-specific driver details. - Provided examples for accessing driver components and creating custom drivers. In `index.md`: - Updated "Cross Platform" feature to reflect new driver names and clarified compatibility with SSH and monochrome terminals. * Moved files around --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: tig <[email protected]> Co-authored-by: Tig <[email protected]> Co-authored-by: Thomas Nind <[email protected]> Co-authored-by: Copilot <[email protected]> * Fix nit test. * Change ClearScreenNextIteration to internal and trying to fix unit test failure * Reuse method and fix text field color to normal, probably due some changed configuration * Fix scenario Shortcut not restoring Application.Quit * Giving more time to load Scrolling scenario and display failing scenario * Revert changes and add more assertions * Forcing CI tests again and I suspect that is causing by UpdateFromJson unit test * Changed test to force fake driver * Ensure restore the original colors * Update test runner behavior in unit-tests.yml Changed `fail-fast` to `false` in `non_parallel_unittests` to allow all runners to complete even if errors occur. Updated `xunit.stopOnFail` to `true` in both `Run UnitTests` and `Run UnitTestsParallelizable` steps to stop test execution immediately upon failure. These changes improve test handling and execution consistency. Refactor and enhance configuration and scheme handling Refactored `ConfigurationManager` and `Scope<T>` to improve clarity and ensure proper resetting to hardcoded defaults. Updated `Color` constructor to use ARGB values for accuracy. Added debug assertions and logging for better test reliability. Expanded test coverage: - Verified hardcoded schemes and themes reset correctly. - Added tests for `UpdateFromJson` behavior and `Color.ToString` output. - Improved `SchemeManager` and `SchemeTests` to validate attributes and scheme overrides. General improvements include better state management during tests and enhanced readability of event handlers. * Found cause of #4288 and provided a workaround * Reverted unneeded change to ComboBoxTests * Fixed test that wasn't actually testing anything * Added more precise unit test showing issue * Added more precise unit test showing issue2 * Made test even more precise * Potential fix for underlying issue * Fixed test that broke with last change * Reverted`ConfigurationManager` to return `_hardCodedConfigPropertyCache` directly, eliminating deep copy overhead for better performance. Added a new test in `ConfigurationManagerTests` to verify that `GetHardCodedConfigPropertyCache` always returns the same reference. Updated existing tests to reflect this change. Refactored `SchemeManagerTests` to use `try-finally` blocks for proper cleanup and improved test reliability. Applied similar changes to other test methods for consistency. Re-enabled the `UpdateFrom_Corrupts_Schemes_HardCodeDefaults` test in `ThemeScopeTests` as the underlying issue has been rnot been esolved. * Updated the `Disable` method calls across test classes to use the new overload with a `true` parameter, ensuring consistent behavior. * Refactor and fix configuration and theme management Refactored method names across multiple classes for clarity and consistency (e.g., `LoadCurrentValues` to `UpdateToCurrentValues`, `ResetToHardCodedDefaults` to `LoadHardCodedDefaults`). Removed redundant attributes from `ConfigurationManager`. Implemented a workaround for `SchemeManager` to address issues with hard-coded schemes being overwritten. Updated `ThemeManager` logic to ensure proper initialization and updates of themes. Aligned unit tests with refactored methods and added comments to document changes. Made minor adjustments to improve code maintainability, including handling of property values and removal of unused variables. * Fix hard-coded defaults corruption in ThemeScope Replaced `ResetToCurrentValues` with `ResetToHardCodedDefaults` across multiple files to address corruption of hard-coded defaults. - Added a partial workaround in `ConfigurationManager.cs` to prevent overwriting hard-coded schemes in `ThemeScope`. - Highlighted known issues with `UpdateToCurrentValues` in `ThemeManager.cs`. - Updated tests in `ConfigurationManagerTests`, `SchemeManagerTests`, and others to reflect the reset method. - Skipped or modified tests that rely on `ResetToCurrentValues` due to its corruption issues. - Refactored `GlyphTests` to ensure proper cleanup using `try-finally`. - Added comments and skipped tests to document and work around known bugs (e.g., #4288). * Clarify comments and add theme reset functionality Updated comments in `SchemeManager` and `ThemeManager` to clarify that the workaround for hardcoded schemes is partial. Added a new `LoadHardCodedDefaults` method to `ThemeManager`, marked with `[RequiresUnreferencedCode]` and `[RequiresDynamicCode]`, to reset themes to hardcoded defaults. This method ensures proper initialization by throwing an exception if `ConfigurationManager` is not initialized. Updated `ThemeManager` to call `SchemeManager.LoadToHardCodedDefaults` during the theme reset process, ensuring consistent loading of hardcoded schemes. * Removed special handling for the "Schemes" key in `hardCodedThemeProperties`, * Code cleanup Refactored XML documentation comments for better readability. Enhanced exception handling in `GetScheme(Schemes)` by adding a null check and throwing `ArgumentException` for invalid inputs. Simplified method definitions by converting multi-line methods to single-line. Updated attributes for `LoadToHardCodedDefaults` to align with the `SetSchemes` method. Refactored `LoadToHardCodedDefaults` implementation for cleaner code. Added support for Visual Studio debug console in `WindowsDriver`, including disabling the alternative screen buffer, preserving original console colors, and restoring them on shutdown. Performed general code cleanup, including removing unnecessary comments and improving inline comments for clarity. * Refactor and remove redundant validation methods Removed `Validate` methods from `ConfigurationManager`, `Scope<T>`, and `ThemeManager`, indicating a shift in validation responsibilities. Enabled nullable reference types in `Scope.cs` to enforce stricter nullability checks. Simplified `Scope<T>` constructor and replaced explicit type declarations with `var` for improved readability. Adjusted LINQ query formatting and removed unused `using System.Text.Json;` to clean up dependencies. Made minor formatting changes for consistency and maintainability. * Refactor ConfigurationManager for clarity and safety Renamed `ResetToCurrentValues` to `UpdateToCurrentValues` for better clarity and updated all references, including comments and documentation. Introduced `_hardCodedConfigPropertyCacheLock` to ensure thread-safety when accessing `_hardCodedConfigPropertyCache`. Updated `Reset` terminology to `Update` across the codebase to reflect the updated behavior. Improved `SerializerContext` initialization with concise syntax and fixed a formatting issue in a `Console.WriteLine` statement. Reformatted filtering logic for `configPropertiesByScope` for better readability. Updated test cases in `AppSettingsScopeTests` and `ConfigurationManagerTests` to align with the renamed method and ensure consistent functionality. * Code cleanup Improve readability and handle null in serialization Refactored LINQ queries to remove redundant line breaks, improving code readability. Updated comments for clarity and adjusted tone. Added a null check for the `prop` variable during serialization to ensure proper handling of null values by writing `null` to the JSON writer. * Code Cleanup - Refactor ThemeManager and improve nullability handling Updated ThemeManager to improve method visibility, naming consistency, and documentation. Introduced `GetHardCodedThemes` and `SetThemes` for better encapsulation. Made `DEFAULT_THEME_NAME` public for broader access. Enhanced nullability handling across multiple files using the null-forgiving operator (`!`) to suppress warnings. Refactored `Themes.cs` to ensure proper cleanup of `allViewsView`. Simplified assertions in test files to reflect updated method visibility and removed redundant checks. Improved code clarity and maintainability throughout the codebase. --------- Co-authored-by: BDisp <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: tig <[email protected]> Co-authored-by: Thomas Nind <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent dea6736 commit 8aec052

31 files changed

+1399
-310
lines changed

Examples/UICatalog/Scenarios/CombiningMarks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public override void Main ()
1313
top.DrawComplete += (s, e) =>
1414
{
1515
// Forces reset _lineColsOffset because we're dealing with direct draw
16-
Application.ClearScreenNextIteration = true;
16+
Application.Top!.SetNeedsDraw ();
1717

1818
var i = -1;
1919
top.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");

Examples/UICatalog/Scenarios/Shortcuts.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ public class Shortcuts : Scenario
1212
public override void Main ()
1313
{
1414
Application.Init ();
15+
var quitKey = Application.QuitKey;
1516
Window app = new ();
1617

1718
app.Loaded += App_Loaded;
1819

1920
Application.Run (app);
2021
app.Dispose ();
2122
Application.Shutdown ();
23+
Application.QuitKey = quitKey;
2224
}
2325

2426
// Setting everything up in Loaded handler because we change the

Examples/UICatalog/Scenarios/Themes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public override void Main ()
172172
else
173173
{
174174
appWindow.Remove (allViewsView);
175-
allViewsView.Dispose ();
175+
allViewsView!.Dispose ();
176176
allViewsView = null;
177177

178178
appWindow.Add (viewFrame);

Terminal.Gui/App/Application.Screen.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ public static bool OnSizeChanging (SizeChangedEventArgs args)
8282
/// Gets or sets whether the screen will be cleared, and all Views redrawn, during the next Application iteration.
8383
/// </summary>
8484
/// <remarks>
85-
/// This is typicall set to true when a View's <see cref="View.Frame"/> changes and that view has no
85+
/// This is typical set to true when a View's <see cref="View.Frame"/> changes and that view has no
8686
/// SuperView (e.g. when <see cref="Application.Top"/> is moved or resized.
8787
/// </remarks>
88-
public static bool ClearScreenNextIteration { get; set; }
88+
internal static bool ClearScreenNextIteration { get; set; }
8989
}

Terminal.Gui/Configuration/ConfigProperty.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#nullable enable
22
using System.Collections.Concurrent;
33
using System.Collections.Immutable;
4+
using System.Diagnostics;
45
using System.Diagnostics.CodeAnalysis;
56
using System.Reflection;
67
using System.Text.Json;
@@ -74,6 +75,8 @@ public bool Apply ()
7475
{
7576
// Use DeepCloner to create a deep copy of PropertyValue
7677
object? val = DeepCloner.DeepClone (PropertyValue);
78+
79+
Debug.Assert (!Immutable);
7780
PropertyInfo.SetValue (null, val);
7881

7982
}

Terminal.Gui/Configuration/ConfigurationManager.cs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static class ConfigurationManager
5151
{
5252
/// <summary>The backing property for <see cref="Settings"/> (config settings of <see cref="SettingsScope"/>).</summary>
5353
/// <remarks>
54-
/// Is <see langword="null"/> until <see cref="ResetToCurrentValues"/> is called. Gets set to a new instance by
54+
/// Is <see langword="null"/> until <see cref="UpdateToCurrentValues"/> is called. Gets set to a new instance by
5555
/// deserialization
5656
/// (see <see cref="Load"/>).
5757
/// </remarks>
@@ -117,15 +117,19 @@ internal static bool IsInitialized ()
117117
}
118118
}
119119

120+
// TODO: Find a way to make this cache truly read-only at the leaf node level.
121+
// TODO: Right now, the dictionary is frozen, but the ConfigProperty instances can still be modified
122+
// TODO: if the PropertyValue is a reference type.
123+
// TODO: See https://github.com/gui-cs/Terminal.Gui/issues/4288
120124
/// <summary>
121125
/// A cache of all<see cref="ConfigurationPropertyAttribute"/> properties and their hard coded values.
122126
/// </summary>
123127
/// <remarks>Is <see langword="null"/> until <see cref="Initialize"/> is called.</remarks>
124128
#pragma warning disable IDE1006 // Naming Styles
125129
internal static FrozenDictionary<string, ConfigProperty>? _hardCodedConfigPropertyCache;
130+
126131
private static readonly object _hardCodedConfigPropertyCacheLock = new ();
127132
#pragma warning restore IDE1006 // Naming Styles
128-
129133
internal static FrozenDictionary<string, ConfigProperty>? GetHardCodedConfigPropertyCache ()
130134
{
131135
lock (_hardCodedConfigPropertyCacheLock)
@@ -183,7 +187,7 @@ internal static void Initialize ()
183187
lock (_uninitializedConfigPropertiesCacheCacheLock)
184188
{
185189
// _allConfigProperties: for ordered, iterable access (LINQ-friendly)
186-
// _frozenConfigPropertyCache: for high-speed key lookup (frozen)
190+
// _hardCodedConfigPropertyCache: for high-speed key lookup (frozen)
187191

188192
// Note GetAllConfigProperties returns a new instance and all the properties !HasValue and Immutable.
189193
_uninitializedConfigPropertiesCache = ConfigProperty.GetAllConfigProperties ();
@@ -209,6 +213,11 @@ internal static void Initialize ()
209213
}
210214

211215
LoadHardCodedDefaults ();
216+
217+
// BUGBUG: ThemeScope is broken and needs to be fixed to not have the hard coded schemes get overwritten.
218+
// BUGBUG: This a partial workaround.
219+
// BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/4288
220+
ThemeManager.Themes? [ThemeManager.Theme]?.Apply ();
212221
}
213222

214223
#endregion Initialization
@@ -291,6 +300,7 @@ public static void Disable (bool resetToHardCodedDefaults = false)
291300

292301
if (resetToHardCodedDefaults)
293302
{
303+
// Calls Apply
294304
ResetToHardCodedDefaults ();
295305
}
296306
}
@@ -299,16 +309,17 @@ public static void Disable (bool resetToHardCodedDefaults = false)
299309

300310
#region Reset
301311

302-
// `Reset` - Reset the configuration to either the current values or the hard-coded defaults.
303-
// Resetting does not load the configuration; it only resets the configuration to the default values.
312+
// `Update` - Updates the configuration from either the current values or the hard-coded defaults.
313+
// Updating does not load the configuration; it only updates the configuration to the values currently
314+
// in the static ConfigProperties.
304315

305316
/// <summary>
306-
/// INTERNAL: Resets <see cref="ConfigurationManager"/>. Loads settings from the current
317+
/// INTERNAL: Updates <see cref="ConfigurationManager"/> to the settings from the current
307318
/// values of the static <see cref="ConfigurationPropertyAttribute"/> properties.
308319
/// </summary>
309320
[RequiresUnreferencedCode ("AOT")]
310321
[RequiresDynamicCode ("AOT")]
311-
internal static void ResetToCurrentValues ()
322+
internal static void UpdateToCurrentValues ()
312323
{
313324
if (!IsInitialized ())
314325
{
@@ -327,13 +338,13 @@ internal static void ResetToCurrentValues ()
327338
_settingsLockSlim.ExitWriteLock ();
328339
}
329340

330-
Settings!.LoadCurrentValues ();
341+
Settings!.UpdateToCurrentValues ();
331342
ThemeManager.UpdateToCurrentValues ();
332-
AppSettings!.LoadCurrentValues ();
343+
AppSettings!.UpdateToCurrentValues ();
333344
}
334345

335346
/// <summary>
336-
/// INTERNAL: Resets <see cref="ConfigurationManager"/>. Loads the hard-coded values of the
347+
/// INTERNAL: Loads the hard-coded values of the
337348
/// <see cref="ConfigurationPropertyAttribute"/> properties and applies them.
338349
/// </summary>
339350
[RequiresUnreferencedCode ("AOT")]
@@ -374,7 +385,7 @@ internal static void LoadHardCodedDefaults ()
374385

375386
Settings = new ();
376387
Settings!.LoadHardCodedDefaults ();
377-
ThemeManager.ResetToHardCodedDefaults ();
388+
ThemeManager.LoadHardCodedDefaults ();
378389
AppSettings!.LoadHardCodedDefaults ();
379390
}
380391

@@ -447,10 +458,6 @@ public static void Load (ConfigLocations locations)
447458
{
448459
SourcesManager?.Load (Settings, $"~/.tui/{AppName}.{_configFilename}", ConfigLocations.AppHome);
449460
}
450-
451-
Settings!.Validate ();
452-
ThemeManager.Validate ();
453-
AppSettings!.Validate ();
454461
}
455462

456463
// TODO: Rename to Loaded?
@@ -566,7 +573,7 @@ private static void OnApplied ()
566573

567574
[SuppressMessage ("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
568575
internal static readonly SourceGenerationContext SerializerContext = new (
569-
new JsonSerializerOptions
576+
new()
570577
{
571578
// Be relaxed
572579
ReadCommentHandling = JsonCommentHandling.Skip,
@@ -638,7 +645,7 @@ public static AppSettingsScope? AppSettings
638645
if (!appSettingsConfigProperty.HasValue)
639646
{
640647
var appSettings = new AppSettingsScope ();
641-
appSettings.LoadCurrentValues ();
648+
appSettings.UpdateToCurrentValues ();
642649

643650
return appSettings;
644651
}
@@ -710,8 +717,9 @@ public static void PrintJsonErrors ()
710717
{
711718
if (_jsonErrors.Length > 0)
712719
{
713-
Console.WriteLine (@"Terminal.Gui ConfigurationManager encountered these errors while reading configuration files" +
714-
@"(set ThrowOnJsonErrors to have these caught during execution):");
720+
Console.WriteLine (
721+
@"Terminal.Gui ConfigurationManager encountered these errors while reading configuration files"
722+
+ @"(set ThrowOnJsonErrors to have these caught during execution):");
715723
Console.WriteLine (_jsonErrors.ToString ());
716724
}
717725
}
@@ -783,8 +791,10 @@ public static string GetHardCodedConfig ()
783791

784792
Debug.Assert (filtered is { });
785793

786-
IEnumerable<KeyValuePair<string, ConfigProperty>> configPropertiesByScope = filtered as KeyValuePair<string, ConfigProperty> [] ?? filtered.ToArray ();
794+
IEnumerable<KeyValuePair<string, ConfigProperty>> configPropertiesByScope =
795+
filtered as KeyValuePair<string, ConfigProperty> [] ?? filtered.ToArray ();
787796
Debug.Assert (configPropertiesByScope.All (v => !v.Value.HasValue));
797+
788798
return configPropertiesByScope;
789799
}
790800
}

Terminal.Gui/Configuration/SchemeManager.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,29 @@
77
namespace Terminal.Gui.Configuration;
88

99
/// <summary>
10-
/// Holds the <see cref="Drawing.Scheme"/>s that define the <see cref="System.Attribute"/>s that are used by views to render
11-
/// themselves. A Scheme is a mapping from <see cref="Drawing.VisualRole"/>s (such as <see cref="Drawing.VisualRole.Focus"/>) to <see cref="System.Attribute"/>s.
10+
/// Holds the <see cref="Drawing.Scheme"/>s that define the <see cref="System.Attribute"/>s that are used by views to
11+
/// render
12+
/// themselves. A Scheme is a mapping from <see cref="Drawing.VisualRole"/>s (such as
13+
/// <see cref="Drawing.VisualRole.Focus"/>) to <see cref="System.Attribute"/>s.
1214
/// A Scheme defines how a `View` should look based on its purpose (e.g. Menu or Dialog).
1315
/// </summary>
14-
public sealed class SchemeManager// : INotifyCollectionChanged, IDictionary<string, Scheme?>
16+
public sealed class SchemeManager // : INotifyCollectionChanged, IDictionary<string, Scheme?>
1517
{
1618
#pragma warning disable IDE1006 // Naming Styles
1719
private static readonly object _schemesLock = new ();
1820
#pragma warning restore IDE1006 // Naming Styles
1921

2022
/// <summary>
21-
/// INTERNAL: Gets the hard-coded schemes defined by <see cref="View"/>. These are not loaded from the configuration files,
23+
/// INTERNAL: Gets the hard-coded schemes defined by <see cref="View"/>. These are not loaded from the configuration
24+
/// files,
2225
/// but are hard-coded in the source code. Used for unit testing when ConfigurationManager is not initialized.
2326
/// </summary>
2427
/// <returns></returns>
2528
internal static ImmutableSortedDictionary<string, Scheme?>? GetHardCodedSchemes () { return Scheme.GetHardCodedSchemes ()!; }
2629

2730
/// <summary>
28-
/// Use <see cref="AddScheme"/>, <see cref="GetScheme(Drawing.Schemes)"/>, <see cref="GetSchemeNames"/>, <see cref="GetSchemesForCurrentTheme"/>, etc... instead.
31+
/// Use <see cref="AddScheme"/>, <see cref="GetScheme(Drawing.Schemes)"/>, <see cref="GetSchemeNames"/>,
32+
/// <see cref="GetSchemesForCurrentTheme"/>, etc... instead.
2933
/// </summary>
3034
[ConfigurationProperty (Scope = typeof (ThemeScope), OmitClassName = true)]
3135
[JsonConverter (typeof (DictionaryJsonConverter<Scheme?>))]
@@ -54,7 +58,7 @@ public sealed class SchemeManager// : INotifyCollectionChanged, IDictionary<stri
5458
/// <summary>INTERNAL: The set method for <see cref="Schemes"/>.</summary>
5559
[RequiresUnreferencedCode ("Calls Terminal.Gui.ConfigProperty.UpdateFrom(Object)")]
5660
[RequiresDynamicCode ("Calls Terminal.Gui.ConfigProperty.UpdateFrom(Object)")]
57-
private static void SetSchemes (Dictionary<string, Scheme?>? value)
61+
internal static void SetSchemes (Dictionary<string, Scheme?>? value)
5862
{
5963
lock (_schemesLock)
6064
{
@@ -117,6 +121,7 @@ public static Scheme GetScheme (Schemes schemeName)
117121
{
118122
// Convert schemeName to string via Enum api
119123
string? schemeNameString = SchemesToSchemeName (schemeName);
124+
120125
if (schemeNameString is null)
121126
{
122127
throw new ArgumentException ($"Invalid scheme name: {schemeName}");
@@ -131,21 +136,15 @@ public static Scheme GetScheme (Schemes schemeName)
131136
/// <param name="schemeName"></param>
132137
/// <returns></returns>
133138
/// <exception cref="ArgumentException"></exception>
134-
public static Scheme GetScheme (string schemeName)
135-
{
136-
return GetSchemesForCurrentTheme ()! [schemeName]!;
137-
}
139+
public static Scheme GetScheme (string schemeName) { return GetSchemesForCurrentTheme ()! [schemeName]!; }
138140

139141
/// <summary>
140142
/// Gets the name of the specified <see cref="Schemes"/>. Will throw an exception if <paramref name="schemeName"/>
141143
/// is not a built-in Scheme.
142144
/// </summary>
143145
/// <param name="schemeName"></param>
144146
/// <returns>The name of scheme.</returns>
145-
public static string? SchemesToSchemeName (Schemes schemeName)
146-
{
147-
return Enum.GetName (typeof (Schemes), schemeName);
148-
}
147+
public static string? SchemesToSchemeName (Schemes schemeName) { return Enum.GetName (typeof (Schemes), schemeName); }
149148

150149
/// <summary>
151150
/// Converts a string to a <see cref="Schemes"/> enum value.
@@ -158,11 +157,12 @@ public static Scheme GetScheme (string schemeName)
158157
{
159158
return value?.ToString ();
160159
}
160+
161161
return null;
162162
}
163163

164164
/// <summary>
165-
/// Get the dictionary schemes from the selected theme loaded from configuration.
165+
/// Get the dictionary of schemes from the current theme. Current means active.
166166
/// </summary>
167167
/// <returns></returns>
168168
public static Dictionary<string, Scheme?> GetSchemesForCurrentTheme ()
@@ -195,4 +195,14 @@ public static ImmutableList<string> GetSchemeNames ()
195195
return GetSchemes ()!.Keys.ToImmutableList ();
196196
}
197197
}
198+
199+
[RequiresUnreferencedCode ("Calls SetSchemes")]
200+
[RequiresDynamicCode ("Calls SetSchemes")]
201+
internal static void LoadToHardCodedDefaults ()
202+
{
203+
// BUGBUG: SchemeManager is broken and needs to be fixed to not have the hard coded schemes get overwritten.
204+
// BUGBUG: This is a partial workaround
205+
// BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/4288
206+
SetSchemes (GetHardCodedSchemes ()!.ToDictionary ());
207+
}
198208
}

0 commit comments

Comments
 (0)