mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00
Change IAnsiConsole to render IRenderable
This makes it possible for encoders to output better representation of the actual objects instead of working with chopped up segments. * IAnsiConsole.Write now takes an IRenderable instead of segments * Calculating cell width does no longer require a render context * Removed RenderContext.LegacyConsole * Removed RenderContext.Encoding * Added Capabilities.Unicode
This commit is contained in:

committed by
Phil Scott

parent
2ba6da3514
commit
20650f1e7e
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
@ -8,21 +7,21 @@ namespace Spectre.Console
|
||||
internal sealed class AnsiConsoleBackend : IAnsiConsoleBackend
|
||||
{
|
||||
private readonly AnsiBuilder _builder;
|
||||
private readonly Profile _profile;
|
||||
private readonly IAnsiConsole _console;
|
||||
|
||||
public IAnsiConsoleCursor Cursor { get; }
|
||||
|
||||
public AnsiConsoleBackend(Profile profile)
|
||||
public AnsiConsoleBackend(IAnsiConsole console)
|
||||
{
|
||||
_profile = profile ?? throw new ArgumentNullException(nameof(profile));
|
||||
_builder = new AnsiBuilder(profile);
|
||||
_console = console ?? throw new ArgumentNullException(nameof(console));
|
||||
_builder = new AnsiBuilder(_console.Profile);
|
||||
|
||||
Cursor = new AnsiConsoleCursor(this);
|
||||
}
|
||||
|
||||
public void Clear(bool home)
|
||||
{
|
||||
Render(new[] { Segment.Control("\u001b[2J") });
|
||||
Write(new ControlSequence("\u001b[2J"));
|
||||
|
||||
if (home)
|
||||
{
|
||||
@ -30,10 +29,10 @@ namespace Spectre.Console
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(IEnumerable<Segment> segments)
|
||||
public void Write(IRenderable renderable)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var segment in segments)
|
||||
foreach (var segment in renderable.GetSegments(_console))
|
||||
{
|
||||
if (segment.IsControlCode)
|
||||
{
|
||||
@ -58,8 +57,8 @@ namespace Spectre.Console
|
||||
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
_profile.Out.Write(builder.ToString());
|
||||
_profile.Out.Flush();
|
||||
_console.Profile.Out.Write(builder.ToString());
|
||||
_console.Profile.Out.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
@ -16,11 +15,11 @@ namespace Spectre.Console
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
_backend.Render(new[] { Segment.Control("\u001b[?25h") });
|
||||
_backend.Write(new ControlSequence("\u001b[?25h"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_backend.Render(new[] { Segment.Control("\u001b[?25l") });
|
||||
_backend.Write(new ControlSequence("\u001b[?25l"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,23 +33,23 @@ namespace Spectre.Console
|
||||
switch (direction)
|
||||
{
|
||||
case CursorDirection.Up:
|
||||
_backend.Render(new[] { Segment.Control($"\u001b[{steps}A") });
|
||||
_backend.Write(new ControlSequence($"\u001b[{steps}A"));
|
||||
break;
|
||||
case CursorDirection.Down:
|
||||
_backend.Render(new[] { Segment.Control($"\u001b[{steps}B") });
|
||||
_backend.Write(new ControlSequence($"\u001b[{steps}B"));
|
||||
break;
|
||||
case CursorDirection.Right:
|
||||
_backend.Render(new[] { Segment.Control($"\u001b[{steps}C") });
|
||||
_backend.Write(new ControlSequence($"\u001b[{steps}C"));
|
||||
break;
|
||||
case CursorDirection.Left:
|
||||
_backend.Render(new[] { Segment.Control($"\u001b[{steps}D") });
|
||||
_backend.Write(new ControlSequence($"\u001b[{steps}D"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPosition(int column, int line)
|
||||
{
|
||||
_backend.Render(new[] { Segment.Control($"\u001b[{line};{column}H") });
|
||||
_backend.Write(new ControlSequence($"\u001b[{line};{column}H"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
@ -19,13 +18,14 @@ namespace Spectre.Console
|
||||
public AnsiConsoleFacade(Profile profile, IExclusivityMode exclusivityMode)
|
||||
{
|
||||
_renderLock = new object();
|
||||
_ansiBackend = new AnsiConsoleBackend(profile);
|
||||
_legacyBackend = new LegacyConsoleBackend(profile);
|
||||
|
||||
Profile = profile ?? throw new ArgumentNullException(nameof(profile));
|
||||
Input = new DefaultInput(Profile);
|
||||
ExclusivityMode = exclusivityMode ?? throw new ArgumentNullException(nameof(exclusivityMode));
|
||||
Pipeline = new RenderPipeline();
|
||||
|
||||
_ansiBackend = new AnsiConsoleBackend(this);
|
||||
_legacyBackend = new LegacyConsoleBackend(this);
|
||||
}
|
||||
|
||||
public void Clear(bool home)
|
||||
@ -36,11 +36,11 @@ namespace Spectre.Console
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(IEnumerable<Segment> segments)
|
||||
public void Write(IRenderable renderable)
|
||||
{
|
||||
lock (_renderLock)
|
||||
{
|
||||
GetBackend().Render(segments);
|
||||
GetBackend().Write(renderable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
@ -20,9 +19,9 @@ namespace Spectre.Console
|
||||
void Clear(bool home);
|
||||
|
||||
/// <summary>
|
||||
/// Renders segments to the console.
|
||||
/// Writes a <see cref="IRenderable"/> to the console backend.
|
||||
/// </summary>
|
||||
/// <param name="segments">The segments to render.</param>
|
||||
void Render(IEnumerable<Segment> segments);
|
||||
/// <param name="renderable">The <see cref="IRenderable"/> to write.</param>
|
||||
void Write(IRenderable renderable);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
internal sealed class LegacyConsoleBackend : IAnsiConsoleBackend
|
||||
{
|
||||
private readonly Profile _profile;
|
||||
private readonly IAnsiConsole _console;
|
||||
private Style _lastStyle;
|
||||
|
||||
public IAnsiConsoleCursor Cursor { get; }
|
||||
|
||||
public LegacyConsoleBackend(Profile profile)
|
||||
public LegacyConsoleBackend(IAnsiConsole console)
|
||||
{
|
||||
_profile = profile ?? throw new System.ArgumentNullException(nameof(profile));
|
||||
_console = console ?? throw new System.ArgumentNullException(nameof(console));
|
||||
_lastStyle = Style.Plain;
|
||||
|
||||
Cursor = new LegacyConsoleCursor();
|
||||
@ -31,9 +30,9 @@ namespace Spectre.Console
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(IEnumerable<Segment> segments)
|
||||
public void Write(IRenderable renderable)
|
||||
{
|
||||
foreach (var segment in segments)
|
||||
foreach (var segment in renderable.GetSegments(_console))
|
||||
{
|
||||
if (segment.IsControlCode)
|
||||
{
|
||||
@ -45,7 +44,7 @@ namespace Spectre.Console
|
||||
SetStyle(segment.Style);
|
||||
}
|
||||
|
||||
_profile.Out.Write(segment.Text.NormalizeNewLines(native: true));
|
||||
_console.Profile.Out.Write(segment.Text.NormalizeNewLines(native: true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,13 +55,13 @@ namespace Spectre.Console
|
||||
System.Console.ResetColor();
|
||||
|
||||
var background = Color.ToConsoleColor(style.Background);
|
||||
if (_profile.ColorSystem != ColorSystem.NoColors && (int)background != -1)
|
||||
if (_console.Profile.ColorSystem != ColorSystem.NoColors && (int)background != -1)
|
||||
{
|
||||
System.Console.BackgroundColor = background;
|
||||
}
|
||||
|
||||
var foreground = Color.ToConsoleColor(style.Foreground);
|
||||
if (_profile.ColorSystem != ColorSystem.NoColors && (int)foreground != -1)
|
||||
if (_console.Profile.ColorSystem != ColorSystem.NoColors && (int)foreground != -1)
|
||||
{
|
||||
System.Console.ForegroundColor = foreground;
|
||||
}
|
||||
|
Reference in New Issue
Block a user