Fixes #4885. View.GetScheme() falls back gracefully instead of throwing when SchemeName is not found#4886
Merged
tig merged 7 commits intogui-cs:developfrom Apr 8, 2026
Conversation
…etScheme()
Add SchemeManager.TryGetScheme() — a non-throwing scheme lookup that safely
handles uninitialized ConfigurationManager and missing Schemes in the current
theme (both cases that GetSchemesForCurrentTheme() throws for).
Refactor View.GetScheme() DefaultAction to use the full fallback chain in all
cases, removing the asymmetry where a SchemeName pointing to a missing scheme
threw KeyNotFoundException while no SchemeName gracefully fell back:
HasScheme (_scheme)
-> Named scheme via TryGetScheme(SchemeName)
-> SuperView.GetScheme()
-> 'Base' scheme
-> Hard-coded 'Base' (guaranteed last resort)
Add Logging.Warning() when SchemeName is set but not found, to aid debugging.
Add tests covering: TryGetScheme happy/sad paths, fallback to SuperView,
fallback to Base, and full chain traversal with missing scheme at every level.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…k chain - Registers a custom 'CustomHighlight' scheme with TextStyle.Blink on the Default theme, making it visually distinct from built-in schemes - Shows a view with SchemeName = 'CustomHighlight' (found on Default, blinks) - Shows a view with SchemeName = 'NonExistentScheme' (never found, falls back) - Includes a theme selector: switching to a non-Default theme causes 'CustomHighlight' to also fall back, demonstrating both fallback cases live - The warning written to the debug log for missing scheme names is mentioned in the UI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Collaborator
Author
tig
approved these changes
Apr 8, 2026
Collaborator
tig
left a comment
There was a problem hiding this comment.
Excellent!
I effed up on an earlier merge to develop and introduced a bug to UICatalog. I pulled your branch down to review and noticed that. So I fixed it in your branch and pushed that and some code cleanup changes too.
…d didn't test... Refactor style, naming, and shortcut logic for consistency Refactored constant naming and string interpolation in ThemeFallback for clarity and consistency. Improved XML documentation formatting. Updated UICatalogRunnable shortcut key assignment to avoid conflicts and accept ignored keys. Fixed GetScheme logic in View to handle empty SchemeName correctly. Replaced var with explicit types and used collection expressions in tests. Improved lambda formatting and simplified event handler assignments. Applied project code style conventions throughout.
Contributor
There was a problem hiding this comment.
Pull request overview
Implements a non-throwing scheme resolution path so View.GetScheme() gracefully falls back when SchemeName is missing from the active theme (Fixes #4885), while preserving existing throwing APIs for backwards compatibility.
Changes:
- Added
SchemeManager.TryGetScheme(string, out Scheme?)to safely resolve schemes without exceptions. - Updated
View.GetScheme()to useTryGetSchemeplus a fallback chain (SuperView → theme “Base” → hard-coded “Base”) and emit a warning when falling back. - Added/updated tests and introduced a new UICatalog scenario to demonstrate the fallback behavior live.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/UnitTestsParallelizable/ViewBase/Draw/SchemeTests.cs | Adds fallback-chain tests and refactors some locals/types. |
| Tests/UnitTestsParallelizable/Configuration/SourcesManagerTests.cs | Minor test refactors/cleanup unrelated to schemes. |
| Tests/UnitTestsParallelizable/Configuration/SchemeManagerTests.cs | Adds tests for TryGetScheme behavior. |
| Terminal.Gui/ViewBase/View.Drawing.Scheme.cs | Implements GetScheme() fallback chain + warning logging. |
| Terminal.Gui/Configuration/SchemeManager.cs | Adds TryGetScheme API and updates exception docs for GetScheme(string). |
| Examples/UICatalog/UICatalogRunnable.cs | Adjusts unbound F-key selection logic for StatusBar/menu usage. |
| Examples/UICatalog/Scenarios/ThemeFallback.cs | New scenario demonstrating missing-scheme fallback behavior across theme changes. |
YourRobotOverlord
added a commit
to YourRobotOverlord/Terminal.Gui
that referenced
this pull request
Apr 10, 2026
…g.md Document PR gui-cs#4886 functionality in config.md: - Add 'Custom Schemes for Individual Views' section showing View.SchemeName, SchemeManager.AddScheme(), and JSON config definition of custom schemes - Add 'Scheme Resolution Order' section with Mermaid flowchart of the View.GetScheme() fallback chain (HasScheme -> SchemeName -> SuperView -> Base theme -> hard-coded Base) and priority table - Note SchemeManager.TryGetScheme() as the safe consumer API Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #4885.
Summary
When
View.SchemeNameis set to a name that doesn't exist in the active theme,View.GetScheme()previously threw aKeyNotFoundException. This PR implements a graceful fallback chain so the view degrades silently instead of crashing.Fallback Chain
If the named scheme is not found, resolution continues through:
SuperView.GetScheme()— inherit from the parent view (recursive)"Base"scheme from the active theme"Base"— always available regardless of config stateA
Logging.Warningis emitted when a fallback occurs so developers can diagnose misconfiguredSchemeNamevalues.Changes
SchemeManager— newTryGetSchememethodcsharp public static bool TryGetScheme(string schemeName, [NotNullWhen(true)] out Scheme? scheme)Fully exception-safe: handles an uninitialised
ConfigurationManagerand a theme with noSchemesproperty, returningfalsein both cases.GetScheme(string)is left unchanged (backward compat — it still throws).View.GetScheme()— use fallback chainReplaced the direct
SchemeManager.GetScheme(SchemeName)call (which throws) withTryGetScheme+ResolveFallbackScheme().UICatalog scenario — Theme Fallback
New demo scenario (
Examples/UICatalog/Scenarios/ThemeFallback.cs) showing:SchemeName = "CustomHighlight"(exists on Default, blinking yellow/blue)SchemeName = "NonExistentScheme"(never exists, always falls back)Tests
7 new tests across two files — all in
UnitTestsParallelizable:SchemeManagerTests.csTryGetSchemehappy path, missing scheme, CM-not-initialisedSchemeTests.csAll 15,163 existing tests pass; no new warnings.