* touching publish.yml * ColorScheme->Scheme * ColorScheme->Scheme 2 * Prototype of GetAttributeForRole * Badly broke CM * Further Badly broke CM * Refactored CM big-time. View still broken * All unit test pass again. Tons added. CM is still WIP, but Schemes is not mostly refactored and working. * Actually: All unit test pass again. Tons added. CM is still WIP, but Schemes is not mostly refactored and working. * Bug fixes. DeepMemberWiseClone cleanup * Further cleanup of Scope<T>, ConfigProperty, etc. * Made ConfigManager thread safe. * WIP: Broken * WIP: new deep clone impl * WIP: new deep clone impl is done. Now fixing CM * WIP: - config.md - Working on AOT clean up - Core CM is broken; but known. * WIP * Merged. Removed CM from Application.Init * WIP * More WIP; Less broke * All CM unit tests pass... Not sure if it actually works though * All unit tests pass... Themes are broken though in UI Cat * CM Ready for review? * Fixed failures due to TextStyles PR * Working on Scheme/Attribute * Working on Scheme/Attribute 2 * Working on Scheme/Attribute 3 * Working on Scheme/Attribute 4 * Working on Scheme/Attribute 5 * Working on Scheme/Attribute 6 * Added test to show how awful memory usage is * Improved schema. Updated config.json * Nade Scope<T> concurrentdictionary and added test to prove * Made Themes ConcrurrentDictionary. Added bunches of tests * Code cleanup * Code cleanup 2 * Code cleanup 3 * Tweaking Scheme * ClearJsonErrors * ClearJsonErrors2 * Updated Attribute API * It all (mostly) works! * Skip odd unit test * Messed with Themes * Theme tweaks * Code reorg. New .md stuff * Fixed Enabled. Added mock driver * Fixed a bunch of View.Enabled related issues * Scheme -> Get/SetScheme() * Cleanup * Cleanup2 * Broke something * Fixed everything * Made CM.Enable better * Text Style Scenario * Added comments * Fixed UI Catalog Theme Changing * Fixed more dynamic CM update stuff * Warning cleanup * New Default Theme * fixed unit test * Refactoring Scheme and Attribute to fix inheritance * more unit tests * ConfigProperty is not updating schemes correctly * All unit tests pass. Code cleanup * All unit tests pass. Code cleanup2 * Fixed unit tests * Upgraded TextField and TextView * Fixed TextView !Enabled bug * More updates to TextView. More unit tests for SchemeManager * Upgraded CharMap * API docs * Fixe HexView API * upgrade HexView * Fixed shortcut KeyView * Fixed more bugs. Added new themes * updated themes * upgraded Border * Fixed themes memory usage...mostly * Fixed themes memory usage...mostly2 * Fixed themes memory usage...2 * Fixed themes memory usage...3 * Added new colors * Fixed GetHardCodedConfig bug * Added Themes Scenario - WIP * Added Themes Scenario * Tweaked Themes Scenario * Code cleanup * Fixed json schmea * updated deepdives * updated deepdives * Tweaked Themes Scenario * Made Schemes a concurrent dict * Test cleanup * Thread safe ConfigProperty tests * trying to make things more thread safe * more trying to make things more thread safe * Fixing bugs in shadowview * Fixing bugs in shadowview 2 * Refactored GetViewsUnderMouse to GetViewsUnderLocation etc... * Fixed dupe unit tests? * Added better description of layout and coordiantes to deep dive * Added better description of layout and coordiantes to deep dive * Modified tests that call v2.AddTimeout; they were returning true which means restart the timer! This was causing mac/linux unit test failures. I think * Fixed auto scheme. Broke TextView/TextField selection * Realized Attribute.IsExplicitlySet is stupid; just use nullable * Fixed Attribute. Simplified. MOre theme testing * Updated themes again * GetViewsUnderMouse to GetViewsUnderLocation broke TransparentMouse. * Fixing mouseunder bugs * rewriting... * All working again. Shadows are now slick as snot. GetViewsUnderLocation is rewritten to actually work and be readable. Tons more low-level unit tests. Margin is now actually ViewportSettings.Transparent. * Code cleanup * Code cleanup * Code cleanup of color apis * Fixed Hover/Highlight * Update Examples/UICatalog/Scenarios/AllViewsTester.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update Examples/UICatalog/Scenarios/Clipping.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fixed race condition? * reverted * Simplified Attribute API by removing events from SetAttributeForRole * Removed recursion from GetViewsAtLocation * Removed unneeded code * Code clean up. Fixed Scheme bug. * reverted temporary disable * Adjusted scheme algo * Upgraded TextValidateField * Fixed TextValidate bugs * Tweaks * Frameview rounded border by default * API doc cleanup * Readme fix * Addressed tznind feeback * Fixed more unit test issues by protecting Application statics from being set if Application.Initialized is not true * Fixed more unit test issues by protecting Application statics from being set if Application.Initialized is not true 2 * cleanup --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
18 KiB
Configuration Management
Terminal.Gui provides persistent configuration settings via the ConfigurationManager class.
Configuration Lexicon and Taxonomy
| Term | Meaning |
|---|---|
| AppSettings | Application-specific settings stored in the application's resources. |
| Apply | Apply the configuration to the application; copies settings from configuration properties to corresponding static [ConfigProperty] properties. |
| Attribute | Defines concrete visual styling for a visual element (Foreground color, Background color, TextStyle). |
| BackgroundColor | A property of Attribute describing the background text color. |
| Color | Base terminal color (supports TrueColor and named values like White, Black, Cyan, etc.). |
| ConfigProperty | A property decorated with [ConfigProperty] that can be configured via the configuration system. |
| Configuration | A collection of settings defining application behavior and appearance. |
| ConfigurationManager | System that loads and manages application runtime settings from external sources. |
| ForegroundColor | A property of Attribute describing the foreground text color. |
| Load | Load configuration from given location(s), updating with new values. Loading doesn't apply settings automatically. |
| Location | Storage location for configuration (e.g., user's home directory, application directory). |
| Reset | Reset configuration to current values or hard-coded defaults. Does not load configuration. |
| Scope | Defines the context where configuration applies (Settings, Theme, or AppSettings). |
| Scheme | Maps VisualRole to Attribute, defining visual element appearance (color and style) based on semantic purpose. |
| Settings | Runtime options including both system settings and application-specific settings. |
| Sources | Set of locations where configuration can be stored (@Terminal.Gui.ConfigLocations enum). |
| Style | Property of Attribute for font-like hints (bold, italic, underline). |
| Theme | Named instance containing specific appearance settings. |
| ThemeInheritance | Mechanism where themes can inherit and override settings from other themes. |
| Themes | Collection of named Theme definitions bundling visual and layout settings. |
| VisualRole | Semantic role/purpose of a visual element (Normal, Focus, HotFocus, Active, Disabled, ReadOnly). |
Fundamentals
The ConfigurationManager class provides a way to store and retrieve configuration settings for an application. The configuration is stored in JSON documents, which can be located in the user's home directory, the current working directory, in memory, or as a resource within the application's main assembly.
Settings are defined in JSON format, according to this schema: https://gui-cs.github.io/Terminal.GuiV2Docs/schemas/tui-config-schema.json.
Terminal.Gui library developers can define settings in code and set the default values in the Terminal.Gui assembly's resources (e.g. Terminal.Gui.Resources.config.json).
Terminal.Gui application developers can define settings in their apps' code and set the default values in their apps' resources (e.g. Resources/config.json) or by setting @Terminal.Gui.Application.RuntimeConfig to string containing JSON.
Users can change settings on a global or per-application basis by providing JSON formatted configuration files. The configuration files can be placed in at .tui folder in the user's home directory (e.g. C:/Users/username/.tui, or /usr/username/.tui) or the folder where the Terminal.Gui application was launched from (e.g. ./.tui).
CM is Disabled by Default
The ConfigurationManager must be enabled explicitly by calling @Terminal.Gui.ConfigurationManager.Enable() in an application's Main method.
// Enable configuration with all sources
ConfigurationManager.Enable(ConfigLocations.All);
If ConfigurationManager.Enable() is not called (ConfigurationManager.IsEnabled is 'false'), all configuration settings are ignored and ConfigurationManager will effectively be a no-op. All [ConfigurationProperty] properties will initially be their hard-coded default values. Calling @Terminal.Gui.ConfigurationManager.Reset will reset all configuration properties back to their hard-coded default values.
Other than that, no other ConfigurationManager APIs will have any effect.
Loading and Applying Configuration
Optionally, developers can more granularly control the loading and applying of configuration by calling the Load and Apply methods directly.
When a configuration has been loaded, the @Terminal.Gui.ConfigurationManager.Apply method must be called to apply the settings to the application. This method uses reflection to find all static fields decorated with the [ConfigurationProperty] attribute and applies the settings to the corresponding properties.
// Load the configuration from just the users home directory.
ConfigurationManager.Enable(ConfigLocations.HardCoded);
ConfigurationManager.Load(ConfigLocations.GlobalHome);
ConfigurationManager.Apply();
Important
Configuration Settings Apply at the Process Level. Configuration settings are applied at the process level, which means that they are applied to all applications that are part of the same process. This is due to the fact that configuration properties are defined as static fields, which are static for the process.
Configuration Types and Scopes
Terminal.Gui supports three main configuration scopes. See the section below titled What Can Be Configured for more details.
SettingsScope
System-level settings that affect Terminal.Gui behavior:
[ConfigurationProperty (Scope = typeof (SettingsScope))]
public static int MaxSearchResults { get; set; } = 10000;
ThemeScope
Visual appearance settings that can be themed:
[ConfigurationProperty (Scope = typeof (ThemeScope))]
public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
AppSettingsScope (default)
Application-specific settings:
[ConfigurationProperty] // AppSettingsScope is default
public static string MyAppSetting { get; set; } = "default";
Configuration Precedence
graph TD
A[Hard-coded Defaults] --> B[Terminal.Gui Defaults]
B --> C[Runtime Config]
C --> D[App Resources]
D --> E[App Home Directory]
E --> F[App Current Directory]
F --> G[Global Home Directory]
G --> H[Global Current Directory]
Settings are applied using the following precedence (higher precedence settings overwrite lower precedence settings):
-
Hard-coded default values in any static property decorated with the
[ConfigurationProperty]attribute. -
@Terminal.Gui.ConfigLocations.Default - Default settings in the Terminal.Gui assembly -- Lowest precedence.
-
@Terminal.Gui.ConfigLocations.Runtime - Settings stored in the @Terminal.Gui.ConfigurationManager.RuntimeConfig static property.
-
@Terminal.Gui.ConfigLocations.AppResources - App settings in app resources (
Resources/config.json). -
@Terminal.Gui.ConfigLocations.AppHome - App-specific settings in the users's home directory (
~/.tui/appname.config.json). -
@Terminal.Gui.ConfigLocations.AppCurrent - App-specific settings in the directory the app was launched from (
./.tui/appname.config.json). -
@Terminal.Gui.ConfigLocations.GlobalHome - Global settings in the the user's home directory (
~/.tui/config.json). -
@Terminal.Gui.ConfigLocations.GlobalCurrent - Global settings in the directory the app was launched from (
./.tui/config.json) --- Hightest precedence.
The ConfigurationManager will look for configuration files in the .tui folder in the user's home directory (e.g. C:/Users/username/.tui or /usr/username/.tui), the folder where the Terminal.Gui application was launched from (e.g. ./.tui), or as a resource within the Terminal.Gui application's main assembly.
Settings that will apply to all applications (global settings) reside in files named config.json. Settings that will apply to a specific Terminal.Gui application reside in files named appname.config.json, where appname is the assembly name of the application (e.g. UICatalog.config.json).
Configuration Events
The ConfigurationManager provides several events to track configuration changes:
// Called after configuration is applied
ConfigurationManager.Applied += (sender, e) => {
// Handle configuration changes
};
// Called when the active theme changes
ConfigurationManager.ThemeChanged += (sender, e) => {
// Handle theme changes
};
How Settings are Defined
Application developers define settings by decorating static properties with the [ConfigurationProperty] attribute.
class MyApp
{
[ConfigurationProperty]
public static string MySetting { get; set; } = "Default Value";
}
Configuration Properties must be public or internal static properties.
The above example will define a configuration property in the AppSettings scope. The name of the property will be MyApp.MySetting and will appear in JSON as:
{
"AppSettings": {
"MyApp.MySetting": "Default Value"
}
}
AppSettings property names must be globally unique. To ensure this, the name of the AppSettings property is the name of the property prefixed with a period and the full name of the class that holds it. In the example above, the AppSettings property is named MyApp.MySetting.
Terminal.Gui library developers can use the SettingsScope and ThemeScope attributes to define settings and themes for the terminal.Gui library.
[!IMPORTANT] App developers cannot define
SettingScopeorThemeScopeproperties.
/// <summary>
/// Gets or sets whether <see cref="Button"/>s are shown with a shadow effect by default.
/// </summary>
[ConfigurationProperty (Scope = typeof (ThemeScope))]
public static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
Sample Code
The UICatalog application provides an example of how to use the ConfigurationManager class to load and save configuration files.
The Configuration Editor Scenario provides an editor that allows users to edit the configuration files. UI Catalog also uses a file system watcher to detect changes to the configuration files to tell ConfigurationManager to reload them; allowing users to change settings without having to restart the application.
The Themes Scenario in the UI Catalog provides a viewer for the themes defined in the configuration files.
What Can Be Configured
ConfigurationManager provides the following features:
- Settings. Settings are applied to the
Applicationclass. Settings are accessed via theSettingsproperty ofConfigurationManager. E.g.Settings["Application.QuitKey"] - Themes. Themes are a named collection of settings impacting how applications look. The default theme is named "Default". Two other built-in themes are provided: "Dark", and "Light". Additional themes can be defined in the configuration files.
Settings ["Themes"]is a dictionary of theme names to theme settings. - AppSettings. Applications can use the
ConfigurationManagerto store and retrieve application-specific settings.
Methods for discovering what can be configured are available in the ConfigurationManager class:
- Call @ConfigurationManager.GetConfigurationProperties()
- Search the source code for
[ConfigurationProperty] - View
./Terminal.Gui/Resources/config.json
For complete schema details and examples, refer to:
- Schema: https://gui-cs.github.io/Terminal.GuiV2Docs/schemas/tui-config-schema.json
- Default configuration: Terminal.Gui/Resources/config.json
Themes
A Theme is a named collection of settings that impact the visual style of Terminal.Gui applications. The default theme is named "Default". The built-in configuration within the Terminal.Gui library defines two more themes: "Dark", and "Light". Additional themes can be defined in the configuration files. The JSON property Theme defines the name of the theme that will be used. If the theme is not found, the default theme will be used.
Themes support defining Schemes (a set of colors and styles that define the appearance of views) as well as various default settings for Views. Both the default color schemes and user-defined color schemes can be configured. See Schemes for more information.
Theme Configuration
Themes provide a way to bundle visual settings together. When @Terminal.Gui.ConfigurationManager.Apply is called, the theme settings are applied to the application.
// ...
"Dark": {
"Dialog.DefaultButtonAlignment": "End",
"Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems",
"Dialog.DefaultBorderStyle": "Heavy",
"Dialog.DefaultShadow": "Transparent",
"FrameView.DefaultBorderStyle": "Single",
"Window.DefaultBorderStyle": "Single",
"MessageBox.DefaultButtonAlignment": "Center",
"MessageBox.DefaultBorderStyle": "Heavy",
"Button.DefaultShadow": "Opaque",
"Schemes": [
{
"TopLevel": {
"Normal": {
"Foreground": "LightGray",
"Background": "Black",
"Style": "None"
},
// etc...
Only properties that are defined in the theme will be applied, meaning that themes can be used to override the a previously applied theme.
To ensure a theme inherits from the default theme, first apply the default theme, then apply the new theme, like this:
// Apply the default theme
ThemeManager.Theme = "Default";
ConfigurationManager.Apply();
// Apply the new theme
ThemeManager.Theme = "MyCustomTheme";
ConfigurationManager.Apply();
Glyphs
Themes support changing the standard set of glyphs used by views (e.g. the default indicator for Button) and line drawing (e.g. LineCanvas).
The value can be either a decimal number or a string. The string may be:
- A Unicode char (e.g. "☑")
- A hex value in U+ format (e.g. "U+2611")
- A hex value in UTF-16 format (e.g. "\u2611")
"Glyphs.RightArrow": "►",
"Glyphs.LeftArrow": "U+25C4",
"Glyphs.DownArrow": "\\u25BC",
"Glyphs.UpArrow": 965010
The UI Catalog application defines a UICatalog Theme. Look at the UI Catalog's ./Resources/config.json file to see how to define a theme.
Theme and Scheme Management
Terminal.Gui provides two key managers for handling visual themes and schemes:
The ThemeManager provides convenient methods for working with themes:
// Get the currently active theme
ThemeScope currentTheme = ThemeManager.GetCurrentTheme();
// Get all available themes
Dictionary<string, ThemeScope> themes = ThemeManager.GetThemes();
// Get list of theme names
ImmutableList<string> themeNames = ThemeManager.GetThemeNames();
// Get/Set current theme name
string currentThemeName = ThemeManager.GetCurrentThemeName();
ThemeManager.Theme = "Dark"; // Switch themes
// Listen for theme changes
ThemeManager.ThemeChanged += (sender, e) => {
// Handle theme changes
};
SchemeManager
The SchemeManager handles schemes within themes. Each theme contains multiple schemes for different UI contexts:
// Get current schemes
Dictionary<string, Scheme> schemes = SchemeManager.GetCurrentSchemes();
// Get list of scheme names
ImmutableList<string> schemeNames = SchemeManager.GetSchemeNames();
// Access specific schemes
Scheme topLevelScheme = SchemeManager.GetScheme("TopLevel");
// Listen for scheme changes
SchemeManager.CollectionChanged += (sender, e) => {
// Handle scheme changes
};
Built-in Schemes
The following Schemes are available by default:
- TopLevel: Used for the application's top-level windows
- Base: Default scheme for most views
- Dialog: Used for dialogs and message boxes
- Menu: Used for menus and status bars
- Error: Used for error messages and dialogs
Each Scheme defines the attributes for different VisualRoles.
Application Settings
Terminal.Gui provides several top-level application settings:
{
"Key.Separator": "+",
"Application.ArrangeKey": "Ctrl+F5",
"Application.Force16Colors": false,
"Application.IsMouseDisabled": false,
"Application.NextTabGroupKey": "F6",
"Application.NextTabKey": "Tab",
"Application.PrevTabGroupKey": "Shift+F6",
"Application.PrevTabKey": "Shift+Tab",
"Application.QuitKey": "Esc"
}
View-Specific Settings
Examples of settings that control specific view behaviors:
{
"PopoverMenu.DefaultKey": "Shift+F10",
"FileDialog.MaxSearchResults": 10000,
"FileDialogStyle.DefaultUseColors": false,
"FileDialogStyle.DefaultUseUnicodeCharacters": false
}
Key Bindings
Warning
Configuration Manager support for key bindings is not yet implemented.
Key bindings are defined in the KeyBindings property of the configuration file. The value is an array of objects, each object defining a key binding. The key binding object has the following properties:
Key: The key to bind to. The format is a string describing the key (e.g. "q", "Q, "Ctrl+Q"). Function keys are specified as "F1", "F2", etc.
Error Handling
{
"ConfigurationManager.ThrowOnJsonErrors": false
}
Set to true to throw exceptions on JSON parsing errors instead of silent failures.
Configuration File Schema
Settings are defined in JSON format, according to the schema found here:
https://gui-cs.github.io/Terminal.Gui/schemas/tui-config-schema.json
The Default Config File
To illustrate the syntax, the below is the config.json file found in Terminal.Gui.dll:
[!code-jsonconfig.json]