8000 Add minimal progress bar using ANSI rendering (#14414) · PowerShell/PowerShell@887467e · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 887467e

Browse files
authored
Add minimal progress bar using ANSI rendering (#14414)
1 parent fdc9a91 commit 887467e

File tree

6 files changed

+328
-60
lines changed

6 files changed

+328
-60
lines changed

src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,11 @@ internal override
516516
Visit(ProgressNode node, ArrayList unused, int unusedToo)
517517
{
518518
node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1);
519-
node.Style = ProgressNode.RenderStyle.FullPlus;
519+
520+
node.Style = ProgressNode.IsMinimalProgressRenderingEnabled()
521+
? ProgressNode.RenderStyle.Ansi
522+
: node.Style = ProgressNode.RenderStyle.FullPlus;
523+
520524
return true;
521525
}
522526
}
@@ -582,6 +586,13 @@ internal override
582586
}
583587

584588
ArrayList result = new ArrayList();
589+
590+
if (ProgressNode.IsMinimalProgressRenderingEnabled())
591+
{
592+
RenderHelper(result, _topLevelNodes, indentation: 0, maxWidth, rawUI);
593+
return (string[])result.ToArray(typeof(string));
594+
}
595+
585596
string border = StringUtil.Padding(maxWidth);
586597

587598
result.Add(border);

src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
using System.Management.Automation;
77
using System.Management.Automation.Host;
88
using System.Management.Automation.Internal;
9+
using System.Text;
10+
11+
using Microsoft.PowerShell.Commands.Internal.Format;
912

1013
using Dbg = System.Management.Automation.Diagnostics;
1114

@@ -20,7 +23,7 @@ namespace Microsoft.PowerShell
2023
ProgressNode : ProgressRecord
2124
{
2225
/// <summary>
23-
/// Indicates the various layouts for rendering a particular node. Each style is progressively less terse.
26+
/// Indicates the various layouts for rendering a particular node.
2427
/// </summary>
2528
internal
2629
enum
@@ -40,6 +43,11 @@ namespace Microsoft.PowerShell
4043
/// The node will be displayed the same as Full, plus, the whole StatusDescription and CurrentOperation will be displayed (in multiple lines if needed).
4144
/// </summary>
4245
FullPlus = 4,
46+
47+
/// <summary>
48+
/// The node will be displayed using ANSI escape sequences.
49+
/// </summary>
50+
Ansi = 5,
4351
}
4452

4553
/// <summary>
@@ -56,7 +64,11 @@ namespace Microsoft.PowerShell
5664
this.PercentComplete = Math.Min(record.PercentComplete, 100);
5765
this.SecondsRemaining = record.SecondsRemaining;
5866
this.RecordType = record.RecordType;
59-
this.Style = RenderStyle.FullPlus;
67+
68+
this.Style = IsMinimalProgressRenderingEnabled()
69+
? RenderStyle.Ansi
70+
: this.Style = RenderStyle.FullPlus;
71+
6072
this.SourceId = sourceId;
6173
}
6274

@@ -98,6 +110,9 @@ namespace Microsoft.PowerShell
98110
case RenderStyle.Minimal:
99111
RenderMinimal(strCollection, indentation, maxWidth, rawUI);
100112
break;
113+
case RenderStyle.Ansi:
114+
RenderAnsi(strCollection, indentation, maxWidth);
115+
break;
101116
case RenderStyle.Invisible:
102117
// do nothing
103118
break;
@@ -336,6 +351,88 @@ private static void RenderFullDescription(string description, string indent, int
336351
maxWidth));
337352
}
338353

354+ internal static bool IsMinimalProgressRenderingEnabled()
355+
{
356+
return ExperimentalFeature.IsEnabled(ExperimentalFeature.PSAnsiProgressFeatureName) && PSStyle.Instance.Progress.View == ProgressView.Minimal;
357+
}
358+
359+
/// <summary>
360+
/// Renders a node in the "ANSI" style.
361+
/// </summary>
362+
/// <param name="strCollection">
363+
/// List of strings to which the node's rendering will be appended.
364+
/// </param>
365+
/// <param name="indentation">
366+
/// The indentation level in chars at which the node should be rendered.
367+
/// </param>
368+
/// <param name="maxWidth">
369+
/// The maximum number of chars that the rendering is allowed to consume.
370+
/// </param>
371+
private
372+
void
373+
RenderAnsi(ArrayList strCollection, int indentation, int maxWidth)
374+
{
375+
string indent = StringUtil.Padding(indentation);
376+
string secRemain = string.Empty;
377+
if (SecondsRemaining >= 0)
378+
{
379+
secRemain = SecondsRemaining.ToString() + "s";
380+
}
381+
382+
int secRemainLength = secRemain.Length + 1;
383+
384+
// limit progress bar to 120 chars as no need to render full width
385+
if (PSStyle.Instance.Progress.MaxWidth > 0 && maxWidth > PSStyle.Instance.Progress.MaxWidth)
386+
{
387+
maxWidth = PSStyle.Instance.Progress.MaxWidth;
388+
}
389+
390+
// 4 is for the extra space and square brackets below and one extra space
391+
int barWidth = maxWidth - Activity.Length - indentation - 4;
392+
393+
var sb = new StringBuilder();
394+
int padding = maxWidth + PSStyle.Instance.Progress.Style.Length + PSStyle.Instance.Reverse.Length + PSStyle.Instance.ReverseOff.Length;
395+
sb.Append(PSStyle.Instance.Reverse);
396+
397+
if (StatusDescription.Length > barWidth - secRemainLength)
398+
{
399+
sb.Append(StatusDescription.Substring(0, barWidth - secRemainLength - 1));
400+
sb.Append(PSObjectHelper.Ellipsis);
401+
}
402+
else
403+
{
404+
sb.Append(StatusDescription);
405+
}
406+
407+
sb.Append(string.Empty.PadRight(barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength));
408+
sb.Append(secRemain);
409+
410+
if (PercentComplete > 0 && PercentComplete < 100)
411+
{
412+
int barLength = PercentComplete * barWidth / 100;
413+
if (barLength >= barWidth)
414+
{
415+
barLength = barWidth - 1;
416+
}
417+
418+
sb.Insert(barLength + PSStyle.Instance.Reverse.Length, PSStyle.Instance.ReverseOff);
419+
}
420+
else
421+
{
422+
sb.Append(PSStyle.Instance.ReverseOff);
423+
}
424+
425+
strCollection.Add(
426+
StringUtil.Format(
427+
"{0}{1}{2} [{3}]{4}",
428+
indent,
429+
PSStyle.Instance.Progress.Style,
430+
Activity,
431+
sb.ToString(),
432+
PSStyle.Instance.Reset)
433+
.PadRight(padding));
434+
}
435+
339436
/// <summary>
340437
/// The nodes that have this node as their parent.
341438
/// </summary>
@@ -396,6 +493,9 @@ internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth)
396493
case RenderStyle.Invisible:
397494
return 0;
398495

496+
case RenderStyle.Ansi:
497+
return 1;
498+
399499
default:
400500
Dbg.Assert(false, "Unknown RenderStyle value");
401501
break;

0 commit comments

Comments
 (0)
0