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
49 changes: 48 additions & 1 deletion src/Spectre.Console.Tests/Unit/Widgets/MarkupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,51 @@ public void Can_Use_Interpolated_Markup_As_IRenderable()
└─────────────────┘
".NormalizeLineEndings());
}
}
[Fact]
public void MarkupInterpolated_Should_Not_Throw_When_Object_ToString_Contains_Brackets()
{
// Given
var console = new TestConsole();
var obj = new CoolThing();

// When
Exception ex = Record.Exception(() => console.MarkupInterpolated($"This is a {obj}"));

// Then
ex.ShouldBeNull();
console.Output.NormalizeLineEndings().ShouldBe("This is a This[contains, braces].");
}

[Fact]
public void MarkupInterpolated_Should_Preserve_Null_For_Custom_Formatter()
{
// Given
var console = new TestConsole();
string? value = null;

// When
Exception ex = Record.Exception(() => console.MarkupInterpolated(new NullAwareFormatProvider(), $"Value: {value}"));

// Then
ex.ShouldBeNull();
console.Output.NormalizeLineEndings().ShouldBe("Value: <null>");
}

private class CoolThing
{
public override string ToString() => "This[contains, braces].";
}

private sealed class NullAwareFormatProvider : IFormatProvider, ICustomFormatter
{
public object? GetFormat(Type? formatType)
{
return formatType == typeof(ICustomFormatter) ? this : null;
}

public string Format(string? format, object? arg, IFormatProvider? formatProvider)
{
return arg is null ? "<null>" : arg.ToString() ?? string.Empty;
}
}
}
12 changes: 10 additions & 2 deletions src/Spectre.Console/Widgets/Markup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,15 @@ public static string Remove(string text)

internal static string EscapeInterpolated(IFormatProvider provider, FormattableString value)
{
object?[] args = value.GetArguments().Select(arg => arg is string s ? s.EscapeMarkup() : arg).ToArray();
object?[] args = value.GetArguments()
.Select(arg => arg switch
{
null => null,
string text => text.EscapeMarkup(),
IFormattable => arg,
_ => arg.ToString()?.EscapeMarkup(),
})
.ToArray();
return string.Format(provider, value.Format, args);
}
}
}