mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 08:52:50 +08:00
Add method to write VT/ANSI control codes
Adds a new extension method IAnsiConsole.WriteAnsi that writes VT/ANSI control codes to the console. If VT/ANSI control codes are not supported, nothing will be written.
This commit is contained in:
parent
91f910326c
commit
3463dde543
@ -17,6 +17,18 @@ namespace Spectre.Console.Testing
|
||||
return console;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether or not ANSI is supported.
|
||||
/// </summary>
|
||||
/// <param name="console">The console.</param>
|
||||
/// <param name="enable">Whether or not VT/ANSI control codes are supported.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static TestConsole SupportsAnsi(this TestConsole console, bool enable)
|
||||
{
|
||||
console.Profile.Capabilities.Ansi = enable;
|
||||
return console;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the console interactive.
|
||||
/// </summary>
|
||||
|
47
src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs
Normal file
47
src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Advanced.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ using Xunit;
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
public sealed class Clear
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(false, "Hello[2J[3JWorld")]
|
||||
@ -25,7 +27,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
// Then
|
||||
console.Output.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Write
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Combine_Decoration_And_Colors()
|
||||
{
|
||||
@ -105,6 +110,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// Then
|
||||
console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WriteLine
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace Spectre.Console
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not
|
||||
/// the console supports Ansi.
|
||||
/// the console supports VT/ANSI control codes.
|
||||
/// </summary>
|
||||
public bool Ansi { get; set; }
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Advanced
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes a VT/Ansi control code sequence to the console (if supported).
|
||||
/// </summary>
|
||||
/// <param name="console">The console to write to.</param>
|
||||
/// <param name="sequence">The VT/Ansi control code sequence to write.</param>
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -38,6 +38,11 @@ namespace Spectre.Console
|
||||
/// <param name="text">The text to write.</param>
|
||||
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
|
||||
/// <param name="style">The text style.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace Spectre.Console
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not
|
||||
/// the console supports Ansi.
|
||||
/// the console supports VT/ANSI control codes.
|
||||
/// </summary>
|
||||
bool Ansi { get; }
|
||||
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,11 @@ namespace Spectre.Console.Rendering
|
||||
/// </summary>
|
||||
public ColorSystem ColorSystem => _capabilities.ColorSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not VT/Ansi codes are supported.
|
||||
/// </summary>
|
||||
public bool Ansi => _capabilities.Ansi;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not unicode is supported.
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
}
|
||||
@ -18,8 +18,11 @@ namespace Spectre.Console
|
||||
}
|
||||
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
{
|
||||
if (context.Ansi)
|
||||
{
|
||||
yield return _segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ProgressTask> GetTasks()
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user