Skip to content

Commit 8dfead5

Browse files
committed
rendering API adjustments, console.Append extension concept
1 parent dde07c5 commit 8dfead5

16 files changed

+185
-58
lines changed

src/System.CommandLine.Rendering.Tests/System.CommandLine.Rendering.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
<Compile Include="..\System.CommandLine.Rendering\WrappingExtensions.cs" Link="WrappingExtensions.cs" />
1717
</ItemGroup>
1818

19+
<ItemGroup>
20+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
21+
</ItemGroup>
22+
1923
<ItemGroup>
2024
<ProjectReference Include="..\System.CommandLine.Rendering\System.CommandLine.Rendering.csproj" />
2125
<ProjectReference Include="..\System.CommandLine.Tests\System.CommandLine.Tests.csproj" />

src/System.CommandLine.Rendering.Tests/TestTerminalTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public void When_in_ANSI_mode_and_ANSI_sequences_are_used_to_set_cursor_position
4848
{
4949
var terminal = (TestTerminal)GetTerminal();
5050

51-
terminal.IsVirtualTerminalModeEnabled = true;
51+
terminal.IsAnsiTerminal = true;
5252

5353
terminal.Out.Write($"before move{Ansi.Cursor.Move.ToLocation(3, 5).EscapeSequence}after move");
5454

@@ -65,7 +65,7 @@ public void When_not_in_ANSI_mode_and_ANSI_sequences_are_used_to_set_cursor_posi
6565
{
6666
var terminal = (TestTerminal)GetTerminal();
6767

68-
terminal.IsVirtualTerminalModeEnabled = false;
68+
terminal.IsAnsiTerminal = false;
6969

7070
var stringWithEscapeSequence = $"before move{Ansi.Cursor.Move.ToLocation(3, 5).EscapeSequence}after move";
7171

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System.CommandLine.Builder;
5+
using System.CommandLine.Invocation;
6+
using System.CommandLine.Parsing;
47
using System.CommandLine.Rendering.Views;
58
using System.CommandLine.Tests;
69
using System.Drawing;
710
using FluentAssertions;
11+
using Microsoft.Extensions.DependencyInjection;
812
using Xunit;
913

1014
namespace System.CommandLine.Rendering.Tests
@@ -13,36 +17,73 @@ public class ViewRenderingTests
1317
{
1418
private readonly TestTerminal _terminal = new TestTerminal();
1519

16-
[Fact(Skip = "WIP")]
17-
public void In_NonAnsi_mode_ConsoleView_keeps_track_of_position_so_that_multiple_WriteLine_statements_do_not_overwrite_the_target_region()
20+
[Fact]
21+
public void Views_can_be_registered_for_specific_types()
1822
{
19-
var renderer = new ConsoleRenderer(
20-
_terminal,
21-
OutputMode.NonAnsi);
23+
ParseResult parseResult = null;
24+
25+
var command = new RootCommand
26+
{
27+
Handler = CommandHandler.Create<ParseResult, IConsole>(
28+
(r, c) =>
29+
{
30+
parseResult = r;
31+
c.Append(new ParseResultView(r));
32+
})
33+
};
34+
35+
var parser = new CommandLineBuilder(command)
36+
.UseMiddleware(c =>
37+
{
38+
c.BindingContext
39+
.AddService(
40+
s => new ParseResultView(s.GetService<ParseResult>()));
41+
})
42+
.Build();
43+
44+
var terminal = new TestTerminal
45+
{
46+
IsAnsiTerminal = false
47+
};
48+
49+
parser.Invoke("", terminal);
50+
51+
terminal.Out.ToString().Should().Contain(parseResult.Diagram());
52+
}
2253

23-
var view = new StringsView(new[] {
54+
[Theory]
55+
[InlineData(OutputMode.NonAnsi)]
56+
[InlineData(OutputMode.Ansi)]
57+
public void Views_can_be_appended_to_output(OutputMode outputMode)
58+
{
59+
var view = new StringsView(new[]
60+
{
2461
"1",
2562
"2",
2663
"3"
2764
});
2865

29-
view.Render(renderer, new Region(3, 5, 1, 3));
66+
_terminal.Append(view, outputMode);
3067

3168
_terminal.RenderOperations()
32-
.Should()
33-
.BeEquivalentSequenceTo(new TextRendered("1", new Point(3, 5)),
34-
new TextRendered("2", new Point(3, 6)),
35-
new TextRendered("3", new Point(3, 7)));
69+
.Should()
70+
.BeEquivalentSequenceTo(
71+
new TextRendered("1", new Point(0, 2)),
72+
new TextRendered("2", new Point(0, 3)),
73+
new TextRendered("3" + Environment.NewLine, new Point(0, 4)));
3674
}
3775

38-
[Fact(Skip = "WIP")]
39-
public void In_Ansi_mode_ConsoleView_keeps_track_of_position_so_that_multiple_WriteLine_statements_do_not_overwrite_the_target_region()
76+
[Theory]
77+
[InlineData(OutputMode.NonAnsi)]
78+
[InlineData(OutputMode.Ansi)]
79+
public void ConsoleView_keeps_track_of_position_so_that_multiple_WriteLine_statements_do_not_overwrite_the_target_region(OutputMode outputMode)
4080
{
4181
var renderer = new ConsoleRenderer(
4282
_terminal,
43-
OutputMode.Ansi);
44-
45-
var view = new StringsView(new[] {
83+
outputMode);
84+
85+
var view = new StringsView(new[]
86+
{
4687
"1",
4788
"2",
4889
"3"
@@ -51,22 +92,29 @@ public void In_Ansi_mode_ConsoleView_keeps_track_of_position_so_that_multiple_Wr
5192
view.Render(renderer, new Region(3, 5, 1, 3));
5293

5394
_terminal.RenderOperations()
54-
.Should()
55-
.BeEquivalentSequenceTo(
56-
new TextRendered("1", new Point(3, 5)),
57-
new TextRendered("2", new Point(3, 6)),
58-
new TextRendered("3", new Point(3, 7)));
95+
.Should()
96+
.BeEquivalentSequenceTo(
97+
new TextRendered("1", new Point(3, 5)),
98+
new TextRendered("2", new Point(3, 6)),
99+
new TextRendered("3", new Point(3, 7)));
59100
}
60101

61102
private class StringsView : StackLayoutView
62103
{
63104
public StringsView(string[] strings)
64105
{
65-
foreach(var @string in strings)
106+
foreach (var @string in strings)
66107
{
67108
Add(new ContentView(@string));
68109
}
69110
}
70111
}
71112
}
72-
}
113+
114+
public class ParseResultView : ContentView<ParseResult>
115+
{
116+
public ParseResultView(ParseResult value) : base(value)
117+
{
118+
}
119+
}
120+
}

src/System.CommandLine.Rendering/AnsiRenderingSpanVisitor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ public AnsiRenderingSpanVisitor(
1414
{
1515
}
1616

17-
protected override void SetCursorPosition(int left, int top)
17+
protected override void SetCursorPosition(int? left = null, int? top = null)
1818
{
1919
Writer.Write(
2020
Cursor.Move
2121
.ToLocation(left: left + 1, top: top + 1)
2222
.EscapeSequence);
23+
2324
}
2425

2526
public override void VisitForegroundColorSpan(ForegroundColorSpan span)

src/System.CommandLine.Rendering/ConsoleExtensions.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System.CommandLine.IO;
5+
using System.CommandLine.Rendering.Views;
6+
47
namespace System.CommandLine.Rendering
58
{
69
public static class ConsoleExtensions
@@ -30,5 +33,17 @@ public static OutputMode DetectOutputMode(this IConsole console)
3033
return OutputMode.PlainText;
3134
}
3235
}
36+
37+
public static void Append(
38+
this IConsole console,
39+
View view,
40+
OutputMode outputMode = OutputMode.Auto)
41+
{
42+
var renderer = new ConsoleRenderer(console, outputMode);
43+
44+
view.Render(renderer, Region.Scrolling);
45+
46+
console.Out.WriteLine();
47+
}
3348
}
3449
}

src/System.CommandLine.Rendering/ConsoleRenderer.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ public void RenderToRegion(
3434
RenderToRegion(formatted, region);
3535
}
3636

37+
public void Append(FormattableString value) => Append(Formatter.ParseToSpan(value));
38+
39+
public void Append(Span span)
40+
{
41+
Render(span);
42+
}
43+
3744
public void RenderToRegion(
3845
FormattableString value,
3946
Region region)
@@ -52,6 +59,11 @@ public void RenderToRegion(
5259
throw new ArgumentNullException(nameof(region));
5360
}
5461

62+
Render(span, region);
63+
}
64+
65+
private void Render(Span span, Region region = null)
66+
{
5567
if (span == null)
5668
{
5769
span = Span.Empty();

src/System.CommandLine.Rendering/ContentRenderingSpanVisitor.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,9 @@ protected virtual bool TryStartNewLine()
202202
return true;
203203
}
204204

205-
private void TrySetCursorPosition(int left, int top)
205+
private void TrySetCursorPosition(
206+
int left,
207+
int? top = null)
206208
{
207209
if (left == _cursorLeft &&
208210
top == _cursorTop)
@@ -211,11 +213,16 @@ private void TrySetCursorPosition(int left, int top)
211213
}
212214

213215
_cursorLeft = left;
214-
_cursorTop = top;
216+
if (top != null)
217+
{
218+
_cursorTop = top.Value;
219+
}
215220

216221
SetCursorPosition(_cursorLeft, _cursorTop);
217222
}
218223

219-
protected abstract void SetCursorPosition(int left, int top);
224+
protected abstract void SetCursorPosition(
225+
int? left = null,
226+
int? top = null);
220227
}
221228
}

src/System.CommandLine.Rendering/EntireConsoleRegion.cs

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace System.CommandLine.Rendering
5+
{
6+
internal class EntireTerminalRegion : Region
7+
{
8+
public EntireTerminalRegion() : base(0, 0, Console.WindowWidth, Console.WindowHeight, false)
9+
{
10+
}
11+
12+
public override int Height => Console.WindowHeight;
13+
14+
public override int Width => Console.WindowWidth;
15+
16+
public override int Top => Console.CursorTop;
17+
18+
public override int Left => Console.CursorLeft;
19+
}
20+
21+
internal class ScrollingTerminalRegion : Region
22+
{
23+
public ScrollingTerminalRegion() : base(0, 0, Console.WindowWidth, Console.WindowHeight, false)
24+
{
25+
}
26+
27+
public override int Height => int.MaxValue;
28+
29+
public override int Width => Console.WindowWidth;
30+
31+
public override int Top => Console.CursorTop;
32+
33+
public override int Left => Console.CursorLeft;
34+
}
35+
}

src/System.CommandLine.Rendering/FileRenderingSpanVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public FileRenderingSpanVisitor(
1414
{
1515
}
1616

17-
protected override void SetCursorPosition(int left, int top)
17+
protected override void SetCursorPosition(int? left = null, int? top = null)
1818
{
1919
if (top > 0 && left == 0)
2020
{

0 commit comments

Comments
 (0)