mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Make Out-String and Out-File keep string input unchanged (#17455)
This commit is contained in:
@@ -552,7 +552,8 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
else
|
||||
{
|
||||
_lo.WriteLine(rte.text);
|
||||
// Write out raw text without any changes to it.
|
||||
_lo.WriteRawText(rte.text);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -250,6 +250,13 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// </param>
|
||||
internal abstract void WriteLine(string s);
|
||||
|
||||
/// <summary>
|
||||
/// Write a line of string as raw text to the output device, with no change to the string.
|
||||
/// For example, keeping VT escape sequences intact in it.
|
||||
/// </summary>
|
||||
/// <param name="s">The raw text to be written to the device.</param>
|
||||
internal virtual void WriteRawText(string s) => WriteLine(s);
|
||||
|
||||
internal WriteStreamType WriteStream
|
||||
{
|
||||
get;
|
||||
@@ -431,7 +438,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// Implementation of the ILineOutput interface accepting an instance of a
|
||||
/// TextWriter abstract class.
|
||||
/// </summary>
|
||||
internal class TextWriterLineOutput : LineOutput
|
||||
internal sealed class TextWriterLineOutput : LineOutput
|
||||
{
|
||||
#region ILineOutput methods
|
||||
|
||||
@@ -467,9 +474,17 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// <param name="s"></param>
|
||||
internal override void WriteLine(string s)
|
||||
{
|
||||
CheckStopProcessing();
|
||||
WriteRawText(PSHostUserInterface.GetOutputString(s, isHost: false));
|
||||
}
|
||||
|
||||
s = PSHostUserInterface.GetOutputString(s, isHost: false);
|
||||
/// <summary>
|
||||
/// Write a raw text by delegating to the writer underneath, with no change to the text.
|
||||
/// For example, keeping VT escape sequences intact in it.
|
||||
/// </summary>
|
||||
/// <param name="s">The raw text to be written to the device.</param>
|
||||
internal override void WriteRawText(string s)
|
||||
{
|
||||
CheckStopProcessing();
|
||||
|
||||
if (_suppressNewline)
|
||||
{
|
||||
@@ -480,6 +495,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
_writer.WriteLine(s);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -115,7 +115,8 @@ Describe 'Tests for $ErrorView' -Tag CI {
|
||||
|
||||
It "Error shows for advanced function" {
|
||||
# need to have it virtually interactive so that InvocationInfo.MyCommand is empty
|
||||
$e = '[cmdletbinding()]param()$pscmdlet.writeerror([System.Management.Automation.ErrorRecord]::new(([System.NotImplementedException]::new("myTest")),"stub","notimplemented","command"))' | pwsh -noprofile -file - 2>&1 | Out-String
|
||||
$e = '[cmdletbinding()]param()$pscmdlet.writeerror([System.Management.Automation.ErrorRecord]::new(([System.NotImplementedException]::new("myTest")),"stub","notimplemented","command"))' | pwsh -noprofile -file - 2>&1
|
||||
$e = $e | Where-Object { $_ -is [System.Management.Automation.ErrorRecord] } | Out-String
|
||||
$e | Should -Not -BeNullOrEmpty
|
||||
|
||||
# need to see if ANSI escape sequences are in the output as ANSI is disabled for CI
|
||||
|
||||
@@ -39,7 +39,7 @@ Describe 'OutputRendering tests' {
|
||||
param($outputRendering, $ansi)
|
||||
|
||||
$PSStyle.OutputRendering = $outputRendering
|
||||
$out = "$($PSStyle.Foreground.Green)hello" | Out-String
|
||||
$out = [pscustomobject] @{ key = "$($PSStyle.Foreground.Green)hello" } | Out-String
|
||||
|
||||
if ($ansi) {
|
||||
$out | Should -BeLike "*`e*" -Because ($out | Format-Hex | Out-String)
|
||||
|
||||
@@ -286,6 +286,77 @@ Describe 'Tests for $PSStyle automatic variable' {
|
||||
$strDec.ContentLength | Should -Be $word.Length
|
||||
$strDec.ToString("PlainText") | Should -Be $word
|
||||
}
|
||||
|
||||
It "String intput to Out-String should be intact with OutputRendering='<OutputRendering>'" -TestCases @(
|
||||
@{ OutputRendering = 'Ansi'; ContainsAnsi = $true }
|
||||
@{ OutputRendering = 'Host'; ContainsAnsi = $false }
|
||||
@{ OutputRendering = 'PlainText'; ContainsAnsi = $false }
|
||||
) {
|
||||
param($OutputRendering, $ContainsAnsi)
|
||||
|
||||
$oldRender = $PSStyle.OutputRendering
|
||||
$testStr = "`e[31mABC`e[0m"
|
||||
|
||||
try {
|
||||
$PSStyle.OutputRendering = $OutputRendering
|
||||
## For input that actually goes through formatting, Out-String should remove VT sequences
|
||||
## from the formatting output based on the output rendering option that is in effect.
|
||||
(Get-Verb -Verb Get | Out-String).Contains("`e[") | Should -Be $ContainsAnsi
|
||||
## For string input, since no formatting is applied, Out-String should keep the string intact.
|
||||
($testStr | Out-String).Trim() | Should -BeExactly $testStr
|
||||
}
|
||||
finally {
|
||||
$PSStyle.OutputRendering = $oldRender
|
||||
}
|
||||
}
|
||||
|
||||
It "String input to Out-File should be intact with OutputRendering='<OutputRendering>'" -TestCases @(
|
||||
@{ OutputRendering = 'Ansi'; }
|
||||
@{ OutputRendering = 'Host'; }
|
||||
@{ OutputRendering = 'PlainText'; }
|
||||
) {
|
||||
param($OutputRendering)
|
||||
|
||||
$oldRender = $PSStyle.OutputRendering
|
||||
$content = "Read-Host -Prompt '`e[33mEnter your device code`e[0m'"
|
||||
Set-Content -Path $TestDrive\test.ps1 -Value $content -Encoding utf8NoBOM
|
||||
|
||||
try {
|
||||
$PSStyle.OutputRendering = $OutputRendering
|
||||
Get-Content $TestDrive\test.ps1 > $TestDrive\copy.ps1
|
||||
(Get-Content $TestDrive\copy.ps1 -Raw).Trim() | Should -BeExactly $content
|
||||
}
|
||||
finally {
|
||||
$PSStyle.OutputRendering = $oldRender
|
||||
Remove-Item $TestDrive\test.ps1 -Force
|
||||
Remove-Item $TestDrive\copy.ps1 -Force
|
||||
}
|
||||
}
|
||||
|
||||
It "Comment based help works with `$PSStyle when OutputRendering='<OutputRendering>'" -TestCases @(
|
||||
@{ OutputRendering = 'Ansi'; ContainsAnsi = $true }
|
||||
@{ OutputRendering = 'Host'; ContainsAnsi = $false }
|
||||
@{ OutputRendering = 'PlainText'; ContainsAnsi = $false }
|
||||
) {
|
||||
param($OutputRendering, $ContainsAnsi)
|
||||
|
||||
$oldRender = $PSStyle.OutputRendering
|
||||
|
||||
function Test-PSStyle {
|
||||
<#
|
||||
.Description
|
||||
Get-Function [31mdisplays[0m the name and syntax of all functions in the session.
|
||||
#>
|
||||
}
|
||||
|
||||
try {
|
||||
$PSStyle.OutputRendering = $OutputRendering
|
||||
(Get-Help Test-PSStyle | Out-String).Contains("`e[31mdisplays`e[0m") | Should -Be $ContainsAnsi
|
||||
}
|
||||
finally {
|
||||
$PSStyle.OutputRendering = $oldRender
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Handle strings with escape sequences in formatting' {
|
||||
|
||||
Reference in New Issue
Block a user