Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions Examples/Themes/code-dark.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://gui-cs.github.io/Terminal.Gui/schemas/tui-config-schema.json",
"Themes": [
{
"Dark": {
"Schemes": [
{
"Base": {
"CodeKeyword": {
"Foreground": "#ff79c6",
"Background": "None",
"Style": "Bold"
},
"CodeString": {
"Foreground": "#f1fa8c",
"Background": "None",
"Style": "None"
}
}
}
]
}
}
]
}
32 changes: 29 additions & 3 deletions Examples/UICatalog/Resources/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,20 @@
"Disabled": {
"Foreground": "BrightGreen",
"Background": "Gray"
}
},
"Code": { "Foreground": "Black", "Background": "#FFFF00", "Style": "None" },
"CodeComment": { "Foreground": "#008000", "Background": "None", "Style": "None" },
"CodeKeyword": { "Foreground": "#FF0000", "Background": "None", "Style": "None" },
"CodeString": { "Foreground": "#0000CC", "Background": "None", "Style": "None" },
"CodeNumber": { "Foreground": "#800080", "Background": "None", "Style": "None" },
"CodeOperator": { "Foreground": "Black", "Background": "None", "Style": "None" },
"CodeType": { "Foreground": "#C00000", "Background": "None", "Style": "None" },
"CodePreprocessor": { "Foreground": "#008000", "Background": "None", "Style": "None" },
"CodeIdentifier": { "Foreground": "Black", "Background": "None", "Style": "None" },
"CodeConstant": { "Foreground": "#800080", "Background": "None", "Style": "None" },
"CodePunctuation": { "Foreground": "Black", "Background": "None", "Style": "None" },
"CodeFunctionName": { "Foreground": "#0000CC", "Background": "None", "Style": "None" },
"CodeAttribute": { "Foreground": "#008000", "Background": "None", "Style": "None" }
}
},
{
Expand Down Expand Up @@ -213,7 +226,20 @@
"Disabled": {
"Foreground": "BrightGreen",
"Background": "Gray"
}
},
"Code": { "Foreground": "White", "Background": "Green", "Style": "None" },
"CodeComment": { "Foreground": "LightGray", "Background": "None", "Style": "None" },
"CodeKeyword": { "Foreground": "Yellow", "Background": "None", "Style": "None" },
"CodeString": { "Foreground": "LightCyan", "Background": "None", "Style": "None" },
"CodeNumber": { "Foreground": "LightYellow", "Background": "None", "Style": "None" },
"CodeOperator": { "Foreground": "White", "Background": "None", "Style": "None" },
"CodeType": { "Foreground": "Cyan", "Background": "None", "Style": "None" },
"CodePreprocessor": { "Foreground": "BrightRed", "Background": "None", "Style": "None" },
"CodeIdentifier": { "Foreground": "White", "Background": "None", "Style": "None" },
"CodeConstant": { "Foreground": "Yellow", "Background": "None", "Style": "None" },
"CodePunctuation": { "Foreground": "White", "Background": "None", "Style": "None" },
"CodeFunctionName": { "Foreground": "LightCyan", "Background": "None", "Style": "None" },
"CodeAttribute": { "Foreground": "LightGray", "Background": "None", "Style": "None" }
}
},
{
Expand Down Expand Up @@ -292,4 +318,4 @@
}
}
]
}
}
159 changes: 159 additions & 0 deletions Examples/UICatalog/Scenarios/CodeViewDemo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
namespace UICatalog.Scenarios;

[ScenarioMetadata ("Code View Demo", "Demonstrates the Code view with theme-aware syntax roles.")]
[ScenarioCategory ("Controls")]
[ScenarioCategory ("Text and Formatting")]
[ScenarioCategory ("Colors")]
public sealed class CodeViewDemo : Scenario
{
private readonly Dictionary<string, string> _snippets = new (StringComparer.OrdinalIgnoreCase)
{
["cs"] = """
#nullable enable
using System;

// Code CodeComment CodeKeyword CodeString
// CodeNumber CodeOperator CodeType CodePreprocessor
// CodeIdentifier CodeConstant CodePunctuation
// CodeFunctionName CodeAttribute
[Obsolete ("CodeAttribute")]
public sealed class Person
{
// CodeComment
private const int CodeNumber = 37;
public string CodeString { get; init; } = "Ada";
public bool CodeConstant => true;
public int CodeFunctionName => Math.Max (CodeNumber, 21 + 16);
}

""",
["json"] = """
{
"roles1": "Code CodeComment CodeKeyword CodeString",
"roles2": "CodeNumber CodeOperator CodeType CodePreprocessor",
"roles3": "CodeIdentifier CodeConstant CodePunctuation",
"roles4": "CodeFunctionName CodeAttribute",
"code": "Code",
"comment": "CodeComment",
"keyword": "CodeKeyword",
"string": "CodeString",
"number": 37,
"operator": "CodeOperator",
"type": "CodeType",
"preprocessor": "CodePreprocessor",
"identifier": "CodeIdentifier",
"constant": true,
"punctuation": "CodePunctuation",
"function": "CodeFunctionName",
"attribute": "CodeAttribute"
}
""",
["xml"] = """
<?xml version="1.0"?>
<!-- Code CodeComment CodeKeyword CodeString -->
<!-- CodeNumber CodeOperator CodeType CodePreprocessor -->
<!-- CodeIdentifier CodeConstant CodePunctuation -->
<!-- CodeFunctionName CodeAttribute -->
<person name="Ada" active="true" CodeAttribute="CodeAttribute">
<age unit="years">37</age>
<roles keyword="CodeKeyword" type="CodeType" function="CodeFunctionName" />
</person>
""",
["md"] = """
# Code view

`VisualRole.CodeKeyword` follows the active theme.

Code CodeComment CodeKeyword CodeString
CodeNumber CodeOperator CodeType CodePreprocessor
CodeIdentifier CodeConstant CodePunctuation
CodeFunctionName CodeAttribute

```cs
#nullable enable
[Obsolete ("CodeAttribute")]
public string CodeString => "Ada"; // CodeComment
public int CodeFunctionName => Math.Max (37, 21 + 16);
```

"""
};

/// <inheritdoc/>
public override void Main ()
{
ConfigurationManager.Enable (ConfigLocations.All);

using IApplication app = Application.Create ();
app.Init ();

using Runnable window = new ();
window.Title = GetQuitKeyAndName ();
window.BorderStyle = LineStyle.None;

string [] languages = ["cs", "json", "xml", "md"];

OptionSelector languageSelector = new ()
{
Title = "_Language",
Labels = languages,
BorderStyle = LineStyle.Rounded,
Width = 16,
Height = Dim.Auto (),
Value = 0
};

string [] themes = ThemeManager.GetThemeNames ().Select (theme => "_" + theme).ToArray ();

OptionSelector themeSelector = new ()
{
Title = "_Theme",
Labels = themes,
BorderStyle = LineStyle.Rounded,
X = Pos.Right (languageSelector) + 1,
Width = 24,
Height = Dim.Auto (),
Value = ThemeManager.GetThemeNames ().IndexOf (ThemeManager.Theme)
};

Code code = new ()
{
X = 0,
Y = Pos.Bottom (themeSelector) + 1,
Width = Dim.Fill (),
Height = Dim.Fill (),
BorderStyle = LineStyle.Rounded,
Title = "Code",
Language = languages [0],
SyntaxHighlighter = new CodeRoleLegendHighlighter (),
Text = _snippets [languages [0]]
};

languageSelector.ValueChanged += (_, args) =>
{
if (args.NewValue is null)
{
return;
}

string language = languages [(int)args.NewValue];
code.Language = language;
code.Text = _snippets [language];
};

themeSelector.ValueChanged += (_, args) =>
{
if (args.NewValue is null)
{
return;
}

string theme = themes [(int)args.NewValue] [1..];
ThemeManager.Theme = theme;
ConfigurationManager.Apply ();
};

window.Add (languageSelector, themeSelector, code);
app.Run (window);
}
}
57 changes: 56 additions & 1 deletion Examples/UICatalog/Scenarios/Themes.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable

using System.Collections.ObjectModel;

// ReSharper disable AccessToDisposedClosure

namespace UICatalog.Scenarios;
Expand Down Expand Up @@ -52,6 +53,29 @@ public override void Main ()
};
defaultAttributeView.Border.Thickness = new Thickness (0, 1, 0, 0);

FrameView codeRolesPanel = CreateCodeRolesPanel ();
codeRolesPanel.Y = Pos.Bottom (defaultAttributeView);
codeRolesPanel.Width = Dim.Width (themeOptionSelector);

Markdown codeRolesMarkdown = new ()
{
Title = "Code Fence",
BorderStyle = LineStyle.Rounded,
Y = Pos.Bottom (codeRolesPanel),
Width = Dim.Width (themeOptionSelector),
Height = 8,
SyntaxHighlighter = new TextMateSyntaxHighlighter (),
Text = """
```cs
public sealed class Demo
{
string Text => "theme";
}
```
"""
};
codeRolesMarkdown.Border.Thickness = new Thickness (0, 1, 0, 0);

themeOptionSelector.ValueChanged += (sender, args) =>
{
if (sender is not OptionSelector optionSelector)
Expand Down Expand Up @@ -129,7 +153,15 @@ public override void Main ()
viewPropertiesEditor.ViewToEdit = _view;
};

appWindow.Add (themeOptionSelector, defaultAttributeView, themeViewer, allViewsCheckBox, viewListView, viewPropertiesEditor, viewFrame);
appWindow.Add (themeOptionSelector,
defaultAttributeView,
codeRolesPanel,
codeRolesMarkdown,
themeViewer,
allViewsCheckBox,
viewListView,
viewPropertiesEditor,
viewFrame);

viewListView.SelectedItem = 0;

Expand Down Expand Up @@ -203,6 +235,29 @@ private static List<Type> GetAllViewClassesCollection ()
return types;
}

private static FrameView CreateCodeRolesPanel ()
{
FrameView panel = new () { Title = "Code roles", BorderStyle = LineStyle.Rounded, Height = Dim.Auto () };
panel.Border.Thickness = new Thickness (0, 1, 0, 0);

VisualRoleViewer? previous = null;

foreach (VisualRole role in Enum.GetValues<VisualRole> ().Where (role => role >= VisualRole.Code))
{
VisualRoleViewer roleViewer = new () { Role = role, SchemeName = "Base" };

if (previous is { })
{
roleViewer.Y = Pos.Bottom (previous);
}

panel.Add (roleViewer);
previous = roleViewer;
}

return panel;
}

private View? CreateView (Type type)
{
// If we are to create a generic Type
Expand Down
22 changes: 17 additions & 5 deletions Terminal.Gui/Configuration/SchemeJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,23 @@ public override Scheme Read (ref Utf8JsonReader reader, Type typeToConvert, Json
"hotactive" => scheme with { HotActive = attribute },
"highlight" => scheme with { Highlight = attribute },
"editable" => scheme with { Editable = attribute },
"readonly" => scheme with { ReadOnly = attribute },
"disabled" => scheme with { Disabled = attribute },
"code" => scheme with { Code = attribute },
_ => throw new JsonException ($"{propertyName}: Unrecognized Scheme Attribute name.")
};
"readonly" => scheme with { ReadOnly = attribute },
"disabled" => scheme with { Disabled = attribute },
"code" => scheme with { Code = attribute },
"codecomment" => scheme with { CodeComment = attribute },
"codekeyword" => scheme with { CodeKeyword = attribute },
"codestring" => scheme with { CodeString = attribute },
"codenumber" => scheme with { CodeNumber = attribute },
"codeoperator" => scheme with { CodeOperator = attribute },
"codetype" => scheme with { CodeType = attribute },
"codepreprocessor" => scheme with { CodePreprocessor = attribute },
"codeidentifier" => scheme with { CodeIdentifier = attribute },
"codeconstant" => scheme with { CodeConstant = attribute },
"codepunctuation" => scheme with { CodePunctuation = attribute },
"codefunctionname" => scheme with { CodeFunctionName = attribute },
"codeattribute" => scheme with { CodeAttribute = attribute },
_ => throw new JsonException ($"{propertyName}: Unrecognized Scheme Attribute name.")
};
}
else
{
Expand Down
Loading
Loading