-
-
Notifications
You must be signed in to change notification settings - Fork 471
/
DefaultProgressRenderer.cs
131 lines (107 loc) · 3.88 KB
/
DefaultProgressRenderer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
namespace Spectre.Console;
internal sealed class DefaultProgressRenderer : ProgressRenderer
{
private readonly IAnsiConsole _console;
private readonly List<ProgressColumn> _columns;
private readonly LiveRenderable _live;
private readonly object _lock;
private readonly Stopwatch _stopwatch;
private readonly bool _hideCompleted;
private readonly Func<IRenderable, IReadOnlyList<ProgressTask>, IRenderable> _renderHook;
private TimeSpan _lastUpdate;
public override TimeSpan RefreshRate { get; }
public DefaultProgressRenderer(IAnsiConsole console, List<ProgressColumn> columns, TimeSpan refreshRate, bool hideCompleted, Func<IRenderable, IReadOnlyList<ProgressTask>, IRenderable> renderHook)
{
_console = console ?? throw new ArgumentNullException(nameof(console));
_columns = columns ?? throw new ArgumentNullException(nameof(columns));
_live = new LiveRenderable(console);
_lock = new object();
_stopwatch = new Stopwatch();
_lastUpdate = TimeSpan.Zero;
_hideCompleted = hideCompleted;
_renderHook = renderHook;
RefreshRate = refreshRate;
}
public override void Started()
{
_console.Cursor.Hide();
}
public override void Completed(bool clear)
{
lock (_lock)
{
if (clear)
{
_console.Write(_live.RestoreCursor());
}
else
{
if (_live.HasRenderable && _live.DidOverflow)
{
// Redraw the whole live renderable
_console.Write(_live.RestoreCursor());
_live.Overflow = VerticalOverflow.Visible;
_console.Write(_live.Target);
}
_console.WriteLine();
}
_console.Cursor.Show();
}
}
public override void Update(ProgressContext context)
{
lock (_lock)
{
if (!_stopwatch.IsRunning)
{
_stopwatch.Start();
}
var renderContext = RenderOptions.Create(_console, _console.Profile.Capabilities);
var delta = _stopwatch.Elapsed - _lastUpdate;
_lastUpdate = _stopwatch.Elapsed;
var grid = new Grid();
for (var columnIndex = 0; columnIndex < _columns.Count; columnIndex++)
{
var column = new GridColumn().PadRight(1);
var columnWidth = _columns[columnIndex].GetColumnWidth(renderContext);
if (columnWidth != null)
{
column.Width = columnWidth;
}
if (_columns[columnIndex].NoWrap)
{
column.NoWrap();
}
// Last column?
if (columnIndex == _columns.Count - 1)
{
column.PadRight(0);
}
grid.AddColumn(column);
}
// Add rows
var tasks = context.GetTasks();
var layout = new Grid();
layout.AddColumn();
foreach (var task in tasks.Where(tsk => !(_hideCompleted && tsk.IsFinished)))
{
var columns = _columns.Select(column => column.Render(renderContext, task, delta));
grid.AddRow(columns.ToArray());
}
layout.AddRow(grid);
_live.SetRenderable(new Padder(_renderHook(layout, tasks), new Padding(0, 1)));
}
}
public override IEnumerable<IRenderable> Process(RenderOptions options, IEnumerable<IRenderable> renderables)
{
lock (_lock)
{
yield return _live.PositionCursor();
foreach (var renderable in renderables)
{
yield return renderable;
}
yield return _live;
}
}
}