mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-20 02:32:50 +08:00
Add fallback for unicode borders
This commit is contained in:
parent
d475e3b30a
commit
fa85216554
@ -13,6 +13,7 @@ namespace Sample
|
|||||||
AnsiConsole.WriteLine("Hello World!");
|
AnsiConsole.WriteLine("Hello World!");
|
||||||
AnsiConsole.Reset();
|
AnsiConsole.Reset();
|
||||||
AnsiConsole.MarkupLine("Capabilities: [yellow underline]{0}[/]", AnsiConsole.Capabilities);
|
AnsiConsole.MarkupLine("Capabilities: [yellow underline]{0}[/]", AnsiConsole.Capabilities);
|
||||||
|
AnsiConsole.MarkupLine("Encoding: [yellow underline]{0}[/]", AnsiConsole.Console.Encoding.EncodingName);
|
||||||
AnsiConsole.MarkupLine("Width=[yellow]{0}[/], Height=[yellow]{1}[/]", AnsiConsole.Width, AnsiConsole.Height);
|
AnsiConsole.MarkupLine("Width=[yellow]{0}[/], Height=[yellow]{1}[/]", AnsiConsole.Width, AnsiConsole.Height);
|
||||||
AnsiConsole.MarkupLine("[white on red]Good[/] [red]bye[/]!");
|
AnsiConsole.MarkupLine("[white on red]Good[/] [red]bye[/]!");
|
||||||
AnsiConsole.WriteLine();
|
AnsiConsole.WriteLine();
|
||||||
@ -51,6 +52,7 @@ namespace Sample
|
|||||||
console.ResetColors();
|
console.ResetColors();
|
||||||
console.ResetDecoration();
|
console.ResetDecoration();
|
||||||
console.MarkupLine("Capabilities: [yellow underline]{0}[/]", console.Capabilities);
|
console.MarkupLine("Capabilities: [yellow underline]{0}[/]", console.Capabilities);
|
||||||
|
console.MarkupLine("Encoding: [yellow underline]{0}[/]", AnsiConsole.Console.Encoding.EncodingName);
|
||||||
console.MarkupLine("Width=[yellow]{0}[/], Height=[yellow]{1}[/]", console.Width, console.Height);
|
console.MarkupLine("Width=[yellow]{0}[/], Height=[yellow]{1}[/]", console.Width, console.Height);
|
||||||
console.MarkupLine("[white on red]Good[/] [red]bye[/]!");
|
console.MarkupLine("[white on red]Good[/] [red]bye[/]!");
|
||||||
console.WriteLine();
|
console.WriteLine();
|
||||||
|
@ -7,7 +7,7 @@ namespace Spectre.Console.Tests
|
|||||||
{
|
{
|
||||||
public sealed class PlainConsole : IAnsiConsole, IDisposable
|
public sealed class PlainConsole : IAnsiConsole, IDisposable
|
||||||
{
|
{
|
||||||
public Capabilities Capabilities => throw new NotSupportedException();
|
public Capabilities Capabilities { get; }
|
||||||
public Encoding Encoding { get; }
|
public Encoding Encoding { get; }
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
@ -21,11 +21,15 @@ namespace Spectre.Console.Tests
|
|||||||
public string Output => Writer.ToString().TrimEnd('\n');
|
public string Output => Writer.ToString().TrimEnd('\n');
|
||||||
public IReadOnlyList<string> Lines => Output.Split(new char[] { '\n' });
|
public IReadOnlyList<string> Lines => Output.Split(new char[] { '\n' });
|
||||||
|
|
||||||
public PlainConsole(int width = 80, int height = 9000, Encoding encoding = null)
|
public PlainConsole(
|
||||||
|
int width = 80, int height = 9000, Encoding encoding = null,
|
||||||
|
bool supportsAnsi = true, ColorSystem colorSystem = ColorSystem.Standard,
|
||||||
|
bool legacyConsole = false)
|
||||||
{
|
{
|
||||||
|
Capabilities = new Capabilities(supportsAnsi, colorSystem, legacyConsole);
|
||||||
|
Encoding = encoding ?? Encoding.UTF8;
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
Encoding = encoding ?? Encoding.UTF8;
|
|
||||||
Writer = new StringWriter();
|
Writer = new StringWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,18 @@ namespace Spectre.Console.Tests.Unit.Composition
|
|||||||
public sealed class TheGetBorderMethod
|
public sealed class TheGetBorderMethod
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(BorderKind.Ascii, typeof(AsciiBorder))]
|
[InlineData(BorderKind.None, false, typeof(NoBorder))]
|
||||||
[InlineData(BorderKind.Square, typeof(SquareBorder))]
|
[InlineData(BorderKind.Ascii, false, typeof(AsciiBorder))]
|
||||||
[InlineData(BorderKind.Rounded, typeof(RoundedBorder))]
|
[InlineData(BorderKind.Square, false, typeof(SquareBorder))]
|
||||||
public void Should_Return_Correct_Border_For_Specified_Kind(BorderKind kind, Type expected)
|
[InlineData(BorderKind.Rounded, false, typeof(RoundedBorder))]
|
||||||
|
[InlineData(BorderKind.None, true, typeof(NoBorder))]
|
||||||
|
[InlineData(BorderKind.Ascii, true, typeof(AsciiBorder))]
|
||||||
|
[InlineData(BorderKind.Square, true, typeof(SquareBorder))]
|
||||||
|
[InlineData(BorderKind.Rounded, true, typeof(SquareBorder))]
|
||||||
|
public void Should_Return_Correct_Border_For_Specified_Kind(BorderKind kind, bool safe, Type expected)
|
||||||
{
|
{
|
||||||
// Given, When
|
// Given, When
|
||||||
var result = Border.GetBorder(kind);
|
var result = Border.GetBorder(kind, safe);
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
result.ShouldBeOfType(expected);
|
result.ShouldBeOfType(expected);
|
||||||
@ -26,7 +31,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
|||||||
public void Should_Throw_If_Unknown_Border_Kind_Is_Specified()
|
public void Should_Throw_If_Unknown_Border_Kind_Is_Specified()
|
||||||
{
|
{
|
||||||
// Given, When
|
// Given, When
|
||||||
var result = Record.Exception(() => Border.GetBorder((BorderKind)int.MaxValue));
|
var result = Record.Exception(() => Border.GetBorder((BorderKind)int.MaxValue, false));
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
result.ShouldBeOfType<InvalidOperationException>();
|
result.ShouldBeOfType<InvalidOperationException>();
|
||||||
|
@ -25,7 +25,13 @@ namespace Spectre.Console
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public bool LegacyConsole { get; }
|
public bool LegacyConsole { get; }
|
||||||
|
|
||||||
internal Capabilities(bool supportsAnsi, ColorSystem colorSystem, bool legacyConsole)
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Capabilities"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="supportsAnsi">Whether or not ANSI escape sequences are supported.</param>
|
||||||
|
/// <param name="colorSystem">The color system that is supported.</param>
|
||||||
|
/// <param name="legacyConsole">Whether or not this is a legacy console.</param>
|
||||||
|
public Capabilities(bool supportsAnsi, ColorSystem colorSystem, bool legacyConsole)
|
||||||
{
|
{
|
||||||
SupportsAnsi = supportsAnsi;
|
SupportsAnsi = supportsAnsi;
|
||||||
ColorSystem = colorSystem;
|
ColorSystem = colorSystem;
|
||||||
|
@ -20,6 +20,11 @@ namespace Spectre.Console.Composition
|
|||||||
{ BorderKind.Rounded, new RoundedBorder() },
|
{ BorderKind.Rounded, new RoundedBorder() },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static readonly Dictionary<BorderKind, BorderKind> _safeLookup = new Dictionary<BorderKind, BorderKind>
|
||||||
|
{
|
||||||
|
{ BorderKind.Rounded, BorderKind.Square },
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Border"/> class.
|
/// Initializes a new instance of the <see cref="Border"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -32,9 +37,15 @@ namespace Spectre.Console.Composition
|
|||||||
/// Gets a <see cref="Border"/> represented by the specified <see cref="BorderKind"/>.
|
/// Gets a <see cref="Border"/> represented by the specified <see cref="BorderKind"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="kind">The kind of border to get.</param>
|
/// <param name="kind">The kind of border to get.</param>
|
||||||
|
/// <param name="safe">Whether or not to get a "safe" border that can be rendered in a legacy console.</param>
|
||||||
/// <returns>A <see cref="Border"/> instance representing the specified <see cref="BorderKind"/>.</returns>
|
/// <returns>A <see cref="Border"/> instance representing the specified <see cref="BorderKind"/>.</returns>
|
||||||
public static Border GetBorder(BorderKind kind)
|
public static Border GetBorder(BorderKind kind, bool safe)
|
||||||
{
|
{
|
||||||
|
if (safe && _safeLookup.TryGetValue(kind, out var safeKind))
|
||||||
|
{
|
||||||
|
kind = safeKind;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_borders.TryGetValue(kind, out var border))
|
if (!_borders.TryGetValue(kind, out var border))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Unknown border kind");
|
throw new InvalidOperationException("Unknown border kind");
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
namespace Spectre.Console.Composition
|
namespace Spectre.Console.Composition
|
||||||
{
|
{
|
||||||
internal sealed class NoBorder : Border
|
/// <summary>
|
||||||
|
/// Represents an invisible border.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class NoBorder : Border
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
protected override string GetBoxPart(BorderPart part)
|
protected override string GetBoxPart(BorderPart part)
|
||||||
{
|
{
|
||||||
return " ";
|
return " ";
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console.Composition;
|
using Spectre.Console.Composition;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
@ -25,15 +24,15 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Measurement Measure(Encoding encoding, int maxWidth)
|
public Measurement Measure(RenderContext context, int maxWidth)
|
||||||
{
|
{
|
||||||
return ((IRenderable)_table).Measure(encoding, maxWidth);
|
return ((IRenderable)_table).Measure(context, maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IEnumerable<Segment> Render(Encoding encoding, int width)
|
public IEnumerable<Segment> Render(RenderContext context, int width)
|
||||||
{
|
{
|
||||||
return ((IRenderable)_table).Render(encoding, width);
|
return ((IRenderable)_table).Render(context, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Spectre.Console.Composition
|
namespace Spectre.Console.Composition
|
||||||
{
|
{
|
||||||
@ -11,17 +10,17 @@ namespace Spectre.Console.Composition
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Measures the renderable object.
|
/// Measures the renderable object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="encoding">The encoding to use.</param>
|
/// <param name="context">The render context.</param>
|
||||||
/// <param name="maxWidth">The maximum allowed width.</param>
|
/// <param name="maxWidth">The maximum allowed width.</param>
|
||||||
/// <returns>The minimum and maximum width of the object.</returns>
|
/// <returns>The minimum and maximum width of the object.</returns>
|
||||||
Measurement Measure(Encoding encoding, int maxWidth);
|
Measurement Measure(RenderContext context, int maxWidth);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Renders the object.
|
/// Renders the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="encoding">The encoding to use.</param>
|
/// <param name="context">The render context.</param>
|
||||||
/// <param name="width">The width of the render area.</param>
|
/// <param name="maxWidth">The maximum allowed width.</param>
|
||||||
/// <returns>A collection of segments.</returns>
|
/// <returns>A collection of segments.</returns>
|
||||||
IEnumerable<Segment> Render(Encoding encoding, int width);
|
IEnumerable<Segment> Render(RenderContext context, int maxWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console.Composition;
|
using Spectre.Console.Composition;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
@ -13,7 +12,14 @@ namespace Spectre.Console
|
|||||||
private readonly IRenderable _child;
|
private readonly IRenderable _child;
|
||||||
private readonly bool _fit;
|
private readonly bool _fit;
|
||||||
private readonly Justify _content;
|
private readonly Justify _content;
|
||||||
private readonly Border _border;
|
private readonly BorderKind _border;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether or not to use
|
||||||
|
/// a "safe" border on legacy consoles that might not be able
|
||||||
|
/// to render non-ASCII characters. Defaults to <c>true</c>.
|
||||||
|
/// </summary>
|
||||||
|
public bool SafeBorder { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Panel"/> class.
|
/// Initializes a new instance of the <see cref="Panel"/> class.
|
||||||
@ -31,47 +37,49 @@ namespace Spectre.Console
|
|||||||
_child = child ?? throw new System.ArgumentNullException(nameof(child));
|
_child = child ?? throw new System.ArgumentNullException(nameof(child));
|
||||||
_fit = fit;
|
_fit = fit;
|
||||||
_content = content;
|
_content = content;
|
||||||
_border = Border.GetBorder(border);
|
_border = border;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
Measurement IRenderable.Measure(Encoding encoding, int maxWidth)
|
Measurement IRenderable.Measure(RenderContext context, int maxWidth)
|
||||||
{
|
{
|
||||||
var childWidth = _child.Measure(encoding, maxWidth);
|
var childWidth = _child.Measure(context, maxWidth);
|
||||||
return new Measurement(childWidth.Min + 4, childWidth.Max + 4);
|
return new Measurement(childWidth.Min + 4, childWidth.Max + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerable<Segment> IRenderable.Render(Encoding encoding, int width)
|
IEnumerable<Segment> IRenderable.Render(RenderContext context, int width)
|
||||||
{
|
{
|
||||||
|
var border = Border.GetBorder(_border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
|
||||||
|
|
||||||
var childWidth = width - 4;
|
var childWidth = width - 4;
|
||||||
if (!_fit)
|
if (!_fit)
|
||||||
{
|
{
|
||||||
var measurement = _child.Measure(encoding, width - 2);
|
var measurement = _child.Measure(context, width - 2);
|
||||||
childWidth = measurement.Max;
|
childWidth = measurement.Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<Segment>();
|
var result = new List<Segment>();
|
||||||
var panelWidth = childWidth + 2;
|
var panelWidth = childWidth + 2;
|
||||||
|
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.HeaderTopLeft)));
|
result.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft)));
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.HeaderTop, panelWidth)));
|
result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth)));
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.HeaderTopRight)));
|
result.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight)));
|
||||||
result.Add(new Segment("\n"));
|
result.Add(new Segment("\n"));
|
||||||
|
|
||||||
// Render the child.
|
// Render the child.
|
||||||
var childSegments = _child.Render(encoding, childWidth);
|
var childSegments = _child.Render(context, childWidth);
|
||||||
|
|
||||||
// Split the child segments into lines.
|
// Split the child segments into lines.
|
||||||
var lines = Segment.SplitLines(childSegments, childWidth);
|
var lines = Segment.SplitLines(childSegments, childWidth);
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.CellLeft)));
|
result.Add(new Segment(border.GetPart(BorderPart.CellLeft)));
|
||||||
result.Add(new Segment(" ")); // Left padding
|
result.Add(new Segment(" ")); // Left padding
|
||||||
|
|
||||||
var content = new List<Segment>();
|
var content = new List<Segment>();
|
||||||
|
|
||||||
var length = line.Sum(segment => segment.CellLength(encoding));
|
var length = line.Sum(segment => segment.CellLength(context.Encoding));
|
||||||
if (length < childWidth)
|
if (length < childWidth)
|
||||||
{
|
{
|
||||||
// Justify right side
|
// Justify right side
|
||||||
@ -116,13 +124,13 @@ namespace Spectre.Console
|
|||||||
result.AddRange(content);
|
result.AddRange(content);
|
||||||
|
|
||||||
result.Add(new Segment(" "));
|
result.Add(new Segment(" "));
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.CellRight)));
|
result.Add(new Segment(border.GetPart(BorderPart.CellRight)));
|
||||||
result.Add(new Segment("\n"));
|
result.Add(new Segment("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.FooterBottomLeft)));
|
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft)));
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.FooterBottom, panelWidth)));
|
result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth)));
|
||||||
result.Add(new Segment(_border.GetPart(BorderPart.FooterBottomRight)));
|
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight)));
|
||||||
result.Add(new Segment("\n"));
|
result.Add(new Segment("\n"));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
37
src/Spectre.Console/Composition/RenderContext.cs
Normal file
37
src/Spectre.Console/Composition/RenderContext.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Composition
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a render context.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RenderContext
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the console's output encoding.
|
||||||
|
/// </summary>
|
||||||
|
public Encoding Encoding { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether or not this a legacy console (i.e. cmd.exe).
|
||||||
|
/// </summary>
|
||||||
|
public bool LegacyConsole { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether or not unicode is supported.
|
||||||
|
/// </summary>
|
||||||
|
public bool Unicode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RenderContext"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encoding">The console's output encoding.</param>
|
||||||
|
/// <param name="legacyConsole">A value indicating whether or not this a legacy console (i.e. cmd.exe).</param>
|
||||||
|
public RenderContext(Encoding encoding, bool legacyConsole)
|
||||||
|
{
|
||||||
|
Encoding = encoding ?? throw new System.ArgumentNullException(nameof(encoding));
|
||||||
|
LegacyConsole = legacyConsole;
|
||||||
|
Unicode = Encoding == Encoding.UTF8 || Encoding == Encoding.Unicode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console.Composition;
|
using Spectre.Console.Composition;
|
||||||
using Spectre.Console.Internal;
|
using Spectre.Console.Internal;
|
||||||
|
|
||||||
@ -15,9 +14,9 @@ namespace Spectre.Console
|
|||||||
// Calculate the widths of each column, including padding, not including borders.
|
// Calculate the widths of each column, including padding, not including borders.
|
||||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
||||||
private List<int> CalculateColumnWidths(Encoding encoding, int maxWidth)
|
private List<int> CalculateColumnWidths(RenderContext options, int maxWidth)
|
||||||
{
|
{
|
||||||
var width_ranges = _columns.Select(column => MeasureColumn(column, encoding, maxWidth));
|
var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth));
|
||||||
var widths = width_ranges.Select(range => range.Max).ToList();
|
var widths = width_ranges.Select(range => range.Max).ToList();
|
||||||
|
|
||||||
var tableWidth = widths.Sum();
|
var tableWidth = widths.Sum();
|
||||||
@ -132,7 +131,7 @@ namespace Spectre.Console
|
|||||||
return widths;
|
return widths;
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int Min, int Max) MeasureColumn(TableColumn column, Encoding encoding, int maxWidth)
|
private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth)
|
||||||
{
|
{
|
||||||
// Predetermined width?
|
// Predetermined width?
|
||||||
if (column.Width != null)
|
if (column.Width != null)
|
||||||
@ -148,7 +147,7 @@ namespace Spectre.Console
|
|||||||
var maxWidths = new List<int>();
|
var maxWidths = new List<int>();
|
||||||
foreach (var row in rows)
|
foreach (var row in rows)
|
||||||
{
|
{
|
||||||
var measure = ((IRenderable)row).Measure(encoding, maxWidth);
|
var measure = ((IRenderable)row).Measure(options, maxWidth);
|
||||||
minWidths.Add(measure.Min);
|
minWidths.Add(measure.Min);
|
||||||
maxWidths.Add(measure.Max);
|
maxWidths.Add(measure.Max);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console.Composition;
|
using Spectre.Console.Composition;
|
||||||
using Spectre.Console.Internal;
|
using Spectre.Console.Internal;
|
||||||
|
|
||||||
@ -47,6 +46,13 @@ namespace Spectre.Console
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int? Width { get; set; } = null;
|
public int? Width { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether or not to use
|
||||||
|
/// a "safe" border on legacy consoles that might not be able
|
||||||
|
/// to render non-ASCII characters. Defaults to <c>true</c>.
|
||||||
|
/// </summary>
|
||||||
|
public bool SafeBorder { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Table"/> class.
|
/// Initializes a new instance of the <see cref="Table"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -123,8 +129,13 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
Measurement IRenderable.Measure(Encoding encoding, int maxWidth)
|
Measurement IRenderable.Measure(RenderContext context, int maxWidth)
|
||||||
{
|
{
|
||||||
|
if (context is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
if (Width != null)
|
if (Width != null)
|
||||||
{
|
{
|
||||||
maxWidth = Math.Min(Width.Value, maxWidth);
|
maxWidth = Math.Min(Width.Value, maxWidth);
|
||||||
@ -132,7 +143,7 @@ namespace Spectre.Console
|
|||||||
|
|
||||||
maxWidth -= GetExtraWidth(includePadding: true);
|
maxWidth -= GetExtraWidth(includePadding: true);
|
||||||
|
|
||||||
var measurements = _columns.Select(column => MeasureColumn(column, encoding, maxWidth)).ToList();
|
var measurements = _columns.Select(column => MeasureColumn(column, context, maxWidth)).ToList();
|
||||||
var min = measurements.Sum(x => x.Min) + GetExtraWidth(includePadding: true);
|
var min = measurements.Sum(x => x.Min) + GetExtraWidth(includePadding: true);
|
||||||
var max = Width ?? measurements.Sum(x => x.Max) + GetExtraWidth(includePadding: true);
|
var max = Width ?? measurements.Sum(x => x.Max) + GetExtraWidth(includePadding: true);
|
||||||
|
|
||||||
@ -140,9 +151,14 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerable<Segment> IRenderable.Render(Encoding encoding, int width)
|
IEnumerable<Segment> IRenderable.Render(RenderContext context, int width)
|
||||||
{
|
{
|
||||||
var border = Composition.Border.GetBorder(Border);
|
if (context is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
var border = Composition.Border.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder);
|
||||||
|
|
||||||
var showBorder = Border != BorderKind.None;
|
var showBorder = Border != BorderKind.None;
|
||||||
var hideBorder = Border == BorderKind.None;
|
var hideBorder = Border == BorderKind.None;
|
||||||
@ -156,7 +172,7 @@ namespace Spectre.Console
|
|||||||
maxWidth -= GetExtraWidth(includePadding: true);
|
maxWidth -= GetExtraWidth(includePadding: true);
|
||||||
|
|
||||||
// Calculate the column and table widths
|
// Calculate the column and table widths
|
||||||
var columnWidths = CalculateColumnWidths(encoding, maxWidth);
|
var columnWidths = CalculateColumnWidths(context, maxWidth);
|
||||||
|
|
||||||
// Update the table width.
|
// Update the table width.
|
||||||
width = columnWidths.Sum() + GetExtraWidth(includePadding: false);
|
width = columnWidths.Sum() + GetExtraWidth(includePadding: false);
|
||||||
@ -181,7 +197,7 @@ namespace Spectre.Console
|
|||||||
var cells = new List<List<SegmentLine>>();
|
var cells = new List<List<SegmentLine>>();
|
||||||
foreach (var (rowWidth, cell) in columnWidths.Zip(row, (f, s) => (f, s)))
|
foreach (var (rowWidth, cell) in columnWidths.Zip(row, (f, s) => (f, s)))
|
||||||
{
|
{
|
||||||
var lines = Segment.SplitLines(((IRenderable)cell).Render(encoding, rowWidth));
|
var lines = Segment.SplitLines(((IRenderable)cell).Render(context, rowWidth));
|
||||||
cellHeight = Math.Max(cellHeight, lines.Count);
|
cellHeight = Math.Max(cellHeight, lines.Count);
|
||||||
cells.Add(lines);
|
cells.Add(lines);
|
||||||
}
|
}
|
||||||
@ -234,7 +250,7 @@ namespace Spectre.Console
|
|||||||
result.AddRange(cell[cellRowIndex]);
|
result.AddRange(cell[cellRowIndex]);
|
||||||
|
|
||||||
// Pad cell content right
|
// Pad cell content right
|
||||||
var length = cell[cellRowIndex].Sum(segment => segment.CellLength(encoding));
|
var length = cell[cellRowIndex].Sum(segment => segment.CellLength(context.Encoding));
|
||||||
if (length < columnWidths[cellIndex])
|
if (length < columnWidths[cellIndex])
|
||||||
{
|
{
|
||||||
result.Add(new Segment(new string(' ', columnWidths[cellIndex] - length)));
|
result.Add(new Segment(new string(' ', columnWidths[cellIndex] - length)));
|
||||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console.Composition;
|
using Spectre.Console.Composition;
|
||||||
using Spectre.Console.Internal;
|
using Spectre.Console.Internal;
|
||||||
|
|
||||||
@ -98,9 +97,9 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
Measurement IRenderable.Measure(Encoding encoding, int maxWidth)
|
Measurement IRenderable.Measure(RenderContext context, int maxWidth)
|
||||||
{
|
{
|
||||||
var lines = Segment.SplitLines(((IRenderable)this).Render(encoding, maxWidth));
|
var lines = Segment.SplitLines(((IRenderable)this).Render(context, maxWidth));
|
||||||
if (lines.Count == 0)
|
if (lines.Count == 0)
|
||||||
{
|
{
|
||||||
return new Measurement(0, maxWidth);
|
return new Measurement(0, maxWidth);
|
||||||
@ -113,7 +112,7 @@ namespace Spectre.Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
IEnumerable<Segment> IRenderable.Render(Encoding encoding, int width)
|
IEnumerable<Segment> IRenderable.Render(RenderContext context, int width)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_text))
|
if (string.IsNullOrWhiteSpace(_text))
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,9 @@ namespace Spectre.Console
|
|||||||
throw new ArgumentNullException(nameof(renderable));
|
throw new ArgumentNullException(nameof(renderable));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var segment in renderable.Render(console.Encoding, console.Width))
|
var options = new RenderContext(console.Encoding, console.Capabilities.LegacyConsole);
|
||||||
|
|
||||||
|
foreach (var segment in renderable.Render(options, console.Width))
|
||||||
{
|
{
|
||||||
if (!segment.Style.Equals(Style.Plain))
|
if (!segment.Style.Equals(Style.Plain))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user