Skip to content

Commit 99cc6a8

Browse files
committed
Update with views from 7
1 parent ec626d7 commit 99cc6a8

19 files changed

+1394
-249
lines changed

ErrorView.code-workspace

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"folders": [
3+
{
4+
"name": "ErrorView",
5+
"path": "."
6+
},
7+
{
8+
"path": "../../Tasks"
9+
}
10+
],
11+
"settings": {
12+
"powershell.cwd": "."
13+
}
14+
}

Reference/default.ps1

+335
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
<#
2+
if (@('NativeCommandErrorMessage','NativeCommandError') -notcontains $_.FullyQualifiedErrorId -and @('CategoryView','ConciseView','DetailedView') -notcontains $ErrorView)
3+
{
4+
$myinv = $_.InvocationInfo
5+
if ($myinv -and $myinv.MyCommand)
6+
{
7+
switch -regex ( $myinv.MyCommand.CommandType )
8+
{
9+
([System.Management.Automation.CommandTypes]::ExternalScript)
10+
{
11+
if ($myinv.MyCommand.Path)
12+
{
13+
$myinv.MyCommand.Path + ' : '
14+
}
15+
16+
break
17+
}
18+
19+
([System.Management.Automation.CommandTypes]::Script)
20+
{
21+
if ($myinv.MyCommand.ScriptBlock)
22+
{
23+
$myinv.MyCommand.ScriptBlock.ToString() + ' : '
24+
}
25+
26+
break
27+
}
28+
default
29+
{
30+
if ($myinv.InvocationName -match '^[&\.]?$')
31+
{
32+
if ($myinv.MyCommand.Name)
33+
{
34+
$myinv.MyCommand.Name + ' : '
35+
}
36+
}
37+
else
38+
{
39+
$myinv.InvocationName + ' : '
40+
}
41+
42+
break
43+
}
44+
}
45+
}
46+
elseif ($myinv -and $myinv.InvocationName)
47+
{
48+
$myinv.InvocationName + ' : '
49+
}
50+
}
51+
52+
53+
Set-StrictMode -Off
54+
$ErrorActionPreference = 'Stop'
55+
trap { 'Error found in error view definition: ' + $_.Exception.Message }
56+
$newline = [Environment]::Newline
57+
58+
$resetColor = ''
59+
$errorColor = ''
60+
$accentColor = ''
61+
62+
if ($Host.UI.SupportsVirtualTerminal -and ([string]::IsNullOrEmpty($env:__SuppressAnsiEscapeSequences))) {
63+
$resetColor = $PSStyle.Reset
64+
$errorColor = $PSStyle.Formatting.Error
65+
$accentColor = $PSStyle.Formatting.ErrorAccent
66+
}
67+
function Get-ConciseViewPositionMessage {
68+
69+
# returns a string cut to last whitespace
70+
function Get-TruncatedString($string, [int]$length) {
71+
72+
if ($string.Length -le $length) {
73+
return $string
74+
}
75+
76+
return ($string.Substring(0,$length) -split '\s',-2)[0]
77+
}
78+
79+
$posmsg = ''
80+
$headerWhitespace = ''
81+
$offsetWhitespace = ''
82+
$message = ''
83+
$prefix = ''
84+
85+
# The checks here determine if we show line detailed error information:
86+
# - check if `ParserError` and comes from PowerShell which eventually results in a ParseException, but during this execution it's an ErrorRecord
87+
# - check if invocation is a script or multiple lines in the console
88+
# - check that it's not a script module as expectation is that users don't want to see the line of error within a module
89+
if ((($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception -is 'System.Management.Automation.ParentContainsErrorRecordException') -or $myinv.ScriptName -or $myinv.ScriptLineNumber -gt 1) -and $myinv.ScriptName -notmatch '\.psm1$') {
90+
$useTargetObject = $false
91+
92+
# Handle case where there is a TargetObject and we can show the error at the target rather than the script source
93+
if ($_.TargetObject.Line -and $_.TargetObject.LineText) {
94+
$posmsg = "${resetcolor}$($_.TargetObject.File)${newline}"
95+
$useTargetObject = $true
96+
}
97+
elseif ($myinv.ScriptName) {
98+
if ($env:TERM_PROGRAM -eq 'vscode') {
99+
# If we are running in vscode, we know the file:line:col links are clickable so we use this format
100+
$posmsg = "${resetcolor}$($myinv.ScriptName):$($myinv.ScriptLineNumber):$($myinv.OffsetInLine)${newline}"
101+
}
102+
else {
103+
$posmsg = "${resetcolor}$($myinv.ScriptName):$($myinv.ScriptLineNumber)${newline}"
104+
}
105+
}
106+
else {
107+
$posmsg = "${newline}"
108+
}
109+
110+
if ($useTargetObject) {
111+
$scriptLineNumber = $_.TargetObject.Line
112+
$scriptLineNumberLength = $_.TargetObject.Line.ToString().Length
113+
}
114+
else {
115+
$scriptLineNumber = $myinv.ScriptLineNumber
116+
$scriptLineNumberLength = $myinv.ScriptLineNumber.ToString().Length
117+
}
118+
119+
if ($scriptLineNumberLength -gt 4) {
120+
$headerWhitespace = ' ' * ($scriptLineNumberLength - 4)
121+
}
122+
123+
$lineWhitespace = ''
124+
if ($scriptLineNumberLength -lt 4) {
125+
$lineWhitespace = ' ' * (4 - $scriptLineNumberLength)
126+
}
127+
128+
$verticalBar = '|'
129+
$posmsg += "${accentColor}${headerWhitespace}Line ${verticalBar}${newline}"
130+
131+
$highlightLine = ''
132+
if ($useTargetObject) {
133+
$line = $_.TargetObject.LineText.Trim()
134+
$offsetLength = 0
135+
$offsetInLine = 0
136+
}
137+
else {
138+
$positionMessage = $myinv.PositionMessage.Split($newline)
139+
$line = $positionMessage[1].Substring(1) # skip the '+' at the start
140+
$highlightLine = $positionMessage[$positionMessage.Count - 1].Substring(1)
141+
$offsetLength = $highlightLine.Trim().Length
142+
$offsetInLine = $highlightLine.IndexOf('~')
143+
}
144+
145+
if (-not $line.EndsWith($newline)) {
146+
$line += $newline
147+
}
148+
149+
# don't color the whole line
150+
if ($offsetLength -lt $line.Length - 1) {
151+
$line = $line.Insert($offsetInLine + $offsetLength, $resetColor).Insert($offsetInLine, $accentColor)
152+
}
153+
154+
$posmsg += "${accentColor}${lineWhitespace}${ScriptLineNumber} ${verticalBar} ${resetcolor}${line}"
155+
$offsetWhitespace = ' ' * $offsetInLine
156+
$prefix = "${accentColor}${headerWhitespace} ${verticalBar} ${errorColor}"
157+
if ($highlightLine -ne '') {
158+
$posMsg += "${prefix}${highlightLine}${newline}"
159+
}
160+
$message = "${prefix}"
161+
}
162+
163+
if (! $err.ErrorDetails -or ! $err.ErrorDetails.Message) {
164+
if ($err.CategoryInfo.Category -eq 'ParserError' -and $err.Exception.Message.Contains("~$newline")) {
165+
# need to parse out the relevant part of the pre-rendered positionmessage
166+
$message += $err.Exception.Message.split("~$newline")[1].split("${newline}${newline}")[0]
167+
}
168+
elseif ($err.Exception) {
169+
$message += $err.Exception.Message
170+
}
171+
elseif ($err.Message) {
172+
$message += $err.Message
173+
}
174+
else {
175+
$message += $err.ToString()
176+
}
177+
}
178+
else {
179+
$message += $err.ErrorDetails.Message
180+
}
181+
182+
# if rendering line information, break up the message if it's wider than the console
183+
if ($myinv -and $myinv.ScriptName -or $err.CategoryInfo.Category -eq 'ParserError') {
184+
$prefixLength = "$([char]27)]8;;{0}`a{1}$([char]27)]8;;`a" -f $pwd, $pwd::new($prefix).ContentLength
185+
$prefixVtLength = $prefix.Length - $prefixLength
186+
187+
# replace newlines in message so it lines up correct
188+
$message = $message.Replace($newline, ' ').Replace("`n", ' ').Replace("`t", ' ')
189+
190+
$windowWidth = 120
191+
if ($Host.UI.RawUI -ne $null) {
192+
$windowWidth = $Host.UI.RawUI.WindowSize.Width
193+
}
194+
195+
if ($windowWidth -gt 0 -and ($message.Length - $prefixVTLength) -gt $windowWidth) {
196+
$sb = [Text.StringBuilder]::new()
197+
$substring = Get-TruncatedString -string $message -length ($windowWidth + $prefixVTLength)
198+
$null = $sb.Append($substring)
199+
$remainingMessage = $message.Substring($substring.Length).Trim()
200+
$null = $sb.Append($newline)
201+
while (($remainingMessage.Length + $prefixLength) -gt $windowWidth) {
202+
$subMessage = $prefix + $remainingMessage
203+
$substring = Get-TruncatedString -string $subMessage -length ($windowWidth + $prefixVtLength)
204+
205+
if ($substring.Length - $prefix.Length -gt 0)
206+
{
207+
$null = $sb.Append($substring)
208+
$null = $sb.Append($newline)
209+
$remainingMessage = $remainingMessage.Substring($substring.Length - $prefix.Length).Trim()
210+
}
211+
else
212+
{
213+
break
214+
}
215+
}
216+
$null = $sb.Append($prefix + $remainingMessage.Trim())
217+
$message = $sb.ToString()
218+
}
219+
220+
$message += $newline
221+
}
222+
223+
$posmsg += "${errorColor}" + $message
224+
225+
$reason = 'Error'
226+
if ($err.Exception -and $err.Exception.WasThrownFromThrowStatement) {
227+
$reason = 'Exception'
228+
}
229+
# MyCommand can be the script block, so we don't want to show that so check if it's an actual command
230+
elseif ($myinv.MyCommand -and $myinv.MyCommand.Name -and (Get-Command -Name $myinv.MyCommand -ErrorAction Ignore))
231+
{
232+
$reason = $myinv.MyCommand
233+
}
234+
# If it's a scriptblock, better to show the command in the scriptblock that had the error
235+
elseif ($_.CategoryInfo.Activity) {
236+
$reason = $_.CategoryInfo.Activity
237+
}
238+
elseif ($myinv.MyCommand) {
239+
$reason = $myinv.MyCommand
240+
}
241+
elseif ($myinv.InvocationName) {
242+
$reason = $myinv.InvocationName
243+
}
244+
elseif ($err.CategoryInfo.Category) {
245+
$reason = $err.CategoryInfo.Category
246+
}
247+
elseif ($err.CategoryInfo.Reason) {
248+
$reason = $err.CategoryInfo.Reason
249+
}
250+
251+
$errorMsg = 'Error'
252+
253+
"${errorColor}${reason}: ${posmsg}${resetcolor}"
254+
}
255+
256+
$myinv = $_.InvocationInfo
257+
$err = $_
258+
if (!$myinv -and $_.ErrorRecord -and $_.ErrorRecord.InvocationInfo) {
259+
$err = $_.ErrorRecord
260+
$myinv = $err.InvocationInfo
261+
}
262+
263+
if ($err.FullyQualifiedErrorId -eq 'NativeCommandErrorMessage' -or $err.FullyQualifiedErrorId -eq 'NativeCommandError') {
264+
return "${errorColor}$($err.Exception.Message)${resetcolor}"
265+
}
266+
267+
$myinv = $err.InvocationInfo
268+
if ($ErrorView -eq 'DetailedView') {
269+
$message = Get-Error
270+
return "${errorColor}${message}${resetcolor}"
271+
}
272+
273+
if ($ErrorView -eq 'CategoryView') {
274+
$message = $err.CategoryInfo.GetMessage()
275+
return "${errorColor}${message}${resetcolor}"
276+
}
277+
278+
$posmsg = ''
279+
if ($ErrorView -eq 'ConciseView') {
280+
$posmsg = Get-ConciseViewPositionMessage
281+
}
282+
elseif ($myinv -and ($myinv.MyCommand -or ($err.CategoryInfo.Category -ne 'ParserError'))) {
283+
$posmsg = $myinv.PositionMessage
284+
}
285+
286+
if ($posmsg -ne '') {
287+
$posmsg = $newline + $posmsg
288+
}
289+
290+
if ($err.PSMessageDetails) {
291+
$posmsg = ' : ' + $err.PSMessageDetails + $posmsg
292+
}
293+
294+
if ($ErrorView -eq 'ConciseView') {
295+
if ($err.PSMessageDetails) {
296+
$posmsg = "${errorColor}${posmsg}"
297+
}
298+
return $posmsg
299+
}
300+
301+
$indent = 4
302+
303+
$errorCategoryMsg = $err.ErrorCategory_Message
304+
305+
if ($null -ne $errorCategoryMsg)
306+
{
307+
$indentString = '+ CategoryInfo : ' + $err.ErrorCategory_Message
308+
}
309+
else
310+
{
311+
$indentString = '+ CategoryInfo : ' + $err.CategoryInfo
312+
}
313+
314+
$posmsg += $newline + $indentString
315+
316+
$indentString = "+ FullyQualifiedErrorId : " + $err.FullyQualifiedErrorId
317+
$posmsg += $newline + $indentString
318+
319+
$originInfo = $err.OriginInfo
320+
321+
if (($null -ne $originInfo) -and ($null -ne $originInfo.PSComputerName))
322+
{
323+
$indentString = "+ PSComputerName : " + $originInfo.PSComputerName
324+
$posmsg += $newline + $indentString
325+
}
326+
327+
$finalMsg = if ($err.ErrorDetails.Message) {
328+
$err.ErrorDetails.Message + $posmsg
329+
} else {
330+
$err.Exception.Message + $posmsg
331+
}
332+
333+
"${errorColor}${finalMsg}${resetcolor}"
334+
335+
#>

0 commit comments

Comments
 (0)