diff --git a/docs/input/assets/images/custom_exception.png b/docs/input/assets/images/custom_exception.png
new file mode 100644
index 0000000..23b730d
Binary files /dev/null and b/docs/input/assets/images/custom_exception.png differ
diff --git a/docs/input/exceptions.md b/docs/input/exceptions.md
index 3ac7231..14d6bb5 100644
--- a/docs/input/exceptions.md
+++ b/docs/input/exceptions.md
@@ -9,9 +9,9 @@ You can make exception a bit more readable by using the `WriteException` method.
AnsiConsole.WriteException(ex);
```
-
-
+
+## Shortening parts
You can also shorten specific parts of the exception to make it even
more readable, and make paths clickable hyperlinks. Whether or not
@@ -24,3 +24,29 @@ AnsiConsole.WriteException(ex,
```
+
+## Customizing exception output
+
+In addition to shorten specific part of the exception, you can
+also override the default styling.
+
+```csharp
+AnsiConsole.WriteException(ex, new ExceptionSettings
+{
+ Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
+ Style = new ExceptionStyle
+ {
+ Exception = Style.WithForeground(Color.Grey),
+ Message = Style.WithForeground(Color.White),
+ NonEmphasized = Style.WithForeground(Color.Cornsilk1),
+ Parenthesis = Style.WithForeground(Color.Cornsilk1),
+ Method = Style.WithForeground(Color.Red),
+ ParameterName = Style.WithForeground(Color.Cornsilk1),
+ ParameterType = Style.WithForeground(Color.Red),
+ Path = Style.WithForeground(Color.Red),
+ LineNumber = Style.WithForeground(Color.Cornsilk1),
+ }
+});
+```
+
+
diff --git a/docs/input/markup.md b/docs/input/markup.md
index 87f3d22..d3323a7 100644
--- a/docs/input/markup.md
+++ b/docs/input/markup.md
@@ -43,6 +43,12 @@ AnsiConsole.Markup("[[Hello]] "); // [Hello]
AnsiConsole.Markup("[red][[World]][/]"); // [World]
```
+You can also use the `SafeMarkup` extension method.
+
+```csharp
+AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup());
+```
+
# Setting background color
You can set the background color in markup by prefixing the color with
diff --git a/examples/Exceptions/Program.cs b/examples/Exceptions/Program.cs
index 7e10289..1a644cb 100644
--- a/examples/Exceptions/Program.cs
+++ b/examples/Exceptions/Program.cs
@@ -14,11 +14,35 @@ namespace Exceptions
}
catch (Exception ex)
{
+ AnsiConsole.WriteLine();
+ AnsiConsole.Render(new Panel("[u]Default[/]").Expand());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex);
+ AnsiConsole.WriteLine();
+ AnsiConsole.Render(new Panel("[u]Compact[/]").Expand());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
+
+ AnsiConsole.WriteLine();
+ AnsiConsole.Render(new Panel("[u]Custom colors[/]").Expand());
+ AnsiConsole.WriteLine();
+ AnsiConsole.WriteException(ex, new ExceptionSettings
+ {
+ Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
+ Style = new ExceptionStyle
+ {
+ Exception = Style.WithForeground(Color.Grey),
+ Message = Style.WithForeground(Color.White),
+ NonEmphasized = Style.WithForeground(Color.Cornsilk1),
+ Parenthesis = Style.WithForeground(Color.Cornsilk1),
+ Method = Style.WithForeground(Color.Red),
+ ParameterName = Style.WithForeground(Color.Cornsilk1),
+ ParameterType = Style.WithForeground(Color.Red),
+ Path = Style.WithForeground(Color.Red),
+ LineNumber = Style.WithForeground(Color.Cornsilk1),
+ }
+ });
}
}
diff --git a/src/Spectre.Console.Tests/Unit/ColorTests.cs b/src/Spectre.Console.Tests/Unit/ColorTests.cs
index 1e6f1f6..259cd4c 100644
--- a/src/Spectre.Console.Tests/Unit/ColorTests.cs
+++ b/src/Spectre.Console.Tests/Unit/ColorTests.cs
@@ -228,6 +228,39 @@ namespace Spectre.Console.Tests.Unit
}
}
+ public sealed class TheToMarkupMethod
+ {
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Default_Color()
+ {
+ // Given, When
+ var result = Color.Default.ToMarkup();
+
+ // Then
+ result.ShouldBe("default");
+ }
+
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Known_Color()
+ {
+ // Given, When
+ var result = Color.Red.ToMarkup();
+
+ // Then
+ result.ShouldBe("red");
+ }
+
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Custom_Color()
+ {
+ // Given, When
+ var result = new Color(255, 1, 12).ToMarkup();
+
+ // Then
+ result.ShouldBe("#FF010C");
+ }
+ }
+
public sealed class TheToStringMethod
{
[Fact]
diff --git a/src/Spectre.Console.Tests/Unit/StyleTests.cs b/src/Spectre.Console.Tests/Unit/StyleTests.cs
index 9b246ac..f90bde0 100644
--- a/src/Spectre.Console.Tests/Unit/StyleTests.cs
+++ b/src/Spectre.Console.Tests/Unit/StyleTests.cs
@@ -317,5 +317,60 @@ namespace Spectre.Console.Tests.Unit
result.ShouldBeFalse();
}
}
+
+ public sealed class TheToMarkupMethod
+ {
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Style_With_Foreground_Color()
+ {
+ // Given
+ var style = new Style(Color.Red);
+
+ // When
+ var result = style.ToMarkup();
+
+ // Then
+ result.ShouldBe("red");
+ }
+
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color()
+ {
+ // Given
+ var style = new Style(Color.Red, Color.Green);
+
+ // When
+ var result = style.ToMarkup();
+
+ // Then
+ result.ShouldBe("red on green");
+ }
+
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Style_With_Foreground_And_Background_Color_And_Decoration()
+ {
+ // Given
+ var style = new Style(Color.Red, Color.Green, Decoration.Bold | Decoration.Underline);
+
+ // When
+ var result = style.ToMarkup();
+
+ // Then
+ result.ShouldBe("bold underline red on green");
+ }
+
+ [Fact]
+ public void Should_Return_Expected_Markup_For_Style_With_Only_Background_Color()
+ {
+ // Given
+ var style = new Style(background: Color.Green);
+
+ // When
+ var result = style.ToMarkup();
+
+ // Then
+ result.ShouldBe("default on green");
+ }
+ }
}
}
diff --git a/src/Spectre.Console/AnsiConsole.Exceptions.cs b/src/Spectre.Console/AnsiConsole.Exceptions.cs
index e3730a5..133fff1 100644
--- a/src/Spectre.Console/AnsiConsole.Exceptions.cs
+++ b/src/Spectre.Console/AnsiConsole.Exceptions.cs
@@ -16,5 +16,15 @@ namespace Spectre.Console
{
Console.WriteException(exception, format);
}
+
+ ///
+ /// Writes an exception to the console.
+ ///
+ /// The exception to write to the console.
+ /// The exception settings.
+ public static void WriteException(Exception exception, ExceptionSettings settings)
+ {
+ Console.WriteException(exception, settings);
+ }
}
}
diff --git a/src/Spectre.Console/Color.cs b/src/Spectre.Console/Color.cs
index f79d452..434e7cd 100644
--- a/src/Spectre.Console/Color.cs
+++ b/src/Spectre.Console/Color.cs
@@ -249,8 +249,13 @@ namespace Spectre.Console
/// Converts the color to a markup string.
///
/// A representing the color as markup.
- public string ToMarkupString()
+ public string ToMarkup()
{
+ if (IsDefault)
+ {
+ return "default";
+ }
+
if (Number != null)
{
var name = ColorTable.GetName(Number.Value);
diff --git a/src/Spectre.Console/ExceptionSettings.cs b/src/Spectre.Console/ExceptionSettings.cs
new file mode 100644
index 0000000..5b7ff18
--- /dev/null
+++ b/src/Spectre.Console/ExceptionSettings.cs
@@ -0,0 +1,27 @@
+namespace Spectre.Console
+{
+ ///
+ /// Exception settings.
+ ///
+ public sealed class ExceptionSettings
+ {
+ ///
+ /// Gets or sets the exception format.
+ ///
+ public ExceptionFormats Format { get; set; }
+
+ ///
+ /// Gets or sets the exception style.
+ ///
+ public ExceptionStyle Style { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ExceptionSettings()
+ {
+ Format = ExceptionFormats.Default;
+ Style = new ExceptionStyle();
+ }
+ }
+}
diff --git a/src/Spectre.Console/ExceptionStyle.cs b/src/Spectre.Console/ExceptionStyle.cs
new file mode 100644
index 0000000..b144992
--- /dev/null
+++ b/src/Spectre.Console/ExceptionStyle.cs
@@ -0,0 +1,58 @@
+namespace Spectre.Console
+{
+ ///
+ /// Represent an exception style.
+ ///
+ public sealed class ExceptionStyle
+ {
+ ///
+ /// Gets or sets the message color.
+ ///
+ public Style Message { get; set; } = new Style(Color.Red, Color.Default, Decoration.Bold);
+
+ ///
+ /// Gets or sets the exception color.
+ ///
+ public Style Exception { get; set; } = new Style(Color.White);
+
+ ///
+ /// Gets or sets the method color.
+ ///
+ public Style Method { get; set; } = new Style(Color.Yellow);
+
+ ///
+ /// Gets or sets the parameter type color.
+ ///
+ public Style ParameterType { get; set; } = new Style(Color.Blue);
+
+ ///
+ /// Gets or sets the parameter name color.
+ ///
+ public Style ParameterName { get; set; } = new Style(Color.Silver);
+
+ ///
+ /// Gets or sets the parenthesis color.
+ ///
+ public Style Parenthesis { get; set; } = new Style(Color.Silver);
+
+ ///
+ /// Gets or sets the path color.
+ ///
+ public Style Path { get; set; } = new Style(Color.Yellow, Color.Default, Decoration.Bold);
+
+ ///
+ /// Gets or sets the line number color.
+ ///
+ public Style LineNumber { get; set; } = new Style(Color.Blue);
+
+ ///
+ /// Gets or sets the color for dimmed text such as "at" or "in".
+ ///
+ public Style Dimmed { get; set; } = new Style(Color.Grey);
+
+ ///
+ /// Gets or sets the color for non emphasized items.
+ ///
+ public Style NonEmphasized { get; set; } = new Style(Color.Silver);
+ }
+}
diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Exceptions.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Exceptions.cs
index a8a445a..6319a5c 100644
--- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Exceptions.cs
+++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Exceptions.cs
@@ -17,5 +17,16 @@ namespace Spectre.Console
{
Render(console, exception.GetRenderable(format));
}
+
+ ///
+ /// Writes an exception to the console.
+ ///
+ /// The console.
+ /// The exception to write to the console.
+ /// The exception settings.
+ public static void WriteException(this IAnsiConsole console, Exception exception, ExceptionSettings settings)
+ {
+ Render(console, exception.GetRenderable(settings));
+ }
}
}
diff --git a/src/Spectre.Console/Extensions/ExceptionExtensions.cs b/src/Spectre.Console/Extensions/ExceptionExtensions.cs
index 0d2ffda..aa0c0aa 100644
--- a/src/Spectre.Console/Extensions/ExceptionExtensions.cs
+++ b/src/Spectre.Console/Extensions/ExceptionExtensions.cs
@@ -16,7 +16,36 @@ namespace Spectre.Console
/// A representing the exception.
public static IRenderable GetRenderable(this Exception exception, ExceptionFormats format = ExceptionFormats.Default)
{
- return ExceptionFormatter.Format(exception, format);
+ if (exception is null)
+ {
+ throw new ArgumentNullException(nameof(exception));
+ }
+
+ return GetRenderable(exception, new ExceptionSettings
+ {
+ Format = format,
+ });
+ }
+
+ ///
+ /// Gets a representation of the exception.
+ ///
+ /// The exception to format.
+ /// The exception settings.
+ /// A representing the exception.
+ public static IRenderable GetRenderable(this Exception exception, ExceptionSettings settings)
+ {
+ if (exception is null)
+ {
+ throw new ArgumentNullException(nameof(exception));
+ }
+
+ if (settings is null)
+ {
+ throw new ArgumentNullException(nameof(settings));
+ }
+
+ return ExceptionFormatter.Format(exception, settings);
}
}
}
diff --git a/src/Spectre.Console/Internal/DecorationTable.cs b/src/Spectre.Console/Internal/DecorationTable.cs
index f84c4b7..2f2ac32 100644
--- a/src/Spectre.Console/Internal/DecorationTable.cs
+++ b/src/Spectre.Console/Internal/DecorationTable.cs
@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
namespace Spectre.Console.Internal
{
internal static class DecorationTable
{
private static readonly Dictionary _lookup;
+ private static readonly Dictionary _reverseLookup;
[SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")]
static DecorationTable()
@@ -28,6 +30,21 @@ namespace Spectre.Console.Internal
{ "strikethrough", Decoration.Strikethrough },
{ "s", Decoration.Strikethrough },
};
+
+ _reverseLookup = new Dictionary();
+ foreach (var (name, decoration) in _lookup)
+ {
+ // Cannot happen, but the compiler thinks so...
+ if (decoration == null)
+ {
+ continue;
+ }
+
+ if (!_reverseLookup.ContainsKey(decoration.Value))
+ {
+ _reverseLookup[decoration.Value] = name;
+ }
+ }
}
public static Decoration? GetDecoration(string name)
@@ -35,5 +52,23 @@ namespace Spectre.Console.Internal
_lookup.TryGetValue(name, out var result);
return result;
}
+
+ public static List GetMarkupNames(Decoration decoration)
+ {
+ var result = new List();
+
+ Enum.GetValues(typeof(Decoration))
+ .Cast()
+ .Where(flag => (decoration & flag) != 0)
+ .ForEach(flag =>
+ {
+ if (flag != Decoration.None && _reverseLookup.TryGetValue(flag, out var name))
+ {
+ result.Add(name);
+ }
+ });
+
+ return result;
+ }
}
}
diff --git a/src/Spectre.Console/Internal/ExceptionFormatter.cs b/src/Spectre.Console/Internal/ExceptionFormatter.cs
index 2a305b2..8e3ecde 100644
--- a/src/Spectre.Console/Internal/ExceptionFormatter.cs
+++ b/src/Spectre.Console/Internal/ExceptionFormatter.cs
@@ -8,13 +8,7 @@ namespace Spectre.Console
{
internal static class ExceptionFormatter
{
- private static readonly Color _typeColor = Color.White;
- private static readonly Color _methodColor = Color.Yellow;
- private static readonly Color _parameterColor = Color.Blue;
- private static readonly Color _pathColor = Color.Yellow;
- private static readonly Color _dimmedColor = Color.Grey;
-
- public static IRenderable Format(Exception exception, ExceptionFormats format)
+ public static IRenderable Format(Exception exception, ExceptionSettings settings)
{
if (exception is null)
{
@@ -27,10 +21,10 @@ namespace Spectre.Console
return new Text(exception.ToString());
}
- return GetException(info, format);
+ return GetException(info, settings);
}
- private static IRenderable GetException(ExceptionInfo info, ExceptionFormats format)
+ private static IRenderable GetException(ExceptionInfo info, ExceptionSettings settings)
{
if (info is null)
{
@@ -39,20 +33,20 @@ namespace Spectre.Console
return new Rows(new IRenderable[]
{
- GetMessage(info, format),
- GetStackFrames(info, format),
+ GetMessage(info, settings),
+ GetStackFrames(info, settings),
}).Expand();
}
- private static Markup GetMessage(ExceptionInfo ex, ExceptionFormats format)
+ private static Markup GetMessage(ExceptionInfo ex, ExceptionSettings settings)
{
- var shortenTypes = (format & ExceptionFormats.ShortenTypes) != 0;
- var type = Emphasize(ex.Type, new[] { '.' }, _typeColor.ToMarkupString(), shortenTypes);
- var message = $"[b red]{ex.Message.SafeMarkup()}[/]";
+ var shortenTypes = (settings.Format & ExceptionFormats.ShortenTypes) != 0;
+ var type = Emphasize(ex.Type, new[] { '.' }, settings.Style.Exception, shortenTypes, settings);
+ var message = $"[{settings.Style.Message.ToMarkup()}]{ex.Message.SafeMarkup()}[/]";
return new Markup(string.Concat(type, ": ", message));
}
- private static Grid GetStackFrames(ExceptionInfo ex, ExceptionFormats format)
+ private static Grid GetStackFrames(ExceptionInfo ex, ExceptionSettings settings)
{
var grid = new Grid();
grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0).NoWrap());
@@ -63,7 +57,7 @@ namespace Spectre.Console
{
grid.AddRow(
Text.Empty,
- GetException(ex.Inner, format));
+ GetException(ex.Inner, settings));
}
// Stack frames
@@ -72,47 +66,57 @@ namespace Spectre.Console
var builder = new StringBuilder();
// Method
- var shortenMethods = (format & ExceptionFormats.ShortenMethods) != 0;
- builder.Append(Emphasize(frame.Method, new[] { '.' }, _methodColor.ToMarkupString(), shortenMethods));
- builder.Append('(');
- builder.Append(string.Join(", ", frame.Parameters.Select(x => $"[{_parameterColor.ToMarkupString()}]{x.Type.SafeMarkup()}[/] {x.Name}")));
- builder.Append(')');
+ var shortenMethods = (settings.Format & ExceptionFormats.ShortenMethods) != 0;
+ builder.Append(Emphasize(frame.Method, new[] { '.' }, settings.Style.Method, shortenMethods, settings));
+ builder.Append('[').Append(settings.Style.Parenthesis.ToMarkup()).Append(']').Append('(').Append("[/]");
+ AppendParameters(builder, frame, settings);
+ builder.Append('[').Append(settings.Style.Parenthesis.ToMarkup()).Append(']').Append(')').Append("[/]");
if (frame.Path != null)
{
- builder.Append(" [").Append(_dimmedColor.ToMarkupString()).Append("]in[/] ");
+ builder.Append(" [").Append(settings.Style.Dimmed.ToMarkup()).Append("]in[/] ");
// Path
- AppendPath(builder, frame, format);
+ AppendPath(builder, frame, settings);
// Line number
if (frame.LineNumber != null)
{
- builder.Append(':');
- builder.Append('[').Append(_parameterColor.ToMarkupString()).Append(']').Append(frame.LineNumber).Append("[/]");
+ builder.Append('[').Append(settings.Style.Dimmed.ToMarkup()).Append("]:[/]");
+ builder.Append('[').Append(settings.Style.LineNumber.ToMarkup()).Append(']').Append(frame.LineNumber).Append("[/]");
}
}
- grid.AddRow($"[{_dimmedColor.ToMarkupString()}]at[/]", builder.ToString());
+ grid.AddRow(
+ $"[{settings.Style.Dimmed.ToMarkup()}]at[/]",
+ builder.ToString());
}
return grid;
}
- private static void AppendPath(StringBuilder builder, StackFrameInfo frame, ExceptionFormats format)
+ private static void AppendParameters(StringBuilder builder, StackFrameInfo frame, ExceptionSettings settings)
+ {
+ var typeColor = settings.Style.ParameterType.ToMarkup();
+ var nameColor = settings.Style.ParameterName.ToMarkup();
+ var parameters = frame.Parameters.Select(x => $"[{typeColor}]{x.Type.SafeMarkup()}[/] [{nameColor}]{x.Name}[/]");
+ builder.Append(string.Join(", ", parameters));
+ }
+
+ private static void AppendPath(StringBuilder builder, StackFrameInfo frame, ExceptionSettings settings)
{
if (frame?.Path is null)
{
return;
}
- void RenderLink()
+ void AppendPath()
{
- var shortenPaths = (format & ExceptionFormats.ShortenPaths) != 0;
- builder.Append(Emphasize(frame.Path, new[] { '/', '\\' }, $"b {_pathColor.ToMarkupString()}", shortenPaths));
+ var shortenPaths = (settings.Format & ExceptionFormats.ShortenPaths) != 0;
+ builder.Append(Emphasize(frame.Path, new[] { '/', '\\' }, settings.Style.Path, shortenPaths, settings));
}
- if ((format & ExceptionFormats.ShowLinks) != 0)
+ if ((settings.Format & ExceptionFormats.ShowLinks) != 0)
{
var hasLink = frame.TryGetUri(out var uri);
if (hasLink && uri != null)
@@ -120,7 +124,7 @@ namespace Spectre.Console
builder.Append("[link=").Append(uri.AbsoluteUri).Append(']');
}
- RenderLink();
+ AppendPath();
if (hasLink && uri != null)
{
@@ -129,11 +133,11 @@ namespace Spectre.Console
}
else
{
- RenderLink();
+ AppendPath();
}
}
- private static string Emphasize(string input, char[] separators, string color, bool compact)
+ private static string Emphasize(string input, char[] separators, Style color, bool compact, ExceptionSettings settings)
{
var builder = new StringBuilder();
@@ -143,10 +147,12 @@ namespace Spectre.Console
{
if (!compact)
{
- builder.Append("[silver]").Append(type, 0, index + 1).Append("[/]");
+ builder.Append('[').Append(settings.Style.NonEmphasized.ToMarkup()).Append(']')
+ .Append(type, 0, index + 1).Append("[/]");
}
- builder.Append('[').Append(color).Append(']').Append(type, index + 1, type.Length - index - 1).Append("[/]");
+ builder.Append('[').Append(color.ToMarkup()).Append(']')
+ .Append(type, index + 1, type.Length - index - 1).Append("[/]");
}
else
{
diff --git a/src/Spectre.Console/Internal/Extensions/DictionaryExtensions.cs b/src/Spectre.Console/Internal/Extensions/DictionaryExtensions.cs
new file mode 100644
index 0000000..bee3b3d
--- /dev/null
+++ b/src/Spectre.Console/Internal/Extensions/DictionaryExtensions.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace Spectre.Console.Internal
+{
+ internal static class DictionaryExtensions
+ {
+ public static void Deconstruct(this KeyValuePair tuple, out T1 key, out T2 value)
+ {
+ key = tuple.Key;
+ value = tuple.Value;
+ }
+ }
+}
diff --git a/src/Spectre.Console/Style.cs b/src/Spectre.Console/Style.cs
index 4eb7bad..b74993e 100644
--- a/src/Spectre.Console/Style.cs
+++ b/src/Spectre.Console/Style.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using Spectre.Console.Internal;
namespace Spectre.Console
@@ -25,7 +27,7 @@ namespace Spectre.Console
public Decoration Decoration { get; }
///
- /// Gets the link.
+ /// Gets the link associated with the style.
///
public string? Link { get; }
@@ -191,6 +193,41 @@ namespace Spectre.Console
}
}
+ ///
+ /// Returns the markup representation of this style.
+ ///
+ /// The markup representation of this style.
+ public string ToMarkup()
+ {
+ var builder = new List();
+
+ if (Decoration != Decoration.None)
+ {
+ var result = DecorationTable.GetMarkupNames(Decoration);
+ if (result.Count != 0)
+ {
+ builder.AddRange(result);
+ }
+ }
+
+ if (Foreground != Color.Default)
+ {
+ builder.Add(Foreground.ToMarkup());
+ }
+
+ if (Background != Color.Default)
+ {
+ if (builder.Count == 0)
+ {
+ builder.Add("default");
+ }
+
+ builder.Add("on " + Background.ToMarkup());
+ }
+
+ return string.Join(" ", builder);
+ }
+
///
public override bool Equals(object? obj)
{