Use $PSStyle.Formatting.FormatAccent for Format-List and $PSStyle.Formatting.TableHeader for Format-Table output (#14406)

This commit is contained in:
Steve Lee 2021-07-19 21:02:52 -07:00 committed by GitHub
parent 31a4528302
commit b5efe7bc39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 273 additions and 15 deletions

View file

@ -2067,6 +2067,7 @@ namespace System.Management.Automation.Runspaces
.AddItemScriptBlock(@"""$($_.Strikethrough)$($_.Strikethrough.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Strikethrough")
.AddItemProperty(@"OutputRendering")
.AddItemScriptBlock(@"""$($_.Formatting.FormatAccent)$($_.Formatting.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.FormatAccent")
.AddItemScriptBlock(@"""$($_.Formatting.TableHeaader)$($_.Formatting.TableHeaader.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.TableHeaader")
.AddItemScriptBlock(@"""$($_.Formatting.ErrorAccent)$($_.Formatting.ErrorAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.ErrorAccent")
.AddItemScriptBlock(@"""$($_.Formatting.Error)$($_.Formatting.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Error")
.AddItemScriptBlock(@"""$($_.Formatting.Warning)$($_.Formatting.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Warning")
@ -2122,6 +2123,7 @@ namespace System.Management.Automation.Runspaces
ListControl.Create()
.StartEntry()
.AddItemScriptBlock(@"""$($_.FormatAccent)$($_.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FormatAccent")
.AddItemScriptBlock(@"""$($_.TableHeader)$($_.TableHeader.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "TableHeader")
.AddItemScriptBlock(@"""$($_.ErrorAccent)$($_.ErrorAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "ErrorAccent")
.AddItemScriptBlock(@"""$($_.Error)$($_.Error.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Error")
.AddItemScriptBlock(@"""$($_.Warning)$($_.Warning.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Warning")

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Internal;
namespace Microsoft.PowerShell.Commands.Internal.Format
@ -59,6 +60,10 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
// check if we have to truncate the labels
int maxAllowableLabelLength = screenColumnWidth - Separator.Length - MinFieldWidth;
if (InternalTestHooks.ForceFormatListFixedLabelWidth)
{
maxAllowableLabelLength = 10;
}
// find out the max display length (cell count) of the property names
_propertyLabelsDisplayLength = 0; // reset max
@ -217,11 +222,25 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
{
if (k == 0)
{
lo.WriteLine(prependString + sc[k]);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
{
lo.WriteLine(PSStyle.Instance.Formatting.FormatAccent + prependString + PSStyle.Instance.Reset + sc[k]);
}
else
{
lo.WriteLine(prependString + sc[k]);
}
}
else
{
lo.WriteLine(padding + sc[k]);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
{
lo.WriteLine(padding + PSStyle.Instance.Formatting.FormatAccent + PSStyle.Instance.Reset + sc[k]);
}
else
{
lo.WriteLine(padding + sc[k]);
}
}
}
}

View file

@ -309,6 +309,11 @@ namespace System.Management.Automation
/// </summary>
public string FormatAccent { get; set; } = "\x1b[32;1m";
/// <summary>
/// Gets or sets the style for table headers.
/// </summary>
public string TableHeader { get; set; } = "\x1b[32;1m";
/// <summary>
/// Gets or sets the accent style for errors.
/// </summary>

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Management.Automation;
using System.Management.Automation.Internal;
using System.Text;
@ -155,7 +156,14 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
{
foreach (string line in _header)
{
lo.WriteLine(line);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
{
lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset);
}
else
{
lo.WriteLine(line);
}
}
return _header.Count;
@ -164,7 +172,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
_header = new List<string>();
// generate the row with the header labels
GenerateRow(values, lo, true, null, lo.DisplayCells, _header);
GenerateRow(values, lo, true, null, lo.DisplayCells, _header, isHeader: true);
// generate an array of "--" as header markers below
// the column header labels
@ -191,14 +199,16 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
breakLine[k] = StringUtil.DashPadding(count);
}
GenerateRow(breakLine, lo, false, null, lo.DisplayCells, _header);
GenerateRow(breakLine, lo, false, null, lo.DisplayCells, _header, isHeader: true);
return _header.Count;
}
internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOnlySpan<int> alignment, DisplayCells dc, List<string> generatedRows)
internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOnlySpan<int> alignment, DisplayCells dc, List<string> generatedRows, bool isHeader = false)
{
if (_disabled)
{
return;
}
// build the current row alignment settings
int cols = _si.columnInfo.Length;
@ -216,9 +226,13 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
for (int i = 0; i < currentAlignment.Length; i++)
{
if (alignment[i] == TextAlignment.Undefined)
{
currentAlignment[i] = _si.columnInfo[i].alignment;
}
else
{
currentAlignment[i] = alignment[i];
}
}
}
@ -227,14 +241,28 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
foreach (string line in GenerateTableRow(values, currentAlignment, lo.DisplayCells))
{
generatedRows?.Add(line);
lo.WriteLine(line);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering") && isHeader)
{
lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset);
}
else
{
lo.WriteLine(line);
}
}
}
else
{
string line = GenerateRow(values, currentAlignment, dc);
generatedRows?.Add(line);
lo.WriteLine(line);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering") && isHeader)
{
lo.WriteLine(PSStyle.Instance.Formatting.TableHeader + line + PSStyle.Instance.Reset);
}
else
{
lo.WriteLine(line);
}
}
}
@ -441,7 +469,15 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
if (values[k].Contains(ESC))
{
// Reset the console output if the content of this column contains ESC
sb.Append(ResetConsoleVt100Code);
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
{
// Remove definition of `ResetConsoleVt10Code` when PSAnsiRendering is not experimental
sb.Append(PSStyle.Instance.Reset);
}
else
{
sb.Append(ResetConsoleVt100Code);
}
}
}

View file

@ -1843,6 +1843,7 @@ namespace System.Management.Automation
{
Reset,
FormatAccent,
TableHeader,
ErrorAccent,
Error,
Warning,
@ -1870,6 +1871,8 @@ namespace System.Management.Automation
return psstyle.Reset;
case FormatStyle.FormatAccent:
return psstyle.Formatting.FormatAccent;
case FormatStyle.TableHeader:
return psstyle.Formatting.TableHeader;
case FormatStyle.ErrorAccent:
return psstyle.Formatting.ErrorAccent;
case FormatStyle.Error:
@ -2073,6 +2076,7 @@ namespace System.Management.Automation.Internal
internal static bool ForcePromptForChoiceDefaultOption;
internal static bool BypassOutputRedirectionCheck;
internal static bool NoPromptForPassword;
internal static bool ForceFormatListFixedLabelWidth;
// Stop/Restart/Rename Computer tests
internal static bool TestStopComputer;

View file

@ -275,7 +275,7 @@ export $envVarName='$guid'
}
It "Doesn't run the login profile when -Login not used" {
$result = & $powershell -Command "`$env:$envVarName"
$result = & $powershell -noprofile -Command "`$env:$envVarName"
$result | Should -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
@ -374,7 +374,20 @@ export $envVarName='$guid'
}
Context "Pipe to/from powershell" {
$p = [PSCustomObject]@{X=10;Y=20}
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
$p = [PSCustomObject]@{X=10;Y=20}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
It "xml input" {
$p | & $powershell -noprofile { $input | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should -Be 30
@ -651,7 +664,7 @@ namespace StackTest {
}
It "powershell starts if PATH is not set" -Skip:($IsWindows) {
bash -c "unset PATH;$powershell -c '1+1'" | Should -BeExactly 2
bash -c "unset PATH;$powershell -nop -c '1+1'" | Should -BeExactly 2
}
}

View file

@ -682,6 +682,19 @@ Describe 'ScriptScopeAccessFromClassMethod' -Tags "CI" {
}
Describe 'Hidden Members Test ' -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
class C1
{
[int]$visibleX

View file

@ -26,7 +26,20 @@ Describe "Format-Custom" -Tags "CI" {
}
Describe "Format-Custom DRT basic functionality" -Tags "CI" {
Add-Type -TypeDefinition @"
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
Add-Type -TypeDefinition @"
public abstract class NamedItem
{
public string name;
@ -310,6 +323,11 @@ class MyLeaf2
Describe "Format-Custom with expression based EntrySelectedBy in a CustomControl" -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
$formatFilePath = Join-Path $TestDrive 'UpdateFormatDataTests.format.ps1xml'
$xmlContent = @'
<?xml version="1.0" encoding="UTF-8" ?>
@ -389,6 +407,10 @@ Describe "Format-Custom with expression based EntrySelectedBy in a CustomControl
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
$rs.Close()
$ps.Dispose()
}

View file

@ -1,7 +1,21 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe "Format-List" -Tags "CI" {
$nl = [Environment]::NewLine
BeforeAll {
$nl = [Environment]::NewLine
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
BeforeEach {
$in = New-Object PSObject
Add-Member -InputObject $in -MemberType NoteProperty -Name testName -Value testValue
@ -70,6 +84,19 @@ Describe "Format-List" -Tags "CI" {
}
Describe "Format-List DRT basic functionality" -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
It "Format-List with array should work" {
$al = (0..255)
$info = @{}
@ -183,3 +210,22 @@ dbda : KM
$actual | Should -BeExactly $expected
}
}
Describe 'Format-List color tests' {
BeforeAll {
$PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRendering')))
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForceFormatListFixedLabelWidth', $true)
}
AfterAll {
$PSDefaultParameterValues.Remove('It:Skip')
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('ForceFormatListFixedLabelWidth', $false)
}
It 'Property names should use FormatAccent' {
$out = ([pscustomobject]@{Short=1;LongLabelName=2} | fl | out-string).Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
$out.Count | Should -Be 2
$out[0] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)Short : $($PSStyle.Reset)1" -Because ($out[0] | Format-Hex)
$out[1] | Should -BeExactly "$($PSStyle.Formatting.FormatAccent)LongLabelN : $($PSStyle.Reset)2"
}
}

View file

@ -1,6 +1,19 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe "Format-Table" -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
It "Should call format table on piped input without error" {
{ Get-Date | Format-Table } | Should -Not -Throw
}
@ -833,3 +846,21 @@ A Name B
($actual.Replace("`r`n", "`n")) | Should -BeExactly ($expected.Replace("`r`n", "`n"))
}
}
Describe 'Table color tests' {
BeforeAll {
$PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRendering')))
}
AfterAll {
$PSDefaultParameterValues.Remove('It:Skip')
}
It 'Table header should use FormatAccent' {
([pscustomobject]@{foo = 1} | Format-Table | Out-String).Trim() | Should -BeExactly @"
$($PSStyle.Formatting.FormatAccent)foo$($PSStyle.Reset)
$($PSStyle.Formatting.FormatAccent)---$($PSStyle.Reset)
1
"@
}
}

View file

@ -21,11 +21,22 @@ Describe "Out-File DRT Unit Tests" -Tags "CI" {
Describe "Out-File" -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
$expectedContent = "some test text"
$inObject = New-Object psobject -Property @{text=$expectedContent}
$testfile = Join-Path -Path $TestDrive -ChildPath outfileTest.txt
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
AfterEach {
Remove-Item -Path $testfile -Force
}

View file

@ -146,6 +146,23 @@ Describe "Set-Variable DRT Unit Tests" -Tags "CI" {
}
Describe "Set-Variable" -Tags "CI" {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
$expectedContent = "some test text"
$inObject = New-Object psobject -Property @{text=$expectedContent}
$testfile = Join-Path -Path $TestDrive -ChildPath outfileTest.txt
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
It "Should create a new variable with no parameters" {
{ Set-Variable testVar } | Should -Not -Throw
}

View file

@ -2,6 +2,18 @@
# Licensed under the MIT License.
Describe "Hidden properties should not be returned by the 'FirstOrDefault' primitive" -Tag CI {
BeforeAll {
if ($null -ne $PSStyle) {
$outputRendering = $PSStyle.OutputRendering
$PSStyle.OutputRendering = 'plaintext'
}
}
AfterAll {
if ($null -ne $PSStyle) {
$PSStyle.OutputRendering = $outputRendering
}
}
It "Formatting for an object with no property/field should use 'ToString'" {
class Empty {

View file

@ -15,7 +15,7 @@ Describe 'Tests for $ErrorView' -Tag CI {
It 'Exceptions not thrown do not get formatted as ErrorRecord' {
$exp = [System.Exception]::new('test') | Out-String
$exp | Should -BeLike "*Message : test*"
$exp | Should -BeLike "*Message : *test*"
}
Context 'ConciseView tests' {

View file

@ -24,6 +24,7 @@ Describe 'Tests for $PSStyle automatic variable' {
$formattingDefaults = @{
FormatAccent = "`e[32;1m"
TableHeader = "`e[32;1m"
ErrorAccent = "`e[36;1m"
Error = "`e[31;1m"
Debug = "`e[33;1m"
@ -138,4 +139,30 @@ Describe 'Tests for $PSStyle automatic variable' {
$o = $PSStyle.FormatHyperlink('PSBlog','https://aka.ms/psblog')
$o | Should -BeExactly "`e]8;;https://aka.ms/psblog`e\PSBlog`e]8;;`e\" -Because ($o | Format-Hex | Out-String)
}
It '$PSStyle.Formatting.FormatAccent is applied to Format-List' {
$old = $PSStyle.Formatting.FormatAccent
try {
$PSStyle.Formatting.FormatAccent = $PSStyle.Foreground.Yellow + $PSStyle.Background.Red + $PSStyle.Italic
$out = $PSVersionTable | Format-List | Out-String
$out | Should -BeLike "*$($PSStyle.Formatting.FormatAccent.Replace('[',"``["))*"
}
finally {
$PSStyle.Formatting.FormatAccent = $old
}
}
It '$PSStyle.Formatting.TableHeader is applied to Format-Table' {
$old = $PSStyle.Formatting.TableHeader
try {
$PSStyle.Formatting.TableHeader = $PSStyle.Foreground.Blue + $PSStyle.Background.White + $PSStyle.Bold
$out = $PSVersionTable | Format-Table | Out-String
$out | Should -BeLike "*$($PSStyle.Formatting.TableHeader.Replace('[',"``["))*"
}
finally {
$PSStyle.Formatting.TableHeader = $old
}
}
}