Last active
May 5, 2024 11:12
-
-
Save trackd/c0d18512a56c0ba3c0b8e588d997f207 to your computer and use it in GitHub Desktop.
something
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Update-TypeData -TypeName '_RegexAnsi' -MemberType ScriptMethod -MemberName ToString -Force -Value { | |
return ($this.Value ? $this.value : $this.Text) | |
} | |
Update-TypeData -TypeName 'System.Management.Automation.Internal.StringDecorated' -MemberType ScriptMethod -MemberName ToString -Force -Value { | |
return $this.IsDecorated | |
} | |
function Get-AnsiEscape { | |
<# | |
.DESCRIPTION | |
Get-AnsiEscape can be used to strip, escape, or regex VT codes from a string. | |
.PARAMETER All | |
This parameter will run all the filters and return the original, stripped, escaped, and regexed strings. | |
Alias: Get-VT | |
.PARAMETER StripAnsi | |
This parameter will strip VT codes from the string. | |
returns: a clean string | |
alias: StripAnsi | |
.PARAMETER EscapeAnsi | |
This parameter will escape VT codes from the string. | |
returns: a string with VT codes escaped | |
alias: EscapeAnsi | |
.PARAMETER RegexAnsi | |
This parameter will regex VT codes from the string. | |
returns: a PSCustomObject with Text and depending on the input Value, and AltWord properties. | |
alias: RegexAnsi | |
.PARAMETER IsDecorated | |
This parameter will determine if the string is decorated with VT codes. | |
returns: a boolean | |
alias: IsDecorated | |
#> | |
[Alias('StripAnsi', 'EscapeAnsi', 'RegexAnsi', 'IsDecorated', 'Get-VT')] | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory, ValueFromPipeline)] | |
[AllowNull()] | |
[AllowEmptyString()] | |
[String] $InputObject, | |
[Switch] $StripAnsi, | |
[Switch] $EscapeAnsi, | |
[Switch] $RegexAnsi, | |
[Switch] $IsDecorated, | |
[Switch] $All | |
) | |
begin { | |
Write-Verbose "Command: $($MyInvocation.MyCommand.Name) Alias: $($MyInvocation.InvocationName) Param: $($PSBoundParameters.GetEnumerator())" | |
$e = [char]27 # `e, escape | |
$a = [char]7 # `a, bell, alert | |
$r = "$e[0m" # reset | |
filter _EscapeAnsi { | |
$_.EnumerateRunes() | ForEach-Object { | |
if ($_.Value -lt 32) { | |
[Text.Rune]::new($_.Value + 9216) | |
} | |
else { | |
$_ | |
} | |
} | Join-String | |
} | |
filter _StripAnsi { | |
<# clean string, but gives link text instead of url #> | |
return [System.Management.Automation.Host.PSHostUserInterface]::GetOutputString($_, $false) | |
} | |
filter _IsDecorated { | |
<# built-in method to determine if VT codes are present and "real" string length. #> | |
[System.Management.Automation.Internal.StringDecorated]::new($_) | |
} | |
filter _RegexAnsi { | |
<# this should handle ANSI colors and Links/OSC #> | |
$Regex = @{ | |
# VT Decoration cleanup | |
Decoration = "$e\[[0-?]*[ -/]*[@-~]" | |
# VT Links | |
Link = "(.*?)?$e]8;;(?<url>.*?)$e\\(.*?)$e]8;;$e\\(.*)?" | |
# osc is a bit untested.. mostly focused on links. | |
OSC = "(.*?)?$e]\d;(?<OSC>.*?)$e\\(.*?)$e]\d;$e\\(.*)?" | |
# terminal vt codes for terminal prompt markings | |
VT = "(.*?)?$e](?<VT>\d*;.*?)[$a|$e](.*)?" | |
} | |
$out = [ordered]@{ | |
PSTypeName = '_RegexAnsi' | |
Text = $_ -replace $regex.Decoration | |
} | |
if ($_ -ne $out.Text) { | |
$out.Type = @('Decoration') | |
} | |
if ($out.Text -match $Regex.Link) { | |
# links | |
$out.Text = ($Matches[1..3] -join '') -replace "$e|$a" | |
$out.Value = [uri]$Matches['url'] | |
$out.AltWord = $Matches[2] | |
$out.Type = $out.Type + 'Link' | |
} | |
elseif ($out.Text -match $Regex.VT) { | |
$out.Text = $out.Text -replace "$e|$a", { [text.rune]([int][char]$_[0].Value + 9216) } | |
$out.Value = $matches['VT'] | |
$out.Type = $out.Type + 'VT' | |
} | |
elseif ($out.Text -match $regex.OSC) { | |
$out.Text = $out.Text -replace $e, [char]9243 | |
$out.Value = $matches['OSC'] | |
$out.Type = $out.Type + 'OSC' | |
} | |
[PSCustomObject]$out | |
} | |
} | |
process { | |
if ([String]::IsNullOrEmpty($InputObject)) { | |
return | |
} | |
if (-Not $All) { | |
switch ($PSBoundParameters.Keys) { | |
# if a parameter is specified, order is not guaranteed | |
'StripAnsi' { return $InputObject | _StripAnsi } | |
'EscapeAnsi' { return $InputObject | _EscapeAnsi } | |
'RegexAnsi' { return $InputObject | _RegexAnsi } | |
'IsDecorated' { return $InputObject | _IsDecorated } | |
} | |
switch ($MyInvocation.InvocationName) { | |
# if an alias is used | |
'StripAnsi' { return $InputObject | _StripAnsi } | |
'EscapeAnsi' { return $InputObject | _EscapeAnsi } | |
'RegexAnsi' { return $InputObject | _RegexAnsi } | |
'IsDecorated' { return $InputObject | _IsDecorated } | |
} | |
} | |
$ht = [ordered]@{ | |
Original = $InputObject | |
Text = $InputObject | _StripAnsi | |
Escaped = $InputObject | _EscapeAnsi | |
IsDecorated = $InputObject | _IsDecorated | |
} | |
if ($InputObject -match "$e\]" -or $All) { | |
if (($test = $InputObject | _RegexAnsi).Value) { | |
$ht.Value = $test | |
# just add reset incase its not there. | |
$ht.Original = $ht.Original + $r | |
} | |
} | |
[PSCustomObject]$ht | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment