Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Management.Automation;
using System.Management.Automation.Internal;
using System.Text;
using System.Text.RegularExpressions;

namespace Microsoft.PowerShell.Commands.Internal.Format
{
Expand Down Expand Up @@ -317,6 +316,7 @@ internal struct GetWordsResult
{
internal string Word;
internal string Delim;
internal bool VtResetAdded;
}

/// <summary>
Expand Down Expand Up @@ -367,9 +367,19 @@ private static IEnumerable<GetWordsResult> GetWords(string s)
{
var vtSpan = s.AsSpan(i, len);
sb.Append(vtSpan);
vtSeqs.Append(vtSpan);

wordHasVtSeqs = true;
if (vtSpan.SequenceEqual(PSStyle.Instance.Reset))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth checking for `e[m as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. There are many other places where PSStyle.Instance.Reset is checked but not "\x1b[m". I will open an issue tracking this, and maybe do it in a separate PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracking issue opened: #26526

{
// The Reset sequence will void all previous VT sequences.
Comment thread
daxian-dbw marked this conversation as resolved.
vtSeqs.Clear();
Comment thread
daxian-dbw marked this conversation as resolved.
wordHasVtSeqs = false;
}
else
{
vtSeqs.Append(vtSpan);
Comment thread
daxian-dbw marked this conversation as resolved.
wordHasVtSeqs = true;
}

i += len - 1;
continue;
}
Expand All @@ -390,15 +400,18 @@ private static IEnumerable<GetWordsResult> GetWords(string s)

if (delimiter is not null)
{
bool vtResetAdded = false;
if (wordHasVtSeqs && !sb.EndsWith(PSStyle.Instance.Reset))
{
vtResetAdded = true;
sb.Append(PSStyle.Instance.Reset);
}

var result = new GetWordsResult()
{
Word = sb.ToString(),
Delim = delimiter
Delim = delimiter,
VtResetAdded = vtResetAdded
};

sb.Clear().Append(vtSeqs);
Expand Down Expand Up @@ -611,7 +624,7 @@ private static StringCollection GenerateLinesWithWordWrap(DisplayCells displayCe

if (suffix is not null)
{
wordToAdd = wordToAdd.EndsWith(resetStr)
wordToAdd = word.VtResetAdded
? wordToAdd.Insert(wordToAdd.Length - resetStr.Length, suffix)
: wordToAdd + suffix;
}
Expand Down Expand Up @@ -760,9 +773,19 @@ internal static List<string> SplitLines(string s)
{
var vtSpan = s.AsSpan(i, len);
sb.Append(vtSpan);
vtSeqs.Append(vtSpan);

hasVtSeqs = true;
if (vtSpan.SequenceEqual(PSStyle.Instance.Reset))
{
// The Reset sequence will void all previous VT sequences.
Comment thread
daxian-dbw marked this conversation as resolved.
vtSeqs.Clear();
Comment thread
daxian-dbw marked this conversation as resolved.
hasVtSeqs = false;
}
else
{
vtSeqs.Append(vtSpan);
Comment thread
daxian-dbw marked this conversation as resolved.
hasVtSeqs = true;
}

i += len - 1;
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ private void WriteSingleLineHelper(string prependString, string line, LineOutput
_cachedBuilder.Append(headPadding).Append(str);
}

if (str.Contains(ValueStringDecorated.ESC) && !str.EndsWith(reset))
if (str.Contains(ValueStringDecorated.ESC) && !str.AsSpan().TrimEnd().EndsWith(reset, StringComparison.Ordinal))
{
_cachedBuilder.Append(reset);
}
Expand Down
81 changes: 79 additions & 2 deletions test/powershell/engine/Formatting/PSStyle.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ Billy Bob… Senior DevOps … 13
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Word wrapping for string with escape sequences" {
It "Word wrapping for string with escape sequences (1)" {
$expected = @"
`e[32;1mLongDescription : `e[0m`e[33mPowerShell `e[0m
`e[33mscripting `e[0m
Expand All @@ -501,7 +501,46 @@ Billy Bob… Senior DevOps … 13
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Splitting multi-line string with escape sequences" {
It "Word wrapping for string with escape sequences (2)" {
$expected = @"
`e[32;1mLongDescription : `e[0m`e[33mPowerShell`e[0m
scripting
language
"@
$obj = [pscustomobject] @{ LongDescription = "`e[33mPowerShell`e[0m scripting language" }
$obj | Format-List | Out-String -Width 35 | Out-File $outFile

$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Word wrapping for string with escape sequences (3)" {
$expected = @"
`e[32;1mLongDescription : `e[0m`e[33mPowerShell`e[0m
`e[32mscripting `e[0m
`e[32mlanguage`e[0m
"@
$obj = [pscustomobject] @{ LongDescription = "`e[33mPowerShell`e[0m `e[32mscripting language" }
$obj | Format-List | Out-String -Width 35 | Out-File $outFile

$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Word wrapping for string with escape sequences (4)" {
$expected = @"
`e[32;1mLongDescription : `e[0m`e[33mPowerShell`e[0m
`e[32mscripting`e[0m
language
"@
$obj = [pscustomobject] @{ LongDescription = "`e[33mPowerShell`e[0m `e[32mscripting`e[0m language" }
$obj | Format-List | Out-String -Width 35 | Out-File $outFile

$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Splitting multi-line string with escape sequences (1)" {
$expected = @"
`e[32;1mb : `e[0m`e[33mPowerShell is a task automation and configuration management program from Microsoft,`e[0m
`e[33mconsisting of a command-line shell and the associated scripting language`e[0m
Expand All @@ -513,6 +552,30 @@ Billy Bob… Senior DevOps … 13
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Splitting multi-line string with escape sequences (2)" {
$expected = @"
`e[32;1mb : `e[0m`e[33mPowerShell is a task automation and configuration management program from Microsoft,`e[0m
consisting of a command-line shell and the associated scripting language
"@
$obj = [pscustomobject] @{ b = "`e[33mPowerShell is a task automation and configuration management program from Microsoft,`e[0m`nconsisting of a command-line shell and the associated scripting language" }
$obj | Format-List | Out-File $outFile

$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Splitting multi-line string with escape sequences (3)" {
$expected = @"
`e[32;1mb : `e[0m`e[33mPowerShell is a task automation and configuration management program from Microsoft,`e[0m
`e[32mconsisting of a command-line shell and the associated scripting language`e[0m
"@
$obj = [pscustomobject] @{ b = "`e[33mPowerShell is a task automation and configuration management program from Microsoft,`e[0m`n`e[32mconsisting of a command-line shell and the associated scripting language" }
$obj | Format-List | Out-File $outFile

$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Wrapping long word with escape sequences" {
$expected = @"
`e[32;1mb : `e[0m`e[33mC:\repos\PowerShell\src\powershell-w`e[0m
Expand All @@ -525,4 +588,18 @@ Billy Bob… Senior DevOps … 13
$text = Get-Content $outFile -Raw
$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}

It "Format 'MatchInfo' object correctly" {
$expected = @"
`e[32;1mb : `e[0mmouclass `e[7mMouse`e[0m Class Driver Mouse Class Driver Kernel Manual Running OK TRUE FALSE 12,288 `e[0m
32,768 0 C:\WINDOWS\system32\drivers\mouclass.sys 4,096
"@

## This string mimics the VT decorated string for a 'MatchInfo' object that matches the word 'mouse'.
$str = "mouclass `e[7mMouse`e[0m Class Driver Mouse Class Driver Kernel Manual Running OK TRUE FALSE 12,288 32,768 0 C:\WINDOWS\system32\drivers\mouclass.sys 4,096"
$obj = [pscustomobject] @{ b = $str }
$text = $obj | Format-List | Out-String -Width 150

$text.Trim().Replace("`r", "") | Should -BeExactly $expected.Replace("`r", "")
}
}
Loading