diff --git a/src/Spectre.Console.Testing/TestConsoleExtensions.cs b/src/Spectre.Console.Testing/TestConsoleExtensions.cs
index 59d9c1a..eb3f441 100644
--- a/src/Spectre.Console.Testing/TestConsoleExtensions.cs
+++ b/src/Spectre.Console.Testing/TestConsoleExtensions.cs
@@ -17,6 +17,18 @@ namespace Spectre.Console.Testing
return console;
}
+ ///
+ /// Sets whether or not ANSI is supported.
+ ///
+ /// The console.
+ /// Whether or not VT/ANSI control codes are supported.
+ /// The same instance so that multiple calls can be chained.
+ public static TestConsole SupportsAnsi(this TestConsole console, bool enable)
+ {
+ console.Profile.Capabilities.Ansi = enable;
+ return console;
+ }
+
///
/// Makes the console interactive.
///
diff --git a/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs
new file mode 100644
index 0000000..3d23c64
--- /dev/null
+++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs
@@ -0,0 +1,47 @@
+using Shouldly;
+using Spectre.Console.Advanced;
+using Spectre.Console.Testing;
+using Xunit;
+
+namespace Spectre.Console.Tests.Unit
+{
+ public partial class AnsiConsoleTests
+ {
+ public sealed class Advanced
+ {
+ [Fact]
+ public void Should_Write_Ansi_Codes_To_Console_If_Supported()
+ {
+ // Given
+ var console = new TestConsole()
+ .SupportsAnsi(true)
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
+
+ // When
+ console.WriteAnsi("[101mHello[0m");
+
+ // Then
+ console.Output.NormalizeLineEndings()
+ .ShouldBe("[101mHello[0m");
+ }
+
+ [Fact]
+ public void Should_Not_Write_Ansi_Codes_To_Console_If_Not_Supported()
+ {
+ // Given
+ var console = new TestConsole()
+ .SupportsAnsi(false)
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
+
+ // When
+ console.WriteAnsi("[101mHello[0m");
+
+ // Then
+ console.Output.NormalizeLineEndings()
+ .ShouldBeEmpty();
+ }
+ }
+ }
+}
diff --git a/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
index fc06cfb..528b87e 100644
--- a/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
+++ b/src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
@@ -7,103 +7,109 @@ namespace Spectre.Console.Tests.Unit
{
public partial class AnsiConsoleTests
{
- [Theory]
- [InlineData(false, "Hello[2J[3JWorld")]
- [InlineData(true, "Hello[2J[3J[1;1HWorld")]
- public void Should_Clear_Screen(bool home, string expected)
+ public sealed class Clear
{
- // Given
- var console = new TestConsole()
- .Colors(ColorSystem.Standard)
- .EmitAnsiSequences();
+ [Theory]
+ [InlineData(false, "Hello[2J[3JWorld")]
+ [InlineData(true, "Hello[2J[3J[1;1HWorld")]
+ public void Should_Clear_Screen(bool home, string expected)
+ {
+ // Given
+ var console = new TestConsole()
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
- // When
- console.Write("Hello");
- console.Clear(home);
- console.Write("World");
+ // When
+ console.Write("Hello");
+ console.Clear(home);
+ console.Write("World");
- // Then
- console.Output.ShouldBe(expected);
+ // Then
+ console.Output.ShouldBe(expected);
+ }
}
- [Fact]
- public void Should_Combine_Decoration_And_Colors()
+ public sealed class Write
{
- // Given
- var console = new TestConsole()
- .Colors(ColorSystem.Standard)
- .EmitAnsiSequences();
+ [Fact]
+ public void Should_Combine_Decoration_And_Colors()
+ {
+ // Given
+ var console = new TestConsole()
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
- // When
- console.Write(
- "Hello",
- new Style()
- .Foreground(Color.RoyalBlue1)
- .Background(Color.NavajoWhite1)
- .Decoration(Decoration.Italic));
+ // When
+ console.Write(
+ "Hello",
+ new Style()
+ .Foreground(Color.RoyalBlue1)
+ .Background(Color.NavajoWhite1)
+ .Decoration(Decoration.Italic));
- // Then
- console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m");
- }
+ // Then
+ console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m");
+ }
- [Fact]
- public void Should_Not_Include_Foreground_If_Set_To_Default_Color()
- {
- // Given
- var console = new TestConsole()
- .Colors(ColorSystem.Standard)
- .EmitAnsiSequences();
+ [Fact]
+ public void Should_Not_Include_Foreground_If_Set_To_Default_Color()
+ {
+ // Given
+ var console = new TestConsole()
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
- // When
- console.Write(
- "Hello",
- new Style()
- .Foreground(Color.Default)
- .Background(Color.NavajoWhite1)
- .Decoration(Decoration.Italic));
+ // When
+ console.Write(
+ "Hello",
+ new Style()
+ .Foreground(Color.Default)
+ .Background(Color.NavajoWhite1)
+ .Decoration(Decoration.Italic));
- // Then
- console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m");
- }
+ // Then
+ console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m");
+ }
- [Fact]
- public void Should_Not_Include_Background_If_Set_To_Default_Color()
- {
- // Given
- var console = new TestConsole()
- .Colors(ColorSystem.Standard)
- .EmitAnsiSequences();
+ [Fact]
+ public void Should_Not_Include_Background_If_Set_To_Default_Color()
+ {
+ // Given
+ var console = new TestConsole()
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
- // When
- console.Write(
- "Hello",
- new Style()
- .Foreground(Color.RoyalBlue1)
- .Background(Color.Default)
- .Decoration(Decoration.Italic));
+ // When
+ console.Write(
+ "Hello",
+ new Style()
+ .Foreground(Color.RoyalBlue1)
+ .Background(Color.Default)
+ .Decoration(Decoration.Italic));
- // Then
- console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m");
- }
+ // Then
+ console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m");
+ }
- [Fact]
- public void Should_Not_Include_Decoration_If_Set_To_None()
- {
- // Given
- var console = new TestConsole()
- .Colors(ColorSystem.Standard)
- .EmitAnsiSequences();
+ [Fact]
+ public void Should_Not_Include_Decoration_If_Set_To_None()
+ {
+ // Given
+ var console = new TestConsole()
+ .Colors(ColorSystem.Standard)
+ .EmitAnsiSequences();
- // When
- console.Write(
- "Hello",
- new Style()
- .Foreground(Color.RoyalBlue1)
- .Background(Color.NavajoWhite1)
- .Decoration(Decoration.None));
+ // When
+ console.Write(
+ "Hello",
+ new Style()
+ .Foreground(Color.RoyalBlue1)
+ .Background(Color.NavajoWhite1)
+ .Decoration(Decoration.None));
- // Then
- console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
+ // Then
+ console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
+ }
}
public sealed class WriteLine
diff --git a/src/Spectre.Console/Capabilities.cs b/src/Spectre.Console/Capabilities.cs
index 2c367b8..3419640 100644
--- a/src/Spectre.Console/Capabilities.cs
+++ b/src/Spectre.Console/Capabilities.cs
@@ -16,7 +16,7 @@ namespace Spectre.Console
///
/// Gets or sets a value indicating whether or not
- /// the console supports Ansi.
+ /// the console supports VT/ANSI control codes.
///
public bool Ansi { get; set; }
diff --git a/src/Spectre.Console/Extensions/Advanced/AnsiConsoleExtensions.cs b/src/Spectre.Console/Extensions/Advanced/AnsiConsoleExtensions.cs
new file mode 100644
index 0000000..cf54473
--- /dev/null
+++ b/src/Spectre.Console/Extensions/Advanced/AnsiConsoleExtensions.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Spectre.Console.Advanced
+{
+ ///
+ /// Contains extension methods for .
+ ///
+ public static class AnsiConsoleExtensions
+ {
+ ///
+ /// Writes a VT/Ansi control code sequence to the console (if supported).
+ ///
+ /// The console to write to.
+ /// The VT/Ansi control code sequence to write.
+ public static void WriteAnsi(this IAnsiConsole console, string sequence)
+ {
+ if (console is null)
+ {
+ throw new ArgumentNullException(nameof(console));
+ }
+
+ if (console.Profile.Capabilities.Ansi)
+ {
+ console.Write(new ControlCode(sequence));
+ }
+ }
+ }
+}
diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs
index e57b4df..b91b813 100644
--- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs
+++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs
@@ -38,6 +38,11 @@ namespace Spectre.Console
/// The text to write.
public static void Write(this IAnsiConsole console, string text)
{
+ if (console is null)
+ {
+ throw new ArgumentNullException(nameof(console));
+ }
+
console.Write(new Text(text, Style.Plain));
}
@@ -49,6 +54,11 @@ namespace Spectre.Console
/// The text style.
public static void Write(this IAnsiConsole console, string text, Style style)
{
+ if (console is null)
+ {
+ throw new ArgumentNullException(nameof(console));
+ }
+
console.Write(new Text(text, style));
}
diff --git a/src/Spectre.Console/IReadOnlyCapabilities.cs b/src/Spectre.Console/IReadOnlyCapabilities.cs
index 340f338..75380ac 100644
--- a/src/Spectre.Console/IReadOnlyCapabilities.cs
+++ b/src/Spectre.Console/IReadOnlyCapabilities.cs
@@ -14,7 +14,7 @@ namespace Spectre.Console
///
/// Gets a value indicating whether or not
- /// the console supports Ansi.
+ /// the console supports VT/ANSI control codes.
///
bool Ansi { get; }
diff --git a/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleBackend.cs b/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleBackend.cs
index 72addb5..e278393 100644
--- a/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleBackend.cs
+++ b/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleBackend.cs
@@ -22,12 +22,12 @@ namespace Spectre.Console
public void Clear(bool home)
{
- Write(new ControlSequence(ED(2)));
- Write(new ControlSequence(ED(3)));
+ Write(new ControlCode(ED(2)));
+ Write(new ControlCode(ED(3)));
if (home)
{
- Write(new ControlSequence(CUP(1, 1)));
+ Write(new ControlCode(CUP(1, 1)));
}
}
diff --git a/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleCursor.cs b/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleCursor.cs
index 9c6aa8c..4fbb8f8 100644
--- a/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleCursor.cs
+++ b/src/Spectre.Console/Internal/Backends/Ansi/AnsiConsoleCursor.cs
@@ -16,11 +16,11 @@ namespace Spectre.Console
{
if (show)
{
- _backend.Write(new ControlSequence(SM(DECTCEM)));
+ _backend.Write(new ControlCode(SM(DECTCEM)));
}
else
{
- _backend.Write(new ControlSequence(RM(DECTCEM)));
+ _backend.Write(new ControlCode(RM(DECTCEM)));
}
}
@@ -34,23 +34,23 @@ namespace Spectre.Console
switch (direction)
{
case CursorDirection.Up:
- _backend.Write(new ControlSequence(CUU(steps)));
+ _backend.Write(new ControlCode(CUU(steps)));
break;
case CursorDirection.Down:
- _backend.Write(new ControlSequence(CUD(steps)));
+ _backend.Write(new ControlCode(CUD(steps)));
break;
case CursorDirection.Right:
- _backend.Write(new ControlSequence(CUF(steps)));
+ _backend.Write(new ControlCode(CUF(steps)));
break;
case CursorDirection.Left:
- _backend.Write(new ControlSequence(CUB(steps)));
+ _backend.Write(new ControlCode(CUB(steps)));
break;
}
}
public void SetPosition(int column, int line)
{
- _backend.Write(new ControlSequence(CUP(line, column)));
+ _backend.Write(new ControlCode(CUP(line, column)));
}
}
}
diff --git a/src/Spectre.Console/Rendering/LiveRenderable.cs b/src/Spectre.Console/Rendering/LiveRenderable.cs
index 582f16a..e3199c9 100644
--- a/src/Spectre.Console/Rendering/LiveRenderable.cs
+++ b/src/Spectre.Console/Rendering/LiveRenderable.cs
@@ -25,11 +25,11 @@ namespace Spectre.Console.Rendering
{
if (_shape == null)
{
- return new ControlSequence(string.Empty);
+ return new ControlCode(string.Empty);
}
var linesToMoveUp = _shape.Value.Height - 1;
- return new ControlSequence("\r" + CUU(linesToMoveUp));
+ return new ControlCode("\r" + CUU(linesToMoveUp));
}
}
@@ -39,11 +39,11 @@ namespace Spectre.Console.Rendering
{
if (_shape == null)
{
- return new ControlSequence(string.Empty);
+ return new ControlCode(string.Empty);
}
var linesToClear = _shape.Value.Height - 1;
- return new ControlSequence("\r" + EL(2) + (CUU(1) + EL(2)).Repeat(linesToClear));
+ return new ControlCode("\r" + EL(2) + (CUU(1) + EL(2)).Repeat(linesToClear));
}
}
diff --git a/src/Spectre.Console/Rendering/RenderContext.cs b/src/Spectre.Console/Rendering/RenderContext.cs
index b4ffff1..be18254 100644
--- a/src/Spectre.Console/Rendering/RenderContext.cs
+++ b/src/Spectre.Console/Rendering/RenderContext.cs
@@ -14,6 +14,11 @@ namespace Spectre.Console.Rendering
///
public ColorSystem ColorSystem => _capabilities.ColorSystem;
+ ///
+ /// Gets a value indicating whether or not VT/Ansi codes are supported.
+ ///
+ public bool Ansi => _capabilities.Ansi;
+
///
/// Gets a value indicating whether or not unicode is supported.
///
diff --git a/src/Spectre.Console/Widgets/ControlSequence.cs b/src/Spectre.Console/Widgets/ControlCode.cs
similarity index 71%
rename from src/Spectre.Console/Widgets/ControlSequence.cs
rename to src/Spectre.Console/Widgets/ControlCode.cs
index a577f15..45c4398 100644
--- a/src/Spectre.Console/Widgets/ControlSequence.cs
+++ b/src/Spectre.Console/Widgets/ControlCode.cs
@@ -3,11 +3,11 @@ using Spectre.Console.Rendering;
namespace Spectre.Console
{
- internal sealed class ControlSequence : Renderable
+ internal sealed class ControlCode : Renderable
{
private readonly Segment _segment;
- public ControlSequence(string control)
+ public ControlCode(string control)
{
_segment = Segment.Control(control);
}
@@ -19,7 +19,10 @@ namespace Spectre.Console
protected override IEnumerable Render(RenderContext context, int maxWidth)
{
- yield return _segment;
+ if (context.Ansi)
+ {
+ yield return _segment;
+ }
}
}
}
diff --git a/src/Spectre.Console/Widgets/Progress/ProgressContext.cs b/src/Spectre.Console/Widgets/Progress/ProgressContext.cs
index b7dcf41..9b9510f 100644
--- a/src/Spectre.Console/Widgets/Progress/ProgressContext.cs
+++ b/src/Spectre.Console/Widgets/Progress/ProgressContext.cs
@@ -73,7 +73,7 @@ namespace Spectre.Console
public void Refresh()
{
_renderer.Update(this);
- _console.Write(new ControlSequence(string.Empty));
+ _console.Write(new ControlCode(string.Empty));
}
internal IReadOnlyList GetTasks()
diff --git a/src/Spectre.Console/Widgets/Prompt/Rendering/RenderableList.cs b/src/Spectre.Console/Widgets/Prompt/Rendering/RenderableList.cs
index 93cd7f2..13a327d 100644
--- a/src/Spectre.Console/Widgets/Prompt/Rendering/RenderableList.cs
+++ b/src/Spectre.Console/Widgets/Prompt/Rendering/RenderableList.cs
@@ -38,7 +38,7 @@ namespace Spectre.Console
public void Redraw()
{
- _console.Write(new ControlSequence(string.Empty));
+ _console.Write(new ControlCode(string.Empty));
}
public bool Update(ConsoleKey key)