Skip to content

Commit a736f02

Browse files
committed
This is DetailedView
1 parent 2fd3ffb commit a736f02

File tree

2 files changed

+64
-69
lines changed

2 files changed

+64
-69
lines changed

source/private/GetListRecursive.ps1

+59-57
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,38 @@ function GetListRecursive {
99
[int]$indent = 0,
1010
[int]$depth = 1
1111
)
12-
Write-Information "ENTER GetListRecursive END $($InputObject.GetType().FullName) $indent $depth" -Tags 'Trace', 'Enter', 'GetListRecursive'
13-
Write-Information (Get-PSCallStack) -Tags 'Trace', 'StackTrace', 'GetListRecursive'
1412
$output = [System.Text.StringBuilder]::new()
15-
$prefix = ' ' * $indent
13+
$padding = ' ' * $indent
1614

1715
$expandTypes = @(
1816
'Microsoft.Rest.HttpRequestMessageWrapper'
1917
'Microsoft.Rest.HttpResponseMessageWrapper'
2018
'System.Management.Automation.InvocationInfo'
2119
)
2220

23-
# The built-in DetailedView aligns all the ":" characters, so we need to find the longest property name
24-
$propLength = 0
25-
foreach ($prop in $InputObject.PSObject.Properties) {
26-
if ($null -ne $prop.Value -and $prop.Value -ne [string]::Empty -and $prop.Name.Length -gt $propLength) {
27-
$propLength = $prop.Name.Length
28-
}
29-
}
21+
# The built-in DetailedView aligns all the ":" characters, but it's awful
3022

3123
$addedProperty = $false
3224
foreach ($prop in $InputObject.PSObject.Properties) {
25+
# PowerShell creates an ErrorRecord property on Exceptions that points back to the parent ErrorRecord.
26+
# This is basically a circular reference that causes repeated informtion, so we're going to skip them
27+
if ($prop.Value -is [System.Management.Automation.ErrorRecord] -and $depth -ge 2) {
28+
continue
29+
}
3330
# don't show empty properties or our added property for $error[index]
3431
if ($null -ne $prop.Value -and $prop.Value -ne [string]::Empty -and $prop.Value.count -gt 0 -and $prop.Name -ne 'PSErrorIndex') {
3532
$addedProperty = $true
36-
$null = $output.Append($prefix)
33+
$null = $output.Append($padding)
3734
$null = $output.Append($accentColor)
3835
$null = $output.Append($prop.Name)
39-
$null = $output.Append(' ',($propLength - $prop.Name.Length))
40-
$null = $output.Append(' : ')
36+
$null = $output.Append(': ')
4137
$null = $output.Append($resetColor)
4238

43-
$newIndent = $indent + 2
39+
[int]$nextIndent = $indent + 2
40+
[int]$nextDepth = $depth + 1
41+
$nextPadding = ' ' * $nextIndent
4442

45-
# only show nested objects that are Exceptions, ErrorRecords, or types defined in $expandTypes and types not in $ignoreTypes
43+
# only show nested objects that are Exceptions, ErrorRecords, or types defined in $expandTypes
4644
if ($prop.Value -is [Exception] -or
4745
$prop.Value -is [System.Management.Automation.ErrorRecord] -or
4846
$expandTypes -contains $prop.TypeNameOfValue -or
@@ -51,16 +49,12 @@ function GetListRecursive {
5149
if ($depth -ge $maxDepth) {
5250
$null = $output.Append($ellipsis)
5351
} else {
52+
# For Exceptions, add a fake "Type" property
5453
if ($prop.Value -is [Exception]) {
55-
$null = $output.Append($newline)
56-
$null = $output.Append((
57-
GetListRecursive ([PSCustomObject]@{
58-
"Type" = $errorAccentColor + $prop.Value.GetType().FullName + $resetColor
59-
}) $newIndent ($depth + 1)
60-
))
54+
$null = $output.Append(( $accentColor + "[" + $prop.Value.GetType().FullName + "]" + $resetColor))
6155
}
6256
$null = $output.Append($newline)
63-
$null = $output.Append((GetListRecursive $prop.Value $newIndent ($depth + 1)))
57+
$null = $output.Append((GetListRecursive $prop.Value $nextIndent $nextDepth))
6458
}
6559
} elseif ($prop.Name -eq 'TargetSite' -and $prop.Value.GetType().Name -eq 'RuntimeMethodInfo') {
6660
# `TargetSite` has many members that are not useful visually, so we have a reduced view of the relevant members
@@ -75,28 +69,34 @@ function GetListRecursive {
7569
}
7670

7771
$null = $output.Append($newline)
78-
$null = $output.Append((GetListRecursive $targetSite $newIndent ($depth + 1)))
72+
$null = $output.Append((GetListRecursive $targetSite $nextIndent $nextDepth))
7973
}
8074
} elseif ($prop.Name -eq 'StackTrace') {
81-
# `StackTrace` is handled specifically because the lines are typically long but necessary so they are left justified without additional indentation
82-
# for a stacktrace which is usually quite wide with info, we left justify it
75+
# StackTrace is handled specifically because the lines are typically long but we can't trucate them, so we don't indent it any more
8376
$null = $output.Append($newline)
84-
$null = $output.Append($prop.Value)
77+
# $null = $output.Append($prop.Value)
78+
$Wrap = @{
79+
Width = $Host.UI.RawUI.BufferSize.Width - 2
80+
IndentPadding = ""
81+
HangingIndent = " "
82+
}
83+
$null = $output.Append(($prop.Value | WrapString @Wrap))
84+
} elseif ($prop.Name -eq 'HResult') {
85+
# `HResult` is handled specifically so we can format it in hex
86+
# $null = $output.Append($newline)
87+
$null = $output.Append("0x{0:x} ({0})" -f $prop.Value)
88+
} elseif ($prop.Name -eq 'PipelineIterationInfo') {
89+
# I literally have no idea what use this is
90+
$null = $output.Append($prop.Value -join ', ')
8591
} elseif ($prop.Value.GetType().Name.StartsWith('Dictionary') -or $prop.Value.GetType().Name -eq 'Hashtable') {
86-
# Dictionary and Hashtable we want to show as Key/Value pairs, we don't do the extra whitespace alignment here
87-
$isFirstElement = $true
92+
# Dictionary and Hashtable we want to show as Key/Value pairs
93+
$null = $output.Append($newline)
8894
foreach ($key in $prop.Value.Keys) {
89-
if ($isFirstElement) {
90-
$null = $output.Append($newline)
91-
}
92-
9395
if ($key -eq 'Authorization') {
94-
$null = $output.Append("${prefix} ${accentColor}${key}: ${resetColor}${ellipsis}${newline}")
96+
$null = $output.Append("${nextPadding}${accentColor}${key}: ${resetColor}${ellipsis}${newline}")
9597
} else {
96-
$null = $output.Append("${prefix} ${accentColor}${key}: ${resetColor}$($prop.Value[$key])${newline}")
98+
$null = $output.Append("${nextPadding}${accentColor}${key}: ${resetColor}$($prop.Value[$key])${newline}")
9799
}
98-
99-
$isFirstElement = $false
100100
}
101101
} elseif (!($prop.Value -is [System.String]) -and $null -ne $prop.Value.GetType().GetInterface('IEnumerable') -and $prop.Name -ne 'Data') {
102102
# if the object implements IEnumerable and not a string, we try to show each object
@@ -108,41 +108,43 @@ function GetListRecursive {
108108
$isFirstElement = $true
109109
foreach ($value in $prop.Value) {
110110
$null = $output.Append($newline)
111-
if (!$isFirstElement) {
112-
$null = $output.Append($newline)
111+
112+
if ($value -is [Type]) {
113+
# Just show the typename instead of it as an object
114+
$null = $output.Append("${nextPadding}[$($value.ToString())]")
115+
} elseif ($value -is [string] -or $value.GetType().IsPrimitive) {
116+
$null = $output.Append("${nextPadding}${value}")
117+
} else {
118+
if (!$isFirstElement) {
119+
$null = $output.Append($newline)
120+
}
121+
$null = $output.Append((GetListRecursive $value $nextIndent $nextDepth))
113122
}
114-
$null = $output.Append((GetListRecursive $value $newIndent ($depth + 1)))
115123
$isFirstElement = $false
116124
}
117125
}
126+
} elseif ($prop.Value -is [Type]) {
127+
# Just show the typename instead of it as an object
128+
$null = $output.Append("[$($prop.Value.ToString())]")
118129
} else {
119130
# Anything else, we convert to string.
120131
# ToString() can throw so we use LanguagePrimitives.TryConvertTo() to hide a convert error
121132
$value = $null
122133
if ([System.Management.Automation.LanguagePrimitives]::TryConvertTo($prop.Value, [string], [ref]$value) -and $null -ne $value) {
123134
$value = $value.Trim()
124-
if ($prop.Name -eq 'PositionMessage') {
135+
if ($InputObject -is [System.Management.Automation.InvocationInfo] -and $prop.Name -eq 'PositionMessage') {
136+
# Make the underline red
125137
$value = $value.Insert($value.IndexOf('~'), $errorColor)
126-
} elseif ($prop.Name -eq 'Message') {
138+
} elseif ( ($InputObject -is [System.Management.Automation.ErrorRecord] -or
139+
$InputObject -is [System.Exception]) -and $prop.Name -in 'Message', 'FullyQualifiedErrorId', 'CategoryInfo') {
127140
$value = $errorColor + $value
128141
}
129-
130-
$isFirstLine = $true
131-
if ($value.Contains($newline)) {
132-
# the 3 is to account for ' : '
133-
# $valueIndent = ' ' * ($prop.Name.Length + 2)
134-
$valueIndent = ' ' * ($propLength + 3)
135-
# need to trim any extra whitespace already in the text
136-
foreach ($line in $value.Split($newline)) {
137-
if (!$isFirstLine) {
138-
$null = $output.Append("${newline}${prefix}${valueIndent}")
139-
}
140-
$null = $output.Append($line.Trim())
141-
$isFirstLine = $false
142-
}
143-
} else {
144-
$null = $output.Append($value)
142+
$Wrap = @{
143+
Width = $Host.UI.RawUI.BufferSize.Width - 2
144+
IndentPadding = " " * ($nextIndent + $prop.Name.Length)
145145
}
146+
147+
$null = $output.Append(($value | WrapString @Wrap).TrimStart())
146148
}
147149
}
148150

+5-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
function ConvertTo-DetailedErrorView {
1+
filter ConvertTo-DetailedErrorView {
22
<#
33
.SYNOPSIS
44
Converts an ErrorRecord to a detailed error string
55
.DESCRIPTION
6-
The default PowerShell "DetailedView" ErrorView
7-
Copied from the PowerShellCore.format.ps1xml
6+
An "improved" version of the PowerShell "DetailedView" ErrorView
7+
Originally copied from the PowerShellCore.format.ps1xml
88
.LINK
99
https://github.com/PowerShell/PowerShell/blob/c444645b0941d73dc769f0bba6ab70d317bd51a9/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs#L903
1010
#>
@@ -19,15 +19,8 @@ function ConvertTo-DetailedErrorView {
1919
# The maximum depth to recurse into the object
2020
[int]$maxDepth = 10
2121
)
22-
23-
begin {
24-
Write-Information "ENTER ConvertTo-DetailedErrorView BEGIN " -Tags 'Trace', 'Enter', 'ConvertTo-DetailedErrorView'
25-
26-
Write-Information "EXIT ConvertTo-DetailedErrorView BEGIN" -Tags 'Trace', 'Enter', 'ConvertTo-DetailedErrorView'
27-
}
22+
begin { ResetColor }
2823
process {
29-
Write-Information "ENTER ConvertTo-DetailedErrorView PROCESS $($InputObject.GetType().FullName)" -Tags 'Trace', 'Enter', 'ConvertTo-DetailedErrorView'
30-
GetListRecursive $InputObject
31-
Write-Information "EXIT ConvertTo-DetailedErrorView PROCESS $($InputObject.GetType().FullName)" -Tags 'Trace', 'Enter', 'ConvertTo-DetailedErrorView'
24+
$newline + (GetListRecursive $InputObject) + $newline
3225
}
3326
}

0 commit comments

Comments
 (0)