functions/Write-AnsiProgress.ps1
|
function Write-ANSIProgress { [cmdletbinding()] [alias('wap')] [OutputType('None', 'String')] param ( [Parameter( Position = 0, Mandatory, ValueFromPipeline, HelpMessage = 'Enter a percentage in decimal value like .25' )] [ValidateScript({ $_ -gt 0 -and $_ -le 1 })] [double]$PercentComplete, [Parameter(HelpMessage = 'Specify an ANSI escape sequence or a PSStyle setting for the progress bar color.')] [string]$ProgressColor = "$([char]27)[38;5;51m", [Parameter(HelpMessage = 'Specify what shape to use for the progress bar.')] [ValidateSet('Box', 'Block', 'Circle')] [string]$BarSymbol = 'Box', [Parameter(HelpMessage = 'Specify the cursor position')] [System.Management.Automation.Host.Coordinates]$Position = $host.UI.RawUI.CursorPosition, [Parameter(HelpMessage = 'Write to the host not the pipeline')] [switch]$ToHost ) begin { #tags are used for categorizing the command #cmdTags = ansi,scripting Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)" Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Running under PowerShell version $($PSVersionTable.PSVersion)" #Validate the progress color. The normal parameter validation techniques don't like the regex pattern if ( -not [regex]::IsMatch($ProgressColor, "$([char]27)\[\d+[\d;]+m")) { throw 'You entered an invalid ANSI escape sequence' } #the closing ANSI sequence $end = "$([char]27)[0m" #a length of 50 is the max or 100% $max = 50 switch ($BarSymbol) { 'box' { $block = [char]9632 } 'block' { $block = [char]9608 } 'circle' { $block = [char]9679 } } #these values will be used to set the progress bar position $x = $position.x #modified July 12, 2024 to not add an extra line $y = $position.y #+ 1 #may need to insert a line in case we are at the bottom of a console or terminal screen if ($env:WT_SESSION -and ($position.y + 1 -ge $host.UI.RawUI.BufferSize.Height)) { #Write-Output "`n" Write-Host "`n" } } #begin process { if ($host.Name -match 'PowerShell ISE') { Write-Warning 'This command will not work in the PowerShell ISE.' #bail out return } Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] $PercentComplete %" [int]$len = $max * $PercentComplete #get current cursor position if in Windows Terminal if ($env:WT_SESSION -and ($position.y + 1 -ge $host.UI.RawUI.BufferSize.Height)) { $y = $host.UI.RawUI.CursorPosition.Y - 1 } [System.Console]::SetCursorPosition($x, $y) #align and pad the percentage value $pct = "$($percentComplete*100)%".PadLeft(4) #Modified June 27, 2024 to write to the host so progress isn't part of any command output if ($ToHost) { Write-Host "$pct $ProgressColor$($($Block.ToString())*$len)$End" } else { Write-Output "$pct $ProgressColor$($($Block.ToString())*$len)$End" } } #process end { Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" } #end } #close Write-ANSIProgress #EOF |