mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-07-06 20:48:15 +08:00
Improve text composite
- A `Text` object should not be able to justify itself. All justification needs to be done by a parent. - Apply colors and styles to part of a `Text` object - Markup parser should return a `Text` object
This commit is contained in:

committed by
Patrik Svensson

parent
8e4f33bba4
commit
f19202b427
@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public sealed class AnsiConsoleFixture : IDisposable
|
||||
{
|
||||
private readonly StringWriter _writer;
|
||||
|
||||
public IAnsiConsole Console { get; }
|
||||
|
||||
public string Output => _writer.ToString();
|
||||
|
||||
public AnsiConsoleFixture(ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes)
|
||||
{
|
||||
_writer = new StringWriter();
|
||||
|
||||
Console = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
{
|
||||
Ansi = ansi,
|
||||
ColorSystem = (ColorSystemSupport)system,
|
||||
Out = _writer,
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_writer?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ using System.Globalization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public partial class AnsiConsoleTests
|
||||
{
|
||||
|
24
src/Spectre.Console.Tests/Unit/AppearanceTests.cs
Normal file
24
src/Spectre.Console.Tests/Unit/AppearanceTests.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class AppearanceTests
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Combine_Two_Appearances_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var first = new Appearance(Color.White, Color.Yellow, Styles.Bold | Styles.Italic);
|
||||
var other = new Appearance(Color.Green, Color.Silver, Styles.Underline);
|
||||
|
||||
// When
|
||||
var result = first.Combine(other);
|
||||
|
||||
// Then
|
||||
result.Foreground.ShouldBe(Color.Green);
|
||||
result.Background.ShouldBe(Color.Silver);
|
||||
result.Style.ShouldBe(Styles.Bold | Styles.Italic | Styles.Underline);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Composition;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Composition
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class PanelTests
|
||||
{
|
||||
@ -13,7 +12,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 80);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text("Hello World")));
|
||||
console.Render(new Panel(Text.New("Hello World")));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
@ -29,7 +28,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 80);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text(" \n💩\n ")));
|
||||
console.Render(new Panel(Text.New(" \n💩\n ")));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(5);
|
||||
@ -47,7 +46,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 80);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text("Hello World\nFoo Bar")));
|
||||
console.Render(new Panel(Text.New("Hello World\nFoo Bar")));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(4);
|
||||
@ -57,6 +56,29 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
console.Lines[3].ShouldBe("└─────────────┘");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Preserve_Explicit_Line_Ending()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 80);
|
||||
var text = new Panel(
|
||||
Text.New("I heard [underline on blue]you[/] like 📦\n\n\n\nSo I put a 📦 in a 📦"),
|
||||
content: Justify.Center);
|
||||
|
||||
// When
|
||||
console.Render(text);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(7);
|
||||
console.Lines[0].ShouldBe("┌───────────────────────┐");
|
||||
console.Lines[1].ShouldBe("│ I heard you like 📦 │");
|
||||
console.Lines[2].ShouldBe("│ │");
|
||||
console.Lines[3].ShouldBe("│ │");
|
||||
console.Lines[4].ShouldBe("│ │");
|
||||
console.Lines[5].ShouldBe("│ So I put a 📦 in a 📦 │");
|
||||
console.Lines[6].ShouldBe("└───────────────────────┘");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Fit_Panel_To_Parent_If_Enabled()
|
||||
{
|
||||
@ -64,7 +86,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 25);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text("Hello World"), fit: true));
|
||||
console.Render(new Panel(Text.New("Hello World"), fit: true));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
@ -80,7 +102,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 25);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text("Hello World", justify: Justify.Right), fit: true));
|
||||
console.Render(new Panel(Text.New("Hello World"), fit: true, content: Justify.Right));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
@ -96,7 +118,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 25);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Text("Hello World", justify: Justify.Center), fit: true));
|
||||
console.Render(new Panel(Text.New("Hello World"), fit: true, content: Justify.Center));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
@ -112,7 +134,7 @@ namespace Spectre.Console.Tests.Unit.Composition
|
||||
var console = new PlainConsole(width: 80);
|
||||
|
||||
// When
|
||||
console.Render(new Panel(new Panel(new Text("Hello World"))));
|
||||
console.Render(new Panel(new Panel(Text.New("Hello World"))));
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(5);
|
||||
|
@ -2,66 +2,91 @@ using Shouldly;
|
||||
using Spectre.Console.Composition;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit.Composition
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class SegmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Split_Segment()
|
||||
public sealed class TheSplitMethod
|
||||
{
|
||||
var lines = Segment.Split(new[]
|
||||
[Fact]
|
||||
public void Should_Split_Segment_Correctly()
|
||||
{
|
||||
new Segment("Foo"),
|
||||
new Segment("Bar"),
|
||||
new Segment("\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux"),
|
||||
new Segment("\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
// Given
|
||||
var appearance = new Appearance(Color.Red, Color.Green, Styles.Bold);
|
||||
var segment = new Segment("Foo Bar", appearance);
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
// When
|
||||
var (first, second) = segment.Split(3);
|
||||
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
// Then
|
||||
first.Text.ShouldBe("Foo");
|
||||
first.Appearance.ShouldBe(appearance);
|
||||
second.Text.ShouldBe(" Bar");
|
||||
second.Appearance.ShouldBe(appearance);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Split_Segments_With_Linebreak_In_Text()
|
||||
public sealed class TheSplitLinesMethod
|
||||
{
|
||||
var lines = Segment.Split(new[]
|
||||
[Fact]
|
||||
public void Should_Split_Segment()
|
||||
{
|
||||
new Segment("Foo\n"),
|
||||
new Segment("Bar\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo"),
|
||||
new Segment("Bar"),
|
||||
new Segment("\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux"),
|
||||
new Segment("\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(4);
|
||||
// Then
|
||||
lines.Count.ShouldBe(3);
|
||||
|
||||
lines[0].Count.ShouldBe(1);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0].Count.ShouldBe(2);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
lines[0][1].Text.ShouldBe("Bar");
|
||||
|
||||
lines[1].Count.ShouldBe(1);
|
||||
lines[1][0].Text.ShouldBe("Bar");
|
||||
lines[1].Count.ShouldBe(2);
|
||||
lines[1][0].Text.ShouldBe("Baz");
|
||||
lines[1][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[2].Count.ShouldBe(2);
|
||||
lines[2][0].Text.ShouldBe("Baz");
|
||||
lines[2][1].Text.ShouldBe("Qux");
|
||||
lines[2].Count.ShouldBe(1);
|
||||
lines[2][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
|
||||
lines[3].Count.ShouldBe(1);
|
||||
lines[3][0].Text.ShouldBe("Corgi");
|
||||
[Fact]
|
||||
public void Should_Split_Segments_With_Linebreak_In_Text()
|
||||
{
|
||||
var lines = Segment.SplitLines(
|
||||
new[]
|
||||
{
|
||||
new Segment("Foo\n"),
|
||||
new Segment("Bar\n"),
|
||||
new Segment("Baz"),
|
||||
new Segment("Qux\n"),
|
||||
new Segment("Corgi"),
|
||||
});
|
||||
|
||||
// Then
|
||||
lines.Count.ShouldBe(4);
|
||||
|
||||
lines[0].Count.ShouldBe(1);
|
||||
lines[0][0].Text.ShouldBe("Foo");
|
||||
|
||||
lines[1].Count.ShouldBe(1);
|
||||
lines[1][0].Text.ShouldBe("Bar");
|
||||
|
||||
lines[2].Count.ShouldBe(2);
|
||||
lines[2][0].Text.ShouldBe("Baz");
|
||||
lines[2][1].Text.ShouldBe("Qux");
|
||||
|
||||
lines[3].Count.ShouldBe(1);
|
||||
lines[3][0].Text.ShouldBe("Corgi");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,77 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Composition;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Composition
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class TextTests
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Render_Text_To_Console()
|
||||
public void Should_Render_Unstyled_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var fixture = new PlainConsole(width: 80);
|
||||
var text = Text.New("Hello World");
|
||||
|
||||
// When
|
||||
console.Render(new Text("Hello World"));
|
||||
fixture.Render(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello World");
|
||||
fixture.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe("Hello World");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Right_Align_Text_To_Parent()
|
||||
public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 15);
|
||||
var fixture = new PlainConsole(width: 5);
|
||||
var text = Text.New("Hello World");
|
||||
|
||||
// When
|
||||
console.Render(new Text("Hello World", justify: Justify.Right));
|
||||
fixture.Render(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(" Hello World");
|
||||
fixture.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe("Hello\n Worl\nd");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Center_Text_To_Parent()
|
||||
public sealed class TheStylizeMethod
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 15);
|
||||
[Fact]
|
||||
public void Should_Apply_Style_To_Text()
|
||||
{
|
||||
// Given
|
||||
var fixture = new AnsiConsoleFixture(ColorSystem.Standard);
|
||||
var text = Text.New("Hello World");
|
||||
text.Stylize(start: 3, end: 8, new Appearance(style: Styles.Underline));
|
||||
|
||||
// When
|
||||
console.Render(new Text("Hello World", justify: Justify.Center));
|
||||
// When
|
||||
fixture.Console.Render(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe(" Hello World ");
|
||||
}
|
||||
// Then
|
||||
fixture.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe("Hel[4mlo Wo[0mrld");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Split_Text_To_Multiple_Lines_If_It_Does_Not_Fit()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 5);
|
||||
[Fact]
|
||||
public void Should_Apply_Style_To_Text_Which_Spans_Over_Multiple_Lines()
|
||||
{
|
||||
// Given
|
||||
var fixture = new AnsiConsoleFixture(ColorSystem.Standard, width: 5);
|
||||
var text = Text.New("Hello World");
|
||||
text.Stylize(start: 3, end: 8, new Appearance(style: Styles.Underline));
|
||||
|
||||
// When
|
||||
console.Render(new Text("Hello World"));
|
||||
// When
|
||||
fixture.Console.Render(text);
|
||||
|
||||
// Then
|
||||
console.Output.ShouldBe("Hello\n Worl\nd");
|
||||
// Then
|
||||
fixture.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe("Hel[4mlo[0m\n[4m Wo[0mrl\nd");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user