mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-04 10:35:27 +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