Skip to content

Instantly share code, notes, and snippets.

@trackd
Last active May 5, 2024 11:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trackd/c0d18512a56c0ba3c0b8e588d997f207 to your computer and use it in GitHub Desktop.
Save trackd/c0d18512a56c0ba3c0b8e588d997f207 to your computer and use it in GitHub Desktop.
something
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