6
6
using System . Management . Automation ;
7
7
using System . Management . Automation . Host ;
8
8
using System . Management . Automation . Internal ;
9
+ using System . Text ;
10
+
11
+ using Microsoft . PowerShell . Commands . Internal . Format ;
9
12
10
13
using Dbg = System . Management . Automation . Diagnostics ;
11
14
@@ -20,7 +23,7 @@ namespace Microsoft.PowerShell
20
23
ProgressNode : ProgressRecord
21
24
{
22
25
/// <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.
24
27
/// </summary>
25
28
internal
26
29
enum
@@ -40,6 +43,11 @@ namespace Microsoft.PowerShell
40
43
/// The node will be displayed the same as Full, plus, the whole StatusDescription and CurrentOperation will be displayed (in multiple lines if needed).
41
44
/// </summary>
42
45
FullPlus = 4 ,
46
+
47
+ /// <summary>
48
+ /// The node will be displayed using ANSI escape sequences.
49
+ /// </summary>
50
+ Ansi = 5 ,
43
51
}
44
52
45
53
/// <summary>
@@ -56,7 +64,11 @@ namespace Microsoft.PowerShell
56
64
this . PercentComplete = Math . Min ( record . PercentComplete , 100 ) ;
57
65
this . SecondsRemaining = record . SecondsRemaining ;
58
66
this . RecordType = record . RecordType ;
59
- this . Style = RenderStyle . FullPlus ;
67
+
68
+ this . Style = IsMinimalProgressRenderingEnabled ( )
69
+ ? RenderStyle . Ansi
70
+ : this . Style = RenderStyle . FullPlus ;
71
+
60
72
this . SourceId = sourceId ;
61
73
}
62
74
@@ -98,6 +110,9 @@ namespace Microsoft.PowerShell
98
110
case RenderStyle . Minimal :
99
111
RenderMinimal ( strCollection , indentation , maxWidth , rawUI ) ;
100
112
break ;
113
+ case RenderStyle . Ansi :
114
+ RenderAnsi ( strCollection , indentation , maxWidth ) ;
115
+ break ;
101
116
case RenderStyle . Invisible :
102
117
// do nothing
103
118
break ;
@@ -336,6 +351,88 @@ private static void RenderFullDescription(string description, string indent, int
336
351
maxWidth ) ) ;
337
352
}
338
353
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
+
339
436
/// <summary>
340
437
/// The nodes that have this node as their parent.
341
438
/// </summary>
@@ -396,6 +493,9 @@ internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth)
396
493
case RenderStyle . Invisible :
397
494
return 0 ;
398
495
496
+ case RenderStyle . Ansi :
497
+ return 1 ;
498
+
399
499
default :
400
500
Dbg . Assert ( false , "Unknown RenderStyle value" ) ;
401
501
break ;
0 commit comments