From 37f0719dd0a2442faf0d435e213de9bf078029c5 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Sun, 13 Dec 2020 15:59:17 -0800 Subject: [PATCH 01/21] Add simpler progress bar using ANSI rendering --- .../host/msh/PendingProgress.cs | 18 +++- .../host/msh/ProgressNode.cs | 85 ++++++++++++++++++- .../host/msh/ProgressPane.cs | 31 ++++++- .../FormatAndOutput/common/PSStyle.cs | 5 ++ .../ExperimentalFeature.cs | 3 + 5 files changed, 138 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index 89901b18126..2485f9e7785 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -516,7 +516,16 @@ internal override Visit(ProgressNode node, ArrayList unused, int unusedToo) { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); - node.Style = ProgressNode.RenderStyle.FullPlus; + + if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + node.Style = ProgressNode.RenderStyle.Ansi; + } + else + { + node.Style = ProgressNode.RenderStyle.FullPlus; + } + return true; } } @@ -582,6 +591,13 @@ internal override } ArrayList result = new ArrayList(); + + if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + RenderHelper(result, _topLevelNodes, 0, maxWidth, rawUI); + return (string[])result.ToArray(typeof(string)); + } + string border = StringUtil.Padding(maxWidth); result.Add(border); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 438ea03c669..56f570c97b7 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -7,6 +7,8 @@ using System.Management.Automation.Host; using System.Management.Automation.Internal; +using Microsoft.PowerShell.Commands.Internal.Format; + using Dbg = System.Management.Automation.Diagnostics; namespace Microsoft.PowerShell @@ -40,6 +42,11 @@ namespace Microsoft.PowerShell /// The node will be displayed the same as Full, plus, the whole StatusDescription and CurrentOperation will be displayed (in multiple lines if needed). /// FullPlus = 4, + + /// + /// The node will be displayed using ANSI escape sequences + /// + Ansi = 5, } /// @@ -56,7 +63,16 @@ namespace Microsoft.PowerShell this.PercentComplete = Math.Min(record.PercentComplete, 100); this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - this.Style = RenderStyle.FullPlus; + + if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + this.Style = RenderStyle.Ansi; + } + else + { + this.Style = RenderStyle.FullPlus; + } + this.SourceId = sourceId; } @@ -98,6 +114,9 @@ namespace Microsoft.PowerShell case RenderStyle.Minimal: RenderMinimal(strCollection, indentation, maxWidth, rawUI); break; + case RenderStyle.Ansi: + RenderAnsi(strCollection, indentation, maxWidth, rawUI); + break; case RenderStyle.Invisible: // do nothing break; @@ -336,6 +355,67 @@ private static void RenderFullDescription(string description, string indent, int maxWidth)); } + /// + /// Renders a node in the "ANSI" style. + /// + /// + /// List of strings to which the node's rendering will be appended. + /// + /// + /// The indentation level (in BufferCells) at which the node should be rendered. + /// + /// + /// The maximum number of BufferCells that the rendering is allowed to consume. + /// + /// + /// The PSHostRawUserInterface used to gauge string widths in the rendering. + /// + private + void + RenderAnsi(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI) + { + string indent = StringUtil.Padding(indentation); + string secRemain = string.Empty; + if (SecondsRemaining >= 0) + { + secRemain = SecondsRemaining.ToString() + "s"; + } + + // 5 is for the extra space and square brackets below + int barWidth = maxWidth - Activity.Length - secRemain.Length - indentation - 5; + if (barWidth > 80) + { + barWidth = 80; + } + + string description; + if (StatusDescription.Length > barWidth) + { + description = StatusDescription.Substring(0, barWidth - 1) + PSObjectHelper.Ellipsis; + } + else + { + description = StatusDescription; + } + + description = description.PadRight(barWidth); + int barLength = PercentComplete * barWidth / 100; + description = description.Insert(barLength, PSStyle.Instance.ReverseOff); + + strCollection.Add( + StringUtil.TruncateToBufferCellWidth( + rawUI, + StringUtil.Format( + " {0}{1}{2} [{3}{4}] {5}", + indent, + PSStyle.Instance.Formatting.Progress, + Activity, + PSStyle.Instance.Reverse, + description, + secRemain), + maxWidth)); + } + /// /// The nodes that have this node as their parent. /// @@ -396,6 +476,9 @@ internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth) case RenderStyle.Invisible: return 0; + case RenderStyle.Ansi: + return 1; + default: Dbg.Assert(false, "Unknown RenderStyle value"); break; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 65f0267d0ed..114655de9a8 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Management.Automation; using System.Management.Automation.Host; using Dbg = System.Management.Automation.Diagnostics; @@ -127,8 +128,11 @@ class ProgressPane new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); #endif - // replace the saved region in the screen buffer with our progress display - _rawui.SetBufferContents(_location, tempProgressRegion); + if (!ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + // replace the saved region in the screen buffer with our progress display + _rawui.SetBufferContents(_location, tempProgressRegion); + } } } @@ -183,6 +187,29 @@ class ProgressPane return; } + if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + if (_location.X == 0 && _location.Y == 0) + { + for (int i = 0; i < contents.Length; i++) + { + Console.Out.WriteLine("a"); + } + + _location.Y = _rawui.CursorPosition.Y - contents.Length; + _location.X = 0; + } + + _rawui.CursorPosition = _location; + + foreach (string content in contents) + { + Console.Out.WriteLine(content); + } + + return; + } + // NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here... BufferCell[,] newRegion = _rawui.NewBufferCellArray(contents, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index 9d6876c44e0..f9dc5762278 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -293,6 +293,11 @@ public class FormattingData /// Gets or sets the style for debug messages. /// public string Debug { get; set; } = "\x1b[33;1m"; + + /// + /// Gets or sets the style for progress bar. + /// + public string Progress { get; set; } = "\x1b[36;1m"; } /// diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs index f1be0c5acc8..354c095cb33 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs @@ -129,6 +129,9 @@ static ExperimentalFeature() new ExperimentalFeature( name: "PSAnsiRendering", description: "Enable $PSStyle variable to control ANSI rendering of strings"), + new ExperimentalFeature( + name: "PSAnsiProgress", + description: "Enable lightweight progress bar that leverages ANSI codes for rendering"), }; EngineExperimentalFeatures = new ReadOnlyCollection(engineFeatures); From bd050c6f3ab4512e862d807a0397c05f63824adc Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Mon, 14 Dec 2020 07:25:15 -0800 Subject: [PATCH 02/21] fix rendering of progress bar --- .../host/msh/ProgressNode.cs | 72 +++++++++++-------- .../host/msh/ProgressPane.cs | 40 +++++++++-- .../FormatAndOutput/common/PSStyle.cs | 2 +- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 56f570c97b7..09d2061e5ec 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -6,6 +6,7 @@ using System.Management.Automation; using System.Management.Automation.Host; using System.Management.Automation.Internal; +using System.Text; using Microsoft.PowerShell.Commands.Internal.Format; @@ -115,7 +116,7 @@ namespace Microsoft.PowerShell RenderMinimal(strCollection, indentation, maxWidth, rawUI); break; case RenderStyle.Ansi: - RenderAnsi(strCollection, indentation, maxWidth, rawUI); + RenderAnsi(strCollection, indentation, maxWidth); break; case RenderStyle.Invisible: // do nothing @@ -362,17 +363,14 @@ private static void RenderFullDescription(string description, string indent, int /// List of strings to which the node's rendering will be appended. /// /// - /// The indentation level (in BufferCells) at which the node should be rendered. + /// The indentation level in chars at which the node should be rendered. /// /// - /// The maximum number of BufferCells that the rendering is allowed to consume. - /// - /// - /// The PSHostRawUserInterface used to gauge string widths in the rendering. + /// The maximum number of chars that the rendering is allowed to consume. /// private void - RenderAnsi(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI) + RenderAnsi(ArrayList strCollection, int indentation, int maxWidth) { string indent = StringUtil.Padding(indentation); string secRemain = string.Empty; @@ -381,39 +379,53 @@ private static void RenderFullDescription(string description, string indent, int secRemain = SecondsRemaining.ToString() + "s"; } - // 5 is for the extra space and square brackets below - int barWidth = maxWidth - Activity.Length - secRemain.Length - indentation - 5; - if (barWidth > 80) + int secRemainLength = secRemain.Length + 1; + + // 4 is for the extra space and square brackets below and one extra space + int barWidth = maxWidth - Activity.Length - indentation - 4; + + var sb = new StringBuilder(); + int padding = maxWidth + PSStyle.Instance.Formatting.Progress.Length + PSStyle.Instance.Reverse.Length + PSStyle.Instance.ReverseOff.Length; + sb.Append(PSStyle.Instance.Reverse); + + if (StatusDescription.Length > barWidth - secRemainLength) + { + sb.Append(StatusDescription.Substring(0, barWidth - secRemainLength - 1)); + sb.Append(PSObjectHelper.Ellipsis); + } + else { - barWidth = 80; + sb.Append(StatusDescription); } - string description; - if (StatusDescription.Length > barWidth) + sb.Append(string.Empty.PadRight(barWidth + PSStyle.Instance.Reverse.Length - sb.Length - secRemainLength)); + sb.Append(secRemain); + + if (PercentComplete > 0 && PercentComplete < 100) { - description = StatusDescription.Substring(0, barWidth - 1) + PSObjectHelper.Ellipsis; + int barLength = PercentComplete * barWidth / 100; + if (barLength >= barWidth) + { + barLength = barWidth - 1; + } + + sb.Insert(barLength, PSStyle.Instance.ReverseOff); } else { - description = StatusDescription; + sb.Append(PSStyle.Instance.ReverseOff); } - description = description.PadRight(barWidth); - int barLength = PercentComplete * barWidth / 100; - description = description.Insert(barLength, PSStyle.Instance.ReverseOff); - strCollection.Add( - StringUtil.TruncateToBufferCellWidth( - rawUI, - StringUtil.Format( - " {0}{1}{2} [{3}{4}] {5}", - indent, - PSStyle.Instance.Formatting.Progress, - Activity, - PSStyle.Instance.Reverse, - description, - secRemain), - maxWidth)); + StringUtil.Format( + "{0}{1}{2} [{3}]", + indent, + PSStyle.Instance.Formatting.Progress, + Activity, + sb.ToString() + ) + .PadRight(padding) + ); } /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 114655de9a8..94b03374931 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -144,6 +144,21 @@ class ProgressPane void Hide() { +/* + if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + { + // erase what was written previously + _rawui.CursorPosition = _location; + for (int i = 0; i < _rows; i++) + { + Console.Out.Write(" ".PadRight(Console.WindowWidth)); + } + + _rawui.CursorPosition = _location; + Console.CursorVisible = true; + } + else +*/ if (IsShowing) { // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, @@ -189,22 +204,32 @@ class ProgressPane if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) { - if (_location.X == 0 && _location.Y == 0) + Console.CursorVisible = false; + + if (contents.Length > _rows) { - for (int i = 0; i < contents.Length; i++) + int scrollRows = contents.Length - _rows; + + if (_rawui.CursorPosition.X != 0 || _rows == 0) + { + scrollRows++; + } + + _rows = contents.Length; + + for (int i = 0; i < scrollRows; i++) { - Console.Out.WriteLine("a"); + Console.Out.WriteLine(); } - _location.Y = _rawui.CursorPosition.Y - contents.Length; - _location.X = 0; + _location.Y = _rawui.CursorPosition.Y - _rows; } _rawui.CursorPosition = _location; - foreach (string content in contents) + for (int i = 0; i < contents.Length; i++) { - Console.Out.WriteLine(content); + Console.Out.Write(contents[i]); } return; @@ -257,6 +282,7 @@ class ProgressPane private Coordinates _location = new Coordinates(0, 0); private Coordinates _savedCursor; + private int _rows; private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index f9dc5762278..7c22b83f553 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -297,7 +297,7 @@ public class FormattingData /// /// Gets or sets the style for progress bar. /// - public string Progress { get; set; } = "\x1b[36;1m"; + public string Progress { get; set; } = "\x1b[33;1m"; } /// From e4fec6868c1e6d1e4a416c873fae592e0c5e4a18 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 14 Dec 2020 07:31:49 -0800 Subject: [PATCH 03/21] remove unused code, limit progress to 120 chars --- .../host/msh/ProgressNode.cs | 6 ++++++ .../host/msh/ProgressPane.cs | 17 +---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 09d2061e5ec..7c9a1ae17e7 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -381,6 +381,12 @@ private static void RenderFullDescription(string description, string indent, int int secRemainLength = secRemain.Length + 1; + // limit progress bar to 120 chars as no need to render full width + if (maxWidth > 120) + { + maxWidth = 120; + } + // 4 is for the extra space and square brackets below and one extra space int barWidth = maxWidth - Activity.Length - indentation - 4; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 94b03374931..da8380b5336 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -144,21 +144,6 @@ class ProgressPane void Hide() { -/* - if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) - { - // erase what was written previously - _rawui.CursorPosition = _location; - for (int i = 0; i < _rows; i++) - { - Console.Out.Write(" ".PadRight(Console.WindowWidth)); - } - - _rawui.CursorPosition = _location; - Console.CursorVisible = true; - } - else -*/ if (IsShowing) { // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, @@ -229,7 +214,7 @@ class ProgressPane for (int i = 0; i < contents.Length; i++) { - Console.Out.Write(contents[i]); + Console.Out.WriteLine(contents[i]); } return; From b91b75e022a2e2c78a3ce83ecee59ec78fae179e Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 14 Dec 2020 08:12:39 -0800 Subject: [PATCH 04/21] fix codefactor issues --- .../host/msh/ProgressNode.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 7c9a1ae17e7..821b9994819 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -45,7 +45,7 @@ namespace Microsoft.PowerShell FullPlus = 4, /// - /// The node will be displayed using ANSI escape sequences + /// The node will be displayed using ANSI escape sequences. /// Ansi = 5, } @@ -428,10 +428,8 @@ private static void RenderFullDescription(string description, string indent, int indent, PSStyle.Instance.Formatting.Progress, Activity, - sb.ToString() - ) - .PadRight(padding) - ); + sb.ToString()) + .PadRight(padding)); } /// From 3c992bc2f9b9fd450455218a596a5edd57088c94 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 14 Dec 2020 09:35:53 -0800 Subject: [PATCH 05/21] restore cursor visibility --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index da8380b5336..929f0086f92 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -217,6 +217,8 @@ class ProgressPane Console.Out.WriteLine(contents[i]); } + Console.CursorVisible = true; + return; } From c98e865738ab38e20c77e4623353064318f3d0de Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 14 Dec 2020 10:17:07 -0800 Subject: [PATCH 06/21] Fix initial rendering issue to take into account length of Reverse escape sequence --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 821b9994819..369cd64f439 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -415,7 +415,7 @@ private static void RenderFullDescription(string description, string indent, int barLength = barWidth - 1; } - sb.Insert(barLength, PSStyle.Instance.ReverseOff); + sb.Insert(barLength + PSStyle.Instance.Reverse.Length, PSStyle.Instance.ReverseOff); } else { From 7f18605f7520d507bc3a5fef4b3b4a185af523b5 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 8 Jan 2021 17:45:58 -0800 Subject: [PATCH 07/21] Support configuration for progress --- .../host/msh/ProgressNode.cs | 10 ++-- .../host/msh/ProgressPane.cs | 13 ++++- .../PowerShellCore_format_ps1xml.cs | 19 ++++++++ .../FormatAndOutput/common/PSStyle.cs | 47 +++++++++++++++++-- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 369cd64f439..e199f55680c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -65,7 +65,7 @@ namespace Microsoft.PowerShell this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && (PSStyle.Instance.Progress.View == ProgressView.Minimal || PSStyle.Instance.Progress.View == ProgressView.MinimalWithClear)) { this.Style = RenderStyle.Ansi; } @@ -382,16 +382,16 @@ private static void RenderFullDescription(string description, string indent, int int secRemainLength = secRemain.Length + 1; // limit progress bar to 120 chars as no need to render full width - if (maxWidth > 120) + if (PSStyle.Instance.Progress.MaxWidth > 0 && maxWidth > PSStyle.Instance.Progress.MaxWidth) { - maxWidth = 120; + maxWidth = PSStyle.Instance.Progress.MaxWidth; } // 4 is for the extra space and square brackets below and one extra space int barWidth = maxWidth - Activity.Length - indentation - 4; var sb = new StringBuilder(); - int padding = maxWidth + PSStyle.Instance.Formatting.Progress.Length + PSStyle.Instance.Reverse.Length + PSStyle.Instance.ReverseOff.Length; + int padding = maxWidth + PSStyle.Instance.Progress.Style.Length + PSStyle.Instance.Reverse.Length + PSStyle.Instance.ReverseOff.Length; sb.Append(PSStyle.Instance.Reverse); if (StatusDescription.Length > barWidth - secRemainLength) @@ -426,7 +426,7 @@ private static void RenderFullDescription(string description, string indent, int StringUtil.Format( "{0}{1}{2} [{3}]", indent, - PSStyle.Instance.Formatting.Progress, + PSStyle.Instance.Progress.Style, Activity, sb.ToString()) .PadRight(padding)); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 929f0086f92..f9f9ab2f16f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -144,7 +144,18 @@ class ProgressPane void Hide() { - if (IsShowing) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.MinimalWithClear) + { + // erase what was written previously + _rawui.CursorPosition = _location; + for (int i = 0; i < _rows; i++) + { + Console.Out.Write(" ".PadRight(Console.WindowWidth)); + } + + _rawui.CursorPosition = _location; + } + else if (IsShowing) { // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index d881f551b31..22e1076e49c 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -272,6 +272,10 @@ internal static IEnumerable GetFormatData() "System.Management.Automation.PSStyle+FormattingData", ViewsOf_System_Management_Automation_PSStyleFormattingData()); + yield return new ExtendedTypeDefinition( + "System.Management.Automation.PSStyle+ProgressConfiguration", + ViewsOf_System_Management_Automation_PSStyleProgressConfiguration()); + yield return new ExtendedTypeDefinition( "System.Management.Automation.PSStyle+ForegroundColor", ViewsOf_System_Management_Automation_PSStyleForegroundColor()); @@ -2047,6 +2051,9 @@ private static IEnumerable ViewsOf_System_Management_Autom .AddItemScriptBlock(@"""$($_.Formatting.Error)$($_.Formatting.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Error") .AddItemScriptBlock(@"""$($_.Formatting.Warning)$($_.Formatting.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Warning") .AddItemScriptBlock(@"""$($_.Formatting.Verbose)$($_.Formatting.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Verbose") + .AddItemScriptBlock(@"""$($_.Progress.Style)$($_.Progress.Style.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Progress.Style") + .AddItemScriptBlock(@"""$($_.Progress.MaxWidth)""", label: "Progress.MaxWidth") + .AddItemScriptBlock(@"""$($_.Progress.View)""", label: "Progress.View") .AddItemScriptBlock(@"""$($_.Formatting.Debug)$($_.Formatting.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Debug") .AddItemScriptBlock(@"""$($_.Foreground.Black)$($_.Foreground.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Black") .AddItemScriptBlock(@"""$($_.Foreground.White)$($_.Foreground.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.White") @@ -2099,6 +2106,18 @@ private static IEnumerable ViewsOf_System_Management_Autom .EndList()); } + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleProgressConfiguration() + { + yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ProgressConfiguration", + ListControl.Create() + .StartEntry() + .AddItemScriptBlock(@"""$($_.Style)$($_.Style.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Style") + .AddItemProperty(@"MaxWidth") + .AddItemProperty(@"View") + .EndEntry() + .EndList()); + } + private static IEnumerable ViewsOf_System_Management_Automation_PSStyleForegroundColor() { yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ForegroundColor", diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index 7c22b83f553..dc9c71098bc 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -23,6 +23,21 @@ public enum OutputRendering } #endregion OutputRendering + /// + /// Defines the options for views of progress rendering. + /// + public enum ProgressView + { + /// Minimal + Minimal = 0, + + /// MinimalWithClear + MinimalWithClear = 1, + + /// Full + Full = 2, + } + #region PSStyle /// /// Contains configuration for how PowerShell renders text. @@ -259,6 +274,27 @@ public string FromRgb(int rgb) } } + /// + /// Contains configuration for the progress bar visualization. + /// + public class ProgressConfiguration + { + /// + /// Gets or sets the style for progress bar. + /// + public string Style { get; set; } = "\x1b[33;1m"; + + /// + /// Gets or sets the max width of the progress bar. + /// + public int MaxWidth { get; set; } = 120; + + /// + /// Gets or sets the style for progress bar. + /// + public ProgressView View { get; set; } = ProgressView.Minimal; + } + /// /// Contains formatting styles for steams and objects. /// @@ -293,11 +329,6 @@ public class FormattingData /// Gets or sets the style for debug messages. /// public string Debug { get; set; } = "\x1b[33;1m"; - - /// - /// Gets or sets the style for progress bar. - /// - public string Progress { get; set; } = "\x1b[33;1m"; } /// @@ -396,6 +427,11 @@ public string FormatHyperlink(string text, Uri link) /// public FormattingData Formatting { get; } + /// + /// Gets the configuration for progress rendering. + /// + public ProgressConfiguration Progress { get; } + /// /// Gets foreground colors. /// @@ -411,6 +447,7 @@ public string FormatHyperlink(string text, Uri link) private PSStyle() { Formatting = new FormattingData(); + Progress = new ProgressConfiguration(); Foreground = new ForegroundColor(); Background = new BackgroundColor(); } From 6c3ae08b7afa897138ee4365f2b4adcbe1c5b089 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 28 Jan 2021 16:25:56 -0800 Subject: [PATCH 08/21] Fix rendering when output is written --- .../host/msh/PendingProgress.cs | 6 +- .../host/msh/ProgressNode.cs | 4 +- .../host/msh/ProgressPane.cs | 209 ++++++++++-------- .../FormatAndOutput/common/PSStyle.cs | 5 +- 4 files changed, 122 insertions(+), 102 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index 2485f9e7785..aa3d5f0506a 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -516,8 +516,8 @@ internal override Visit(ProgressNode node, ArrayList unused, int unusedToo) { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); - - if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) { node.Style = ProgressNode.RenderStyle.Ansi; } @@ -592,7 +592,7 @@ internal override ArrayList result = new ArrayList(); - if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) { RenderHelper(result, _topLevelNodes, 0, maxWidth, rawUI); return (string[])result.ToArray(typeof(string)); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index e199f55680c..fefac18b80b 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -65,7 +65,7 @@ namespace Microsoft.PowerShell this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && (PSStyle.Instance.Progress.View == ProgressView.Minimal || PSStyle.Instance.Progress.View == ProgressView.MinimalWithClear)) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) { this.Style = RenderStyle.Ansi; } @@ -422,6 +422,8 @@ private static void RenderFullDescription(string description, string indent, int sb.Append(PSStyle.Instance.ReverseOff); } + sb.Append(PSStyle.Instance.Reset); + strCollection.Add( StringUtil.Format( "{0}{1}{2} [{3}]", diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index f9f9ab2f16f..ebc8fdb505d 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -74,61 +74,75 @@ class ProgressPane _savedCursor = _rawui.CursorPosition; _location.X = 0; -#if UNIX - _location.Y = _rawui.CursorPosition.Y; - - // if cursor is not on left edge already move down one line - if (_rawui.CursorPosition.X != 0) + if (Platform.IsLinux || (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal)) { - _location.Y++; - _rawui.CursorPosition = _location; - } + _location.Y = _rawui.CursorPosition.Y; - // if the cursor is at the bottom, create screen buffer space by scrolling - int scrollRows = rows - ((_rawui.BufferSize.Height - 1) - _location.Y); - if (scrollRows > 0) - { - // Scroll the console screen up by 'scrollRows' - var bottomLocation = _location; - bottomLocation.Y = _rawui.BufferSize.Height; - _rawui.CursorPosition = bottomLocation; - for (int i = 0; i < scrollRows; i++) + // if cursor is not on left edge already move down one line + if (_rawui.CursorPosition.X != 0) { - Console.Out.Write('\n'); + _location.Y++; + _rawui.CursorPosition = _location; } - _location.Y -= scrollRows; - _savedCursor.Y -= scrollRows; - } + // if the cursor is at the bottom, create screen buffer space by scrolling + int scrollRows = rows - ((_rawui.BufferSize.Height - 1) - _location.Y); + if (scrollRows > 0) + { + // Scroll the console screen up by 'scrollRows' + var bottomLocation = _location; + bottomLocation.Y = _rawui.BufferSize.Height; + if (Platform.IsWindows) + { + bottomLocation.Y--; + } + + _rawui.CursorPosition = bottomLocation; + for (int i = 0; i < scrollRows; i++) + { + Console.Out.Write('\n'); + } + + _location.Y -= scrollRows; + _savedCursor.Y -= scrollRows; + } - // create cleared region to clear progress bar later - _savedRegion = tempProgressRegion; - for (int row = 0; row < rows; row++) - { - for (int col = 0; col < cols; col++) + // create cleared region to clear progress bar later + _savedRegion = tempProgressRegion; + for (int row = 0; row < rows; row++) { - _savedRegion[row, col].Character = ' '; + for (int col = 0; col < cols; col++) + { + _savedRegion[row, col].Character = ' '; + _savedRegion[row, col].ForegroundColor = Console.ForegroundColor; + _savedRegion[row, col].BackgroundColor = Console.BackgroundColor; + } } - } - // put cursor back to where output should be - _rawui.CursorPosition = _location; -#else - _location = _rawui.WindowPosition; + // put cursor back to where output should be + _rawui.CursorPosition = _location; + } + else + { + _location = _rawui.WindowPosition; - // We have to show the progress pane in the first column, as the screen buffer at any point might contain - // a CJK double-cell characters, which makes it impractical to try to find a position where the pane would - // not slice a character. Column 0 is the only place where we know for sure we can place the pane. + // We have to show the progress pane in the first column, as the screen buffer at any point might contain + // a CJK double-cell characters, which makes it impractical to try to find a position where the pane would + // not slice a character. Column 0 is the only place where we know for sure we can place the pane. - _location.Y = Math.Min(_location.Y + 2, _bufSize.Height); + _location.Y = Math.Min(_location.Y + 2, _bufSize.Height); - // Save off the current contents of the screen buffer in the region that we will occupy - _savedRegion = - _rawui.GetBufferContents( - new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); -#endif + // Save off the current contents of the screen buffer in the region that we will occupy + _savedRegion = + _rawui.GetBufferContents( + new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); + } - if (!ExperimentalFeature.IsEnabled("PSAnsiProgress")) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + WriteContent(); + } + else { // replace the saved region in the screen buffer with our progress display _rawui.SetBufferContents(_location, tempProgressRegion); @@ -144,18 +158,7 @@ class ProgressPane void Hide() { - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.MinimalWithClear) - { - // erase what was written previously - _rawui.CursorPosition = _location; - for (int i = 0; i < _rows; i++) - { - Console.Out.Write(" ".PadRight(Console.WindowWidth)); - } - - _rawui.CursorPosition = _location; - } - else if (IsShowing) + if (IsShowing) { // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that @@ -188,8 +191,8 @@ class ProgressPane int maxWidth = _bufSize.Width; int maxHeight = Math.Max(5, _rawui.WindowSize.Height / 3); - string[] contents = pendingProgress.Render(maxWidth, maxHeight, _rawui); - if (contents == null) + _content = pendingProgress.Render(maxWidth, maxHeight, _rawui); + if (_content == null) { // There's nothing to show. @@ -198,44 +201,9 @@ class ProgressPane return; } - if (ExperimentalFeature.IsEnabled("PSAnsiProgress")) - { - Console.CursorVisible = false; - - if (contents.Length > _rows) - { - int scrollRows = contents.Length - _rows; - - if (_rawui.CursorPosition.X != 0 || _rows == 0) - { - scrollRows++; - } - - _rows = contents.Length; - - for (int i = 0; i < scrollRows; i++) - { - Console.Out.WriteLine(); - } - - _location.Y = _rawui.CursorPosition.Y - _rows; - } - - _rawui.CursorPosition = _location; - - for (int i = 0; i < contents.Length; i++) - { - Console.Out.WriteLine(contents[i]); - } - - Console.CursorVisible = true; - - return; - } - // NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here... - BufferCell[,] newRegion = _rawui.NewBufferCellArray(contents, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); + BufferCell[,] newRegion = _rawui.NewBufferCellArray(_content, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); Dbg.Assert(newRegion != null, "NewBufferCellArray has failed!"); if (_progressRegion == null) @@ -273,17 +241,70 @@ class ProgressPane } else { - _rawui.SetBufferContents(_location, _progressRegion); + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + WriteContent(); + } + else + { + _rawui.SetBufferContents(_location, _progressRegion); + } + } + } + } + + private void WriteContent() + { + if (_content != null && ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + Console.CursorVisible = false; + var currentPosition = _rawui.CursorPosition; + + if (_content.Length > _previousRows) + { + int scrollRows = _content.Length - _previousRows; + + if (_rawui.CursorPosition.X != 0 || _previousRows == 0) + { + scrollRows++; + } + + _previousRows = _content.Length; + + for (int i = 0; i < scrollRows; i++) + { + Console.Out.WriteLine(); + } + + _location.Y = _rawui.CursorPosition.Y - _previousRows; } + + _rawui.CursorPosition = _location; + + for (int i = 0; i < _content.Length; i++) + { + if (i < _content.Length - 1) + { + Console.Out.WriteLine(_content[i]); + } + else + { + Console.Out.Write(_content[i]); + } + } + + _rawui.CursorPosition = currentPosition; + Console.CursorVisible = true; } } private Coordinates _location = new Coordinates(0, 0); private Coordinates _savedCursor; - private int _rows; + private int _previousRows; private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; + private string[] _content; private readonly PSHostRawUserInterface _rawui; private readonly ConsoleHostUserInterface _ui; } diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index dc9c71098bc..53f69289238 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -30,12 +30,9 @@ public enum ProgressView { /// Minimal Minimal = 0, - - /// MinimalWithClear - MinimalWithClear = 1, /// Full - Full = 2, + Full = 1, } #region PSStyle From 5e9c7bfd5cb9c4ed3af69dbf1918f59e66550142 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 28 Jan 2021 16:37:33 -0800 Subject: [PATCH 09/21] remove unnecessary duplicated scrolling to create space --- .../host/msh/ProgressPane.cs | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index ebc8fdb505d..fa8dc8049b7 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -259,26 +259,6 @@ private void WriteContent() { Console.CursorVisible = false; var currentPosition = _rawui.CursorPosition; - - if (_content.Length > _previousRows) - { - int scrollRows = _content.Length - _previousRows; - - if (_rawui.CursorPosition.X != 0 || _previousRows == 0) - { - scrollRows++; - } - - _previousRows = _content.Length; - - for (int i = 0; i < scrollRows; i++) - { - Console.Out.WriteLine(); - } - - _location.Y = _rawui.CursorPosition.Y - _previousRows; - } - _rawui.CursorPosition = _location; for (int i = 0; i < _content.Length; i++) @@ -292,7 +272,6 @@ private void WriteContent() Console.Out.Write(_content[i]); } } - _rawui.CursorPosition = currentPosition; Console.CursorVisible = true; } @@ -300,7 +279,7 @@ private void WriteContent() private Coordinates _location = new Coordinates(0, 0); private Coordinates _savedCursor; - private int _previousRows; +// private int _previousRows; private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; From 20aa59f134cdf4b28899667e650887d66c748c95 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 28 Jan 2021 18:07:12 -0800 Subject: [PATCH 10/21] Fix cleanup by not unnecessarily using buffercells but instead writing empty lines --- .../host/msh/ProgressPane.cs | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index fa8dc8049b7..38bde6a152b 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -71,10 +71,16 @@ class ProgressPane int rows = tempProgressRegion.GetLength(0); int cols = tempProgressRegion.GetLength(1); + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + rows = _content.Length; + cols = PSStyle.Instance.Progress.MaxWidth; + } + _savedCursor = _rawui.CursorPosition; _location.X = 0; - if (Platform.IsLinux || (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal)) + if (!Platform.IsWindows || ((ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal))) { _location.Y = _rawui.CursorPosition.Y; @@ -109,13 +115,14 @@ class ProgressPane // create cleared region to clear progress bar later _savedRegion = tempProgressRegion; - for (int row = 0; row < rows; row++) + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View != ProgressView.Minimal) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { - _savedRegion[row, col].Character = ' '; - _savedRegion[row, col].ForegroundColor = Console.ForegroundColor; - _savedRegion[row, col].BackgroundColor = Console.BackgroundColor; + for (int col = 0; col < cols; col++) + { + _savedRegion[row, col].Character = ' '; + } } } @@ -160,12 +167,31 @@ class ProgressPane { if (IsShowing) { - // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, - // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that - // detecting a change would be at least as expensive as chucking the savedRegion and rebuilding it. And it would - // be very complicated. + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + _rawui.CursorPosition = _location; + for (int i = 0; i < _content.Length; i++) + { + if (i < _content.Length - 1) + { + Console.Out.WriteLine(string.Empty.PadRight(PSStyle.Instance.Progress.MaxWidth)); + } + else + { + Console.Out.Write(string.Empty.PadRight(PSStyle.Instance.Progress.MaxWidth)); + } + } + } + else + { + // It would be nice if we knew that the saved region could be kept for the next time Show is called, but alas, + // we have no way of knowing if the screen buffer has changed since we were hidden. By "no good way" I mean that + // detecting a change would be at least as expensive as chucking the savedRegion and rebuilding it. And it would + // be very complicated. + + _rawui.SetBufferContents(_location, _savedRegion); + } - _rawui.SetBufferContents(_location, _savedRegion); _savedRegion = null; _rawui.CursorPosition = _savedCursor; } @@ -201,9 +227,16 @@ class ProgressPane return; } - // NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here... + BufferCell[,] newRegion; + if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + { + newRegion = new BufferCell[0,_content.Length]; + } + else + { + newRegion = _rawui.NewBufferCellArray(_content, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); + } - BufferCell[,] newRegion = _rawui.NewBufferCellArray(_content, _ui.ProgressForegroundColor, _ui.ProgressBackgroundColor); Dbg.Assert(newRegion != null, "NewBufferCellArray has failed!"); if (_progressRegion == null) @@ -279,7 +312,6 @@ private void WriteContent() private Coordinates _location = new Coordinates(0, 0); private Coordinates _savedCursor; -// private int _previousRows; private Size _bufSize; private BufferCell[,] _savedRegion; private BufferCell[,] _progressRegion; From 3e06cdc4e61225fbdec4fa2cba8e4d0c31eb60e2 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 28 Jan 2021 18:11:34 -0800 Subject: [PATCH 11/21] remove unnecessary parenthesis --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 38bde6a152b..a389a476703 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -80,7 +80,7 @@ class ProgressPane _savedCursor = _rawui.CursorPosition; _location.X = 0; - if (!Platform.IsWindows || ((ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal))) + if (!Platform.IsWindows || (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal)) { _location.Y = _rawui.CursorPosition.Y; From a09dc88f9c056ad13c3cb278841fd8fc1a16a4b0 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 28 Jan 2021 18:48:17 -0800 Subject: [PATCH 12/21] correctly handle when Progress.MaxWidth > Console.WindowWidth --- .../host/msh/ProgressPane.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index a389a476703..f8dd6f3f8b9 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -75,6 +75,10 @@ class ProgressPane { rows = _content.Length; cols = PSStyle.Instance.Progress.MaxWidth; + if (PSStyle.Instance.Progress.MaxWidth > _bufSize.Width) + { + cols = _bufSize.Width; + } } _savedCursor = _rawui.CursorPosition; @@ -170,15 +174,21 @@ class ProgressPane if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) { _rawui.CursorPosition = _location; + int maxWidth = PSStyle.Instance.Progress.MaxWidth; + if (maxWidth > _bufSize.Width) + { + maxWidth = _bufSize.Width; + } + for (int i = 0; i < _content.Length; i++) { if (i < _content.Length - 1) { - Console.Out.WriteLine(string.Empty.PadRight(PSStyle.Instance.Progress.MaxWidth)); + Console.Out.WriteLine(string.Empty.PadRight(maxWidth)); } else { - Console.Out.Write(string.Empty.PadRight(PSStyle.Instance.Progress.MaxWidth)); + Console.Out.Write(string.Empty.PadRight(maxWidth)); } } } From f69385545bd31b64f2056ab9478770e3e736cef8 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 28 Jan 2021 19:12:48 -0800 Subject: [PATCH 13/21] fix cleanup when done rendering --- .../host/msh/ProgressNode.cs | 7 +++---- .../host/msh/ProgressPane.cs | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index fefac18b80b..3391ec8393e 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -422,15 +422,14 @@ private static void RenderFullDescription(string description, string indent, int sb.Append(PSStyle.Instance.ReverseOff); } - sb.Append(PSStyle.Instance.Reset); - strCollection.Add( StringUtil.Format( - "{0}{1}{2} [{3}]", + "{0}{1}{2} [{3}]{4}", indent, PSStyle.Instance.Progress.Style, Activity, - sb.ToString()) + sb.ToString(), + PSStyle.Instance.Reset) .PadRight(padding)); } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index f8dd6f3f8b9..ded40d0e4d7 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -180,9 +180,9 @@ class ProgressPane maxWidth = _bufSize.Width; } - for (int i = 0; i < _content.Length; i++) + for (int i = 0; i < _savedRegion.GetLength(1); i++) { - if (i < _content.Length - 1) + if (i < _savedRegion.GetLength(1) - 1) { Console.Out.WriteLine(string.Empty.PadRight(maxWidth)); } From c0033bc8536bc2bea2fe4433e073d9288335c500 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 28 Jan 2021 19:24:28 -0800 Subject: [PATCH 14/21] address Codefactor --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs | 3 ++- .../FormatAndOutput/common/PSStyle.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index ded40d0e4d7..c5b7d1831e4 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -240,7 +240,7 @@ class ProgressPane BufferCell[,] newRegion; if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) { - newRegion = new BufferCell[0,_content.Length]; + newRegion = new BufferCell[0, _content.Length]; } else { @@ -315,6 +315,7 @@ private void WriteContent() Console.Out.Write(_content[i]); } } + _rawui.CursorPosition = currentPosition; Console.CursorVisible = true; } diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index 53f69289238..012519a0a13 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -28,10 +28,10 @@ public enum OutputRendering /// public enum ProgressView { - /// Minimal + /// Render progress using minimal space. Minimal = 0, - /// Full + /// Class rendering of progress. Full = 1, } From 60c50ba37930b532bed9b0f2d288069f6c22ffe0 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Fri, 29 Jan 2021 08:04:34 -0800 Subject: [PATCH 15/21] Remove unnecessary check --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index c5b7d1831e4..95be6b9657c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -298,7 +298,7 @@ class ProgressPane private void WriteContent() { - if (_content != null && ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (_content != null) { Console.CursorVisible = false; var currentPosition = _rawui.CursorPosition; From 5b34d26ee87f3e08254fcef92ed7cfdefb56045b Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 2 Feb 2021 13:57:03 -0800 Subject: [PATCH 16/21] address Rob's feedback --- .../host/msh/PendingProgress.cs | 6 +++--- .../host/msh/ProgressNode.cs | 7 ++++++- .../host/msh/ProgressPane.cs | 19 ++++++++++++------- .../FormatAndOutput/common/PSStyle.cs | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index aa3d5f0506a..e2ffc5c936f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -517,7 +517,7 @@ internal override { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { node.Style = ProgressNode.RenderStyle.Ansi; } @@ -592,9 +592,9 @@ internal override ArrayList result = new ArrayList(); - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { - RenderHelper(result, _topLevelNodes, 0, maxWidth, rawUI); + RenderHelper(result, _topLevelNodes, indentation: 0, maxWidth, rawUI); return (string[])result.ToArray(typeof(string)); } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 3391ec8393e..faf77e8bf79 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -65,7 +65,7 @@ namespace Microsoft.PowerShell this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (IsMinimalProgressRenderingEnabled()) { this.Style = RenderStyle.Ansi; } @@ -356,6 +356,11 @@ private static void RenderFullDescription(string description, string indent, int maxWidth)); } + internal static bool IsMinimalProgressRenderingEnabled() + { + return ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal; + } + /// /// Renders a node in the "ANSI" style. /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 95be6b9657c..6f4a7a6c1b3 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -71,11 +71,11 @@ class ProgressPane int rows = tempProgressRegion.GetLength(0); int cols = tempProgressRegion.GetLength(1); - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { rows = _content.Length; cols = PSStyle.Instance.Progress.MaxWidth; - if (PSStyle.Instance.Progress.MaxWidth > _bufSize.Width) + if (cols > _bufSize.Width) { cols = _bufSize.Width; } @@ -84,7 +84,7 @@ class ProgressPane _savedCursor = _rawui.CursorPosition; _location.X = 0; - if (!Platform.IsWindows || (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal)) + if (!Platform.IsWindows || ProgressNode.IsMinimalProgressRenderingEnabled()) { _location.Y = _rawui.CursorPosition.Y; @@ -149,7 +149,7 @@ class ProgressPane new Rectangle(_location.X, _location.Y, _location.X + cols - 1, _location.Y + rows - 1)); } - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { WriteContent(); } @@ -171,7 +171,7 @@ class ProgressPane { if (IsShowing) { - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { _rawui.CursorPosition = _location; int maxWidth = PSStyle.Instance.Progress.MaxWidth; @@ -238,8 +238,13 @@ class ProgressPane } BufferCell[,] newRegion; - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { + // Legacy progress rendering relies on a BufferCell which defines a character, foreground color, and background color + // per cell. This model doesn't work with ANSI escape sequences. However, there is existing logic on rendering that + // relies on the existence of the BufferCell to know if something has been rendered previously. Here we are creating + // an empty BufferCell, but using the second dimension to capture the number of rows so that we can clear that many + // elsewhere in Hide(). newRegion = new BufferCell[0, _content.Length]; } else @@ -284,7 +289,7 @@ class ProgressPane } else { - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal) + if (ProgressNode.IsMinimalProgressRenderingEnabled()) { WriteContent(); } diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index 012519a0a13..7fe9eceaeb3 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -39,7 +39,7 @@ public enum ProgressView /// /// Contains configuration for how PowerShell renders text. /// - public class PSStyle + public sealed class PSStyle { /// /// Contains foreground colors. From e4857629cbbb2841ed4b3bc60dc56848654c5937 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 4 Feb 2021 12:55:22 -0800 Subject: [PATCH 17/21] Update src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs Co-authored-by: Ilya --- .../host/msh/PendingProgress.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index e2ffc5c936f..9e456fbc814 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -517,14 +517,10 @@ internal override { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); - if (ProgressNode.IsMinimalProgressRenderingEnabled()) - { - node.Style = ProgressNode.RenderStyle.Ansi; - } - else - { - node.Style = ProgressNode.RenderStyle.FullPlus; - } +. node.Style = ProgressNode.IsMinimalProgressRenderingEnabled() + ? ProgressNode.RenderStyle.Ansi + : node.Style = ProgressNode.RenderStyle.FullPlus; + `` return true; } From 635476f32708db77ef53218a930ba57d8089636c Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 4 Feb 2021 12:55:35 -0800 Subject: [PATCH 18/21] Update src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs Co-authored-by: Ilya --- .../host/msh/ProgressNode.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index faf77e8bf79..16c07f5748a 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -65,14 +65,9 @@ namespace Microsoft.PowerShell this.SecondsRemaining = record.SecondsRemaining; this.RecordType = record.RecordType; - if (IsMinimalProgressRenderingEnabled()) - { - this.Style = RenderStyle.Ansi; - } - else - { - this.Style = RenderStyle.FullPlus; - } + this.Style = IsMinimalProgressRenderingEnabled() + ? RenderStyle.Ansi + : this.Style = RenderStyle.FullPlus; this.SourceId = sourceId; } From 69c36af1c6d20628f6997ffcd46e71b7c36ae27d Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 4 Feb 2021 12:57:47 -0800 Subject: [PATCH 19/21] Update src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs Co-authored-by: Ilya --- src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 6f4a7a6c1b3..3806b61cc62 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -303,7 +303,7 @@ class ProgressPane private void WriteContent() { - if (_content != null) + if (_content is not null) { Console.CursorVisible = false; var currentPosition = _rawui.CursorPosition; From 13e5c29ec9c343f2cccd7f953331eb6cb07c35e6 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 4 Feb 2021 13:21:17 -0800 Subject: [PATCH 20/21] address Ilya's feedback --- .../host/msh/PendingProgress.cs | 3 +-- .../host/msh/ProgressNode.cs | 2 +- .../host/msh/ProgressPane.cs | 2 +- .../FormatAndOutput/common/PSStyle.cs | 6 +++--- .../engine/ExperimentalFeature/ExperimentalFeature.cs | 3 ++- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs index 9e456fbc814..0c38f35960f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs @@ -517,10 +517,9 @@ internal override { node.Age = Math.Min(node.Age + 1, Int32.MaxValue - 1); -. node.Style = ProgressNode.IsMinimalProgressRenderingEnabled() + node.Style = ProgressNode.IsMinimalProgressRenderingEnabled() ? ProgressNode.RenderStyle.Ansi : node.Style = ProgressNode.RenderStyle.FullPlus; - `` return true; } diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 16c07f5748a..612842c68ad 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -353,7 +353,7 @@ private static void RenderFullDescription(string description, string indent, int internal static bool IsMinimalProgressRenderingEnabled() { - return ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View == ProgressView.Minimal; + return ExperimentalFeature.IsEnabled(ExperimentalFeature.PSAnsiProgressFeatureName) && PSStyle.Instance.Progress.View == ProgressView.Minimal; } /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 3806b61cc62..3919ac24621 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -119,7 +119,7 @@ class ProgressPane // create cleared region to clear progress bar later _savedRegion = tempProgressRegion; - if (ExperimentalFeature.IsEnabled("PSAnsiProgress") && PSStyle.Instance.Progress.View != ProgressView.Minimal) + if (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSAnsiProgressFeatureName) && PSStyle.Instance.Progress.View != ProgressView.Minimal) { for (int row = 0; row < rows; row++) { diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index 7fe9eceaeb3..f0b2cdca076 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -31,8 +31,8 @@ public enum ProgressView /// Render progress using minimal space. Minimal = 0, - /// Class rendering of progress. - Full = 1, + /// Classic rendering of progress. + Classic = 1, } #region PSStyle @@ -287,7 +287,7 @@ public class ProgressConfiguration public int MaxWidth { get; set; } = 120; /// - /// Gets or sets the style for progress bar. + /// Gets or sets the view for progress bar. /// public ProgressView View { get; set; } = ProgressView.Minimal; } diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs index 354c095cb33..07fb6ed59c2 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs @@ -21,6 +21,7 @@ public class ExperimentalFeature #region Const Members internal const string EngineSource = "PSEngine"; + internal const string PSAnsiProgressFeatureName = "PSAnsiProgress"; #endregion @@ -130,7 +131,7 @@ static ExperimentalFeature() name: "PSAnsiRendering", description: "Enable $PSStyle variable to control ANSI rendering of strings"), new ExperimentalFeature( - name: "PSAnsiProgress", + name: PSAnsiProgressFeatureName, description: "Enable lightweight progress bar that leverages ANSI codes for rendering"), }; EngineExperimentalFeatures = new ReadOnlyCollection(engineFeatures); From b05f249831e518c6d85a62a7cebbdeb95482e89d Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 4 Feb 2021 22:19:07 -0800 Subject: [PATCH 21/21] address Dongbo's feedback --- .../host/msh/ProgressNode.cs | 2 +- .../host/msh/ProgressPane.cs | 6 +----- .../DefaultFormatters/PowerShellCore_format_ps1xml.cs | 2 +- .../FormatAndOutput/common/PSStyle.cs | 8 ++++---- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs index 612842c68ad..ca2694bcabc 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressNode.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerShell ProgressNode : ProgressRecord { /// - /// Indicates the various layouts for rendering a particular node. Each style is progressively less terse. + /// Indicates the various layouts for rendering a particular node. /// internal enum diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs index 3919ac24621..873cfb483c7 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ProgressPane.cs @@ -101,11 +101,7 @@ class ProgressPane { // Scroll the console screen up by 'scrollRows' var bottomLocation = _location; - bottomLocation.Y = _rawui.BufferSize.Height; - if (Platform.IsWindows) - { - bottomLocation.Y--; - } + bottomLocation.Y = _rawui.BufferSize.Height - 1; _rawui.CursorPosition = bottomLocation; for (int i = 0; i < scrollRows; i++) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index 22e1076e49c..d9763164679 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -2051,10 +2051,10 @@ private static IEnumerable ViewsOf_System_Management_Autom .AddItemScriptBlock(@"""$($_.Formatting.Error)$($_.Formatting.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Error") .AddItemScriptBlock(@"""$($_.Formatting.Warning)$($_.Formatting.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Warning") .AddItemScriptBlock(@"""$($_.Formatting.Verbose)$($_.Formatting.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Verbose") + .AddItemScriptBlock(@"""$($_.Formatting.Debug)$($_.Formatting.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Debug") .AddItemScriptBlock(@"""$($_.Progress.Style)$($_.Progress.Style.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Progress.Style") .AddItemScriptBlock(@"""$($_.Progress.MaxWidth)""", label: "Progress.MaxWidth") .AddItemScriptBlock(@"""$($_.Progress.View)""", label: "Progress.View") - .AddItemScriptBlock(@"""$($_.Formatting.Debug)$($_.Formatting.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Debug") .AddItemScriptBlock(@"""$($_.Foreground.Black)$($_.Foreground.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Black") .AddItemScriptBlock(@"""$($_.Foreground.White)$($_.Foreground.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.White") .AddItemScriptBlock(@"""$($_.Foreground.DarkGray)$($_.Foreground.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.DarkGray") diff --git a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs index f0b2cdca076..aa00bdf9e18 100644 --- a/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs +++ b/src/System.Management.Automation/FormatAndOutput/common/PSStyle.cs @@ -44,7 +44,7 @@ public sealed class PSStyle /// /// Contains foreground colors. /// - public class ForegroundColor + public sealed class ForegroundColor { /// /// Gets the color black. @@ -159,7 +159,7 @@ public string FromRgb(int rgb) /// /// Contains background colors. /// - public class BackgroundColor + public sealed class BackgroundColor { /// /// Gets the color black. @@ -274,7 +274,7 @@ public string FromRgb(int rgb) /// /// Contains configuration for the progress bar visualization. /// - public class ProgressConfiguration + public sealed class ProgressConfiguration { /// /// Gets or sets the style for progress bar. @@ -295,7 +295,7 @@ public class ProgressConfiguration /// /// Contains formatting styles for steams and objects. /// - public class FormattingData + public sealed class FormattingData { /// /// Gets or sets the accent style for formatting.