mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Enable ANSI formatting via $PSStyle and support suppressing ANSI output (#13758)
This commit is contained in:
@@ -696,6 +696,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
|
||||
TextWriter writer = Console.IsOutputRedirected ? Console.Out : _parent.ConsoleTextWriter;
|
||||
value = Utils.GetOutputString(value, isHost: true, SupportsVirtualTerminal, Console.IsOutputRedirected);
|
||||
|
||||
if (_parent.IsRunningAsync)
|
||||
{
|
||||
@@ -1179,11 +1180,17 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
else
|
||||
{
|
||||
// NTRAID#Windows OS Bugs-1061752-2004/12/15-sburns should read a skin setting here...
|
||||
WriteLine(
|
||||
DebugForegroundColor,
|
||||
DebugBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message));
|
||||
if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Debug) + StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(
|
||||
DebugForegroundColor,
|
||||
DebugBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.DebugFormatString, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1234,10 +1241,17 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(
|
||||
VerboseForegroundColor,
|
||||
VerboseBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message));
|
||||
if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Verbose) + StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(
|
||||
VerboseForegroundColor,
|
||||
VerboseBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.VerboseFormatString, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,10 +1285,17 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(
|
||||
WarningForegroundColor,
|
||||
WarningBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message));
|
||||
if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
WriteLine(Utils.GetFormatStyleString(Utils.FormatStyle.Warning) + StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message));
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(
|
||||
WarningForegroundColor,
|
||||
WarningBackgroundColor,
|
||||
StringUtil.Format(ConsoleHostUserInterfaceStrings.WarningFormatString, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1334,9 +1355,20 @@ namespace Microsoft.PowerShell
|
||||
else
|
||||
{
|
||||
if (writer == _parent.ConsoleTextWriter)
|
||||
WriteLine(ErrorForegroundColor, ErrorBackgroundColor, value);
|
||||
{
|
||||
if (SupportsVirtualTerminal && ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
WriteLine(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine(ErrorForegroundColor, ErrorBackgroundColor, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+143
-1
@@ -263,6 +263,22 @@ namespace System.Management.Automation.Runspaces
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"Microsoft.PowerShell.Commands.ByteCollection",
|
||||
ViewsOf_Microsoft_PowerShell_Commands_ByteCollection());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"System.Management.Automation.PSStyle",
|
||||
ViewsOf_System_Management_Automation_PSStyle());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"System.Management.Automation.PSStyle+FormattingData",
|
||||
ViewsOf_System_Management_Automation_PSStyleFormattingData());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"System.Management.Automation.PSStyle+ForegroundColor",
|
||||
ViewsOf_System_Management_Automation_PSStyleForegroundColor());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"System.Management.Automation.PSStyle+BackgroundColor",
|
||||
ViewsOf_System_Management_Automation_PSStyleBackgroundColor());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_RuntimeType()
|
||||
@@ -1317,7 +1333,7 @@ namespace System.Management.Automation.Runspaces
|
||||
$err.CategoryInfo.GetMessage()
|
||||
}
|
||||
elseif (! $err.ErrorDetails -or ! $err.ErrorDetails.Message) {
|
||||
$err.Exception.Message + $posmsg + $newline
|
||||
$err.Exception.Message + $posmsg
|
||||
} else {
|
||||
$err.ErrorDetails.Message + $posmsg
|
||||
}
|
||||
@@ -2004,5 +2020,131 @@ namespace System.Management.Automation.Runspaces
|
||||
.GroupByProperty("Label")
|
||||
.EndTable());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_PSStyle()
|
||||
{
|
||||
yield return new FormatViewDefinition("System.Management.Automation.PSStyle",
|
||||
ListControl.Create()
|
||||
.StartEntry()
|
||||
.AddItemScriptBlock(@"""$($_.Reset)$($_.Reset.Replace(""""`e"""",'`e'))""", label: "Reset")
|
||||
.AddItemScriptBlock(@"""$($_.BlinkOff)$($_.BlinkOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "BlinkOff")
|
||||
.AddItemScriptBlock(@"""$($_.Blink)$($_.Blink.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Blink")
|
||||
.AddItemScriptBlock(@"""$($_.BoldOff)$($_.BoldOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "BoldOff")
|
||||
.AddItemScriptBlock(@"""$($_.Bold)$($_.Bold.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Bold")
|
||||
.AddItemScriptBlock(@"""$($_.Hidden)$($_.Hidden.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Hidden")
|
||||
.AddItemScriptBlock(@"""$($_.HiddenOff)$($_.HiddenOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "HiddenOff")
|
||||
.AddItemScriptBlock(@"""$($_.Reverse)$($_.Reverse.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Reverse")
|
||||
.AddItemScriptBlock(@"""$($_.ReverseOff)$($_.ReverseOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "ReverseOff")
|
||||
.AddItemScriptBlock(@"""$($_.ItalicOff)$($_.ItalicOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "ItalicOff")
|
||||
.AddItemScriptBlock(@"""$($_.Italic)$($_.Italic.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Italic")
|
||||
.AddItemScriptBlock(@"""$($_.UnderlineOff)$($_.UnderlineOff.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "UnderlineOff")
|
||||
.AddItemScriptBlock(@"""$($_.Underline)$($_.Underline.Replace(""""`e"""",'`e'))$($_.Reset)""", label: "Underline")
|
||||
.AddItemProperty(@"OutputRendering")
|
||||
.AddItemScriptBlock(@"""$($_.Formatting.FormatAccent)$($_.Formatting.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.FormatAccent")
|
||||
.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")
|
||||
.AddItemScriptBlock(@"""$($_.Formatting.Verbose)$($_.Formatting.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Verbose")
|
||||
.AddItemScriptBlock(@"""$($_.Formatting.Debug)$($_.Formatting.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Debug")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Black)$($_.Foreground.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Black")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.White)$($_.Foreground.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.White")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.DarkGray)$($_.Foreground.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.DarkGray")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightGray)$($_.Foreground.LightGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightGray")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Red)$($_.Foreground.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Red")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightRed)$($_.Foreground.LightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightRed")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Magenta)$($_.Foreground.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Magenta")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightMagenta)$($_.Foreground.LightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightMagenta")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Blue)$($_.Foreground.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Blue")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightBlue)$($_.Foreground.LightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightBlue")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Cyan)$($_.Foreground.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Cyan")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightCyan)$($_.Foreground.LightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightCyan")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Green)$($_.Foreground.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Green")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightGreen)$($_.Foreground.LightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightGreen")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.Yellow)$($_.Foreground.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.Yellow")
|
||||
.AddItemScriptBlock(@"""$($_.Foreground.LightYellow)$($_.Foreground.LightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Foreground.LightYellow")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Black)$($_.Background.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Black")
|
||||
.AddItemScriptBlock(@"""$($_.Background.White)$($_.Background.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.White")
|
||||
.AddItemScriptBlock(@"""$($_.Background.DarkGray)$($_.Background.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.DarkGray")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightGray)$($_.Background.LightGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightGray")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Red)$($_.Background.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Red")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightRed)$($_.Background.LightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightRed")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Magenta)$($_.Background.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Magenta")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightMagenta)$($_.Background.LightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightMagenta")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Blue)$($_.Background.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Blue")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightBlue)$($_.Background.LightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightBlue")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Cyan)$($_.Background.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Cyan")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightCyan)$($_.Background.LightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightCyan")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Green)$($_.Background.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Green")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightGreen)$($_.Background.LightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightGreen")
|
||||
.AddItemScriptBlock(@"""$($_.Background.Yellow)$($_.Background.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.Yellow")
|
||||
.AddItemScriptBlock(@"""$($_.Background.LightYellow)$($_.Background.LightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Background.LightYellow")
|
||||
.EndEntry()
|
||||
.EndList());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_PSStyleFormattingData()
|
||||
{
|
||||
yield return new FormatViewDefinition("System.Management.Automation.PSStyle+FormattingData",
|
||||
ListControl.Create()
|
||||
.StartEntry()
|
||||
.AddItemScriptBlock(@"""$($_.FormatAccent)$($_.FormatAccent.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "FormatAccent")
|
||||
.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")
|
||||
.AddItemScriptBlock(@"""$($_.Verbose)$($_.Verbose.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Formatting.Verbose")
|
||||
.AddItemScriptBlock(@"""$($_.Debug)$($_.Debug.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Debug")
|
||||
.EndEntry()
|
||||
.EndList());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_PSStyleForegroundColor()
|
||||
{
|
||||
yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ForegroundColor",
|
||||
ListControl.Create()
|
||||
.StartEntry()
|
||||
.AddItemScriptBlock(@"""$($_.Black)$($_.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Black")
|
||||
.AddItemScriptBlock(@"""$($_.White)$($_.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "White")
|
||||
.AddItemScriptBlock(@"""$($_.DarkGray)$($_.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "DarkGray")
|
||||
.AddItemScriptBlock(@"""$($_.LightGray)$($_.LightGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightGray")
|
||||
.AddItemScriptBlock(@"""$($_.Red)$($_.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Red")
|
||||
.AddItemScriptBlock(@"""$($_.LightRed)$($_.LightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightRed")
|
||||
.AddItemScriptBlock(@"""$($_.Magenta)$($_.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Magenta")
|
||||
.AddItemScriptBlock(@"""$($_.LightMagenta)$($_.LightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightMagenta")
|
||||
.AddItemScriptBlock(@"""$($_.Blue)$($_.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Blue")
|
||||
.AddItemScriptBlock(@"""$($_.LightBlue)$($_.LightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightBlue")
|
||||
.AddItemScriptBlock(@"""$($_.Cyan)$($_.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Cyan")
|
||||
.AddItemScriptBlock(@"""$($_.LightCyan)$($_.LightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightCyan")
|
||||
.AddItemScriptBlock(@"""$($_.Green)$($_.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Green")
|
||||
.AddItemScriptBlock(@"""$($_.LightGreen)$($_.LightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightGreen")
|
||||
.AddItemScriptBlock(@"""$($_.Yellow)$($_.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Yellow")
|
||||
.AddItemScriptBlock(@"""$($_.LightYellow)$($_.LightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightYellow")
|
||||
.EndEntry()
|
||||
.EndList());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_PSStyleBackgroundColor()
|
||||
{
|
||||
yield return new FormatViewDefinition("System.Management.Automation.PSStyle+ForegroundColor",
|
||||
ListControl.Create()
|
||||
.StartEntry()
|
||||
.AddItemScriptBlock(@"""$($_.Black)$($_.Black.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Black")
|
||||
.AddItemScriptBlock(@"""$($_.White)$($_.White.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "White")
|
||||
.AddItemScriptBlock(@"""$($_.DarkGray)$($_.DarkGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "DarkGray")
|
||||
.AddItemScriptBlock(@"""$($_.LightGray)$($_.LightGray.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightGray")
|
||||
.AddItemScriptBlock(@"""$($_.Red)$($_.Red.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Red")
|
||||
.AddItemScriptBlock(@"""$($_.LightRed)$($_.LightRed.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightRed")
|
||||
.AddItemScriptBlock(@"""$($_.Magenta)$($_.Magenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Magenta")
|
||||
.AddItemScriptBlock(@"""$($_.LightMagenta)$($_.LightMagenta.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightMagenta")
|
||||
.AddItemScriptBlock(@"""$($_.Blue)$($_.Blue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Blue")
|
||||
.AddItemScriptBlock(@"""$($_.LightBlue)$($_.LightBlue.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightBlue")
|
||||
.AddItemScriptBlock(@"""$($_.Cyan)$($_.Cyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Cyan")
|
||||
.AddItemScriptBlock(@"""$($_.LightCyan)$($_.LightCyan.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightCyan")
|
||||
.AddItemScriptBlock(@"""$($_.Green)$($_.Green.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Green")
|
||||
.AddItemScriptBlock(@"""$($_.LightGreen)$($_.LightGreen.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightGreen")
|
||||
.AddItemScriptBlock(@"""$($_.Yellow)$($_.Yellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "Yellow")
|
||||
.AddItemScriptBlock(@"""$($_.LightYellow)$($_.LightYellow.Replace(""""`e"""",'`e'))$($PSStyle.Reset)""", label: "LightYellow")
|
||||
.EndEntry()
|
||||
.EndList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Text;
|
||||
|
||||
// interfaces for host interaction
|
||||
@@ -411,6 +412,9 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
internal override void WriteLine(string s)
|
||||
{
|
||||
CheckStopProcessing();
|
||||
|
||||
s = Utils.GetOutputString(s, isHost: false);
|
||||
|
||||
if (_suppressNewline)
|
||||
{
|
||||
_writer.Write(s);
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace System.Management.Automation
|
||||
{
|
||||
#region OutputRendering
|
||||
/// <summary>
|
||||
/// Defines the options for output rendering.
|
||||
/// </summary>
|
||||
public enum OutputRendering
|
||||
{
|
||||
/// <summary>Automatic by PowerShell.</summary>
|
||||
Automatic = 0,
|
||||
|
||||
/// <summary>Render as plaintext.</summary>
|
||||
PlainText = 1,
|
||||
|
||||
/// <summary>Render as ANSI.</summary>
|
||||
Ansi = 2,
|
||||
|
||||
/// <summary>Render ANSI only to host.</summary>
|
||||
Host = 3,
|
||||
}
|
||||
#endregion OutputRendering
|
||||
|
||||
#region PSStyle
|
||||
/// <summary>
|
||||
/// Contains configuration for how PowerShell renders text.
|
||||
/// </summary>
|
||||
public class PSStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains foreground colors.
|
||||
/// </summary>
|
||||
public class ForegroundColor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the color black.
|
||||
/// </summary>
|
||||
public string Black { get; } = "\x1b[30m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color blue.
|
||||
/// </summary>
|
||||
public string Blue { get; } = "\x1b[34m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color cyan.
|
||||
/// </summary>
|
||||
public string Cyan { get; } = "\x1b[36m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color dark gray.
|
||||
/// </summary>
|
||||
public string DarkGray { get; } = "\x1b[90m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color green.
|
||||
/// </summary>
|
||||
public string Green { get; } = "\x1b[32m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light blue.
|
||||
/// </summary>
|
||||
public string LightBlue { get; } = "\x1b[94m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light cyan.
|
||||
/// </summary>
|
||||
public string LightCyan { get; } = "\x1b[96m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light gray.
|
||||
/// </summary>
|
||||
public string LightGray { get; } = "\x1b[97m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light green.
|
||||
/// </summary>
|
||||
public string LightGreen { get; } = "\x1b[92m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light magenta.
|
||||
/// </summary>
|
||||
public string LightMagenta { get; } = "\x1b[95m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light red.
|
||||
/// </summary>
|
||||
public string LightRed { get; } = "\x1b[91m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light yellow.
|
||||
/// </summary>
|
||||
public string LightYellow { get; } = "\x1b[93m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color magenta.
|
||||
/// </summary>
|
||||
public string Magenta { get; } = "\x1b[35m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color read.
|
||||
/// </summary>
|
||||
public string Red { get; } = "\x1b[31m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color white.
|
||||
/// </summary>
|
||||
public string White { get; } = "\x1b[37m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color yellow.
|
||||
/// </summary>
|
||||
public string Yellow { get; } = "\x1b[33m";
|
||||
|
||||
/// <summary>
|
||||
/// Set as RGB (Red, Green, Blue).
|
||||
/// </summary>
|
||||
/// <param name="red">Byte value representing red.</param>
|
||||
/// <param name="green">Byte value representing green.</param>
|
||||
/// <param name="blue">Byte value representing blue.</param>
|
||||
/// <returns>String representing ANSI code for RGB value.</returns>
|
||||
public string FromRgb(byte red, byte green, byte blue)
|
||||
{
|
||||
return $"\x1b[38;2;{red};{green};{blue}m";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The color set as RGB as a single number.
|
||||
/// </summary>
|
||||
/// <param name="rgb">RGB value specified as an integer.</param>
|
||||
/// <returns>String representing ANSI code for RGB value.</returns>
|
||||
public string FromRgb(int rgb)
|
||||
{
|
||||
byte red, green, blue;
|
||||
blue = (byte)(rgb & 0xFF);
|
||||
rgb >>= 8;
|
||||
green = (byte)(rgb & 0xFF);
|
||||
rgb >>= 8;
|
||||
red = (byte)(rgb & 0xFF);
|
||||
|
||||
return FromRgb(red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains background colors.
|
||||
/// </summary>
|
||||
public class BackgroundColor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the color black.
|
||||
/// </summary>
|
||||
public string Black { get; } = "\x1b[40m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color blue.
|
||||
/// </summary>
|
||||
public string Blue { get; } = "\x1b[44m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color cyan.
|
||||
/// </summary>
|
||||
public string Cyan { get; } = "\x1b[46m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color dark gray.
|
||||
/// </summary>
|
||||
public string DarkGray { get; } = "\x1b[100m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color green.
|
||||
/// </summary>
|
||||
public string Green { get; } = "\x1b[42m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light blue.
|
||||
/// </summary>
|
||||
public string LightBlue { get; } = "\x1b[104m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light cyan.
|
||||
/// </summary>
|
||||
public string LightCyan { get; } = "\x1b[106m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light gray.
|
||||
/// </summary>
|
||||
public string LightGray { get; } = "\x1b[107m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light green.
|
||||
/// </summary>
|
||||
public string LightGreen { get; } = "\x1b[102m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light magenta.
|
||||
/// </summary>
|
||||
public string LightMagenta { get; } = "\x1b[105m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light red.
|
||||
/// </summary>
|
||||
public string LightRed { get; } = "\x1b[101m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color light yellow.
|
||||
/// </summary>
|
||||
public string LightYellow { get; } = "\x1b[103m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color magenta.
|
||||
/// </summary>
|
||||
public string Magenta { get; } = "\x1b[45m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color read.
|
||||
/// </summary>
|
||||
public string Red { get; } = "\x1b[41m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color white.
|
||||
/// </summary>
|
||||
public string White { get; } = "\x1b[47m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color yellow.
|
||||
/// </summary>
|
||||
public string Yellow { get; } = "\x1b[43m";
|
||||
|
||||
/// <summary>
|
||||
/// The color set as RGB (Red, Green, Blue).
|
||||
/// </summary>
|
||||
/// <param name="red">Byte value representing red.</param>
|
||||
/// <param name="green">Byte value representing green.</param>
|
||||
/// <param name="blue">Byte value representing blue.</param>
|
||||
/// <returns>String representing ANSI code for RGB value.</returns>
|
||||
public string FromRgb(byte red, byte green, byte blue)
|
||||
{
|
||||
return $"\x1b[48;2;{red};{green};{blue}m";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The color set as RGB as a single number.
|
||||
/// </summary>
|
||||
/// <param name="rgb">RGB value specified as an integer.</param>
|
||||
/// <returns>String representing ANSI code for RGB value.</returns>
|
||||
public string FromRgb(int rgb)
|
||||
{
|
||||
byte red, green, blue;
|
||||
blue = (byte)(rgb & 0xFF);
|
||||
rgb >>= 8;
|
||||
green = (byte)(rgb & 0xFF);
|
||||
rgb >>= 8;
|
||||
red = (byte)(rgb & 0xFF);
|
||||
|
||||
return FromRgb(red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains formatting styles for steams and objects.
|
||||
/// </summary>
|
||||
public class FormattingData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the accent style for formatting.
|
||||
/// </summary>
|
||||
public string FormatAccent { get; set; } = "\x1b[32;1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accent style for errors.
|
||||
/// </summary>
|
||||
public string ErrorAccent { get; set; } = "\x1b[36;1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the style for error messages.
|
||||
/// </summary>
|
||||
public string Error { get; set; } = "\x1b[31;1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the style for warning messages.
|
||||
/// </summary>
|
||||
public string Warning { get; set; } = "\x1b[33;1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the style for verbose messages.
|
||||
/// </summary>
|
||||
public string Verbose { get; set; } = "\x1b[33;1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the style for debug messages.
|
||||
/// </summary>
|
||||
public string Debug { get; set; } = "\x1b[33;1m";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the rendering mode for output.
|
||||
/// </summary>
|
||||
public OutputRendering OutputRendering { get; set; } = OutputRendering.Automatic;
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off all attributes.
|
||||
/// </summary>
|
||||
public string Reset { get; } = "\x1b[0m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off blink.
|
||||
/// </summary>
|
||||
public string BlinkOff { get; } = "\x1b[5m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on blink.
|
||||
/// </summary>
|
||||
public string Blink { get; } = "\x1b[25m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off bold.
|
||||
/// </summary>
|
||||
public string BoldOff { get; } = "\x1b[22m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on blink.
|
||||
/// </summary>
|
||||
public string Bold { get; } = "\x1b[1m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on hidden.
|
||||
/// </summary>
|
||||
public string Hidden { get; } = "\x1b[8m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off hidden.
|
||||
/// </summary>
|
||||
public string HiddenOff { get; } = "\x1b[28m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on reverse.
|
||||
/// </summary>
|
||||
public string Reverse { get; } = "\x1b[7m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off reverse.
|
||||
/// </summary>
|
||||
public string ReverseOff { get; } = "\x1b[27m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off standout.
|
||||
/// </summary>
|
||||
public string ItalicOff { get; } = "\x1b[23m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on standout.
|
||||
/// </summary>
|
||||
public string Italic { get; } = "\x1b[3m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn off underlined.
|
||||
/// </summary>
|
||||
public string UnderlineOff { get; } = "\x1b[24m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets value to turn on underlined.
|
||||
/// </summary>
|
||||
public string Underline { get; } = "\x1b[4m";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the formatting rendering settings.
|
||||
/// </summary>
|
||||
public FormattingData Formatting { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets foreground colors.
|
||||
/// </summary>
|
||||
public ForegroundColor Foreground { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets background colors.
|
||||
/// </summary>
|
||||
public BackgroundColor Background { get; }
|
||||
|
||||
private static readonly PSStyle s_psstyle = new PSStyle();
|
||||
|
||||
private PSStyle()
|
||||
{
|
||||
Formatting = new FormattingData();
|
||||
Foreground = new ForegroundColor();
|
||||
Background = new BackgroundColor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets singleton instance.
|
||||
/// </summary>
|
||||
public static PSStyle Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_psstyle;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion PSStyle
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace System.Management.Automation.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions to String type to calculate and render decorated content.
|
||||
/// </summary>
|
||||
public class StringDecorated
|
||||
{
|
||||
private readonly bool _isDecorated;
|
||||
private readonly string _text;
|
||||
private string? _plaintextcontent;
|
||||
|
||||
private string PlainText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_plaintextcontent == null)
|
||||
{
|
||||
_plaintextcontent = ValueStringDecorated.AnsiRegex.Replace(_text, string.Empty);
|
||||
}
|
||||
|
||||
return _plaintextcontent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StringDecorated"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The input string.</param>
|
||||
public StringDecorated(string text)
|
||||
{
|
||||
_text = text;
|
||||
_isDecorated = text.Contains(ValueStringDecorated.ESC);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the string contains decoration.
|
||||
/// </summary>
|
||||
/// <returns>Boolean if the string contains decoration.</returns>
|
||||
public bool IsDecorated => _isDecorated;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of content sans escape sequences.
|
||||
/// </summary>
|
||||
/// <returns>Length of content sans escape sequences.</returns>
|
||||
public int ContentLength => PlainText.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Render the decorarted string using automatic output rendering.
|
||||
/// </summary>
|
||||
/// <returns>Rendered string based on automatic output rendering.</returns>
|
||||
public override string ToString() => _isDecorated ? ToString(OutputRendering.Automatic) : _text;
|
||||
|
||||
/// <summary>
|
||||
/// Return string representation of content depending on output rendering mode.
|
||||
/// </summary>
|
||||
/// <param name="outputRendering">Specify how to render the text content.</param>
|
||||
/// <returns>Rendered string based on outputRendering.</returns>
|
||||
public string ToString(OutputRendering outputRendering)
|
||||
{
|
||||
if (!_isDecorated)
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
if (outputRendering == OutputRendering.Automatic)
|
||||
{
|
||||
outputRendering = OutputRendering.Ansi;
|
||||
if (PSStyle.Instance.OutputRendering == OutputRendering.PlainText)
|
||||
{
|
||||
outputRendering = OutputRendering.PlainText;
|
||||
}
|
||||
}
|
||||
|
||||
if (outputRendering == OutputRendering.PlainText)
|
||||
{
|
||||
return PlainText;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ValueStringDecorated
|
||||
{
|
||||
internal const char ESC = '\x1b';
|
||||
private readonly bool _isDecorated;
|
||||
private readonly string _text;
|
||||
private string? _plaintextcontent;
|
||||
|
||||
private string PlainText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_plaintextcontent == null)
|
||||
{
|
||||
_plaintextcontent = AnsiRegex.Replace(_text, string.Empty);
|
||||
}
|
||||
|
||||
return _plaintextcontent;
|
||||
}
|
||||
}
|
||||
|
||||
// replace regex with .NET 6 API once available
|
||||
internal static readonly Regex AnsiRegex = new Regex(@"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])", RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ValueStringDecorated"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="text">The input string.</param>
|
||||
public ValueStringDecorated(string text)
|
||||
{
|
||||
_text = text;
|
||||
_isDecorated = text.Contains(ESC);
|
||||
_plaintextcontent = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the string contains decoration.
|
||||
/// </summary>
|
||||
/// <returns>Boolean if the string contains decoration.</returns>
|
||||
public bool IsDecorated => _isDecorated;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of content sans escape sequences.
|
||||
/// </summary>
|
||||
/// <returns>Length of content sans escape sequences.</returns>
|
||||
public int ContentLength => PlainText.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Render the decorarted string using automatic output rendering.
|
||||
/// </summary>
|
||||
/// <returns>Rendered string based on automatic output rendering.</returns>
|
||||
public override string ToString() => _isDecorated ? ToString(OutputRendering.Automatic) : _text;
|
||||
|
||||
/// <summary>
|
||||
/// Return string representation of content depending on output rendering mode.
|
||||
/// </summary>
|
||||
/// <param name="outputRendering">Specify how to render the text content.</param>
|
||||
/// <returns>Rendered string based on outputRendering.</returns>
|
||||
public string ToString(OutputRendering outputRendering)
|
||||
{
|
||||
if (!_isDecorated)
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
if (outputRendering == OutputRendering.Automatic)
|
||||
{
|
||||
outputRendering = OutputRendering.Ansi;
|
||||
if (PSStyle.Instance.OutputRendering == OutputRendering.PlainText)
|
||||
{
|
||||
outputRendering = OutputRendering.PlainText;
|
||||
}
|
||||
}
|
||||
|
||||
if (outputRendering == OutputRendering.PlainText)
|
||||
{
|
||||
return PlainText;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,6 +222,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
internal override void WriteLine(string s)
|
||||
{
|
||||
CheckStopProcessing();
|
||||
|
||||
// delegate the action to the helper,
|
||||
// that will properly break the string into
|
||||
// screen lines
|
||||
@@ -351,6 +352,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
#if TEST_MULTICELL_ON_SINGLE_CELL_LOCALE
|
||||
s = ((DisplayCellsTest)this._displayCellsPSHost).GenerateTestString(s);
|
||||
#endif
|
||||
|
||||
switch (this.WriteStream)
|
||||
{
|
||||
case WriteStreamType.Error:
|
||||
|
||||
@@ -126,6 +126,9 @@ namespace System.Management.Automation
|
||||
new ExperimentalFeature(
|
||||
name: "PSSubsystemPluginModel",
|
||||
description: "A plugin model for registering and un-registering PowerShell subsystems"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSAnsiRendering",
|
||||
description: "Enable $PSStyle variable to control ANSI rendering of strings"),
|
||||
};
|
||||
EngineExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(engineFeatures);
|
||||
|
||||
|
||||
@@ -4442,6 +4442,13 @@ end {
|
||||
new SessionStateVariableEntry(SpecialVariables.FirstToken, null, string.Empty),
|
||||
new SessionStateVariableEntry(SpecialVariables.StackTrace, null, string.Empty),
|
||||
|
||||
// Variable which controls the output rendering
|
||||
new SessionStateVariableEntry(
|
||||
SpecialVariables.PSStyle,
|
||||
PSStyle.Instance,
|
||||
RunspaceInit.PSStyleDescription,
|
||||
ScopedItemOptions.None),
|
||||
|
||||
// Variable which controls the encoding for piping data to a NativeCommand
|
||||
new SessionStateVariableEntry(
|
||||
SpecialVariables.OutputEncoding,
|
||||
|
||||
@@ -32,6 +32,10 @@ namespace System.Management.Automation
|
||||
|
||||
internal static readonly VariablePath OFSVarPath = new VariablePath(OFS);
|
||||
|
||||
internal const string PSStyle = "PSStyle";
|
||||
|
||||
internal static readonly VariablePath PSStyleVarPath = new VariablePath(PSStyle);
|
||||
|
||||
internal const string OutputEncoding = "OutputEncoding";
|
||||
|
||||
internal static readonly VariablePath OutputEncodingVarPath = new VariablePath(OutputEncoding);
|
||||
|
||||
@@ -1787,6 +1787,107 @@ namespace System.Management.Automation
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool ShouldOutputPlainText(bool isHost, bool? supportsVirtualTerminal)
|
||||
{
|
||||
var outputRendering = OutputRendering.Ansi;
|
||||
|
||||
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
if (supportsVirtualTerminal != false)
|
||||
{
|
||||
switch (PSStyle.Instance.OutputRendering)
|
||||
{
|
||||
case OutputRendering.Automatic:
|
||||
outputRendering = OutputRendering.Ansi;
|
||||
break;
|
||||
case OutputRendering.Host:
|
||||
outputRendering = isHost ? OutputRendering.Ansi : OutputRendering.PlainText;
|
||||
break;
|
||||
default:
|
||||
outputRendering = PSStyle.Instance.OutputRendering;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputRendering == OutputRendering.PlainText;
|
||||
}
|
||||
|
||||
internal static string GetOutputString(string s, bool isHost, bool? supportsVirtualTerminal = null, bool isOutputRedirected = false)
|
||||
{
|
||||
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
var sd = new ValueStringDecorated(s);
|
||||
|
||||
if (sd.IsDecorated)
|
||||
{
|
||||
var outputRendering = OutputRendering.Ansi;
|
||||
if (InternalTestHooks.BypassOutputRedirectionCheck)
|
||||
{
|
||||
isOutputRedirected = false;
|
||||
}
|
||||
|
||||
if (isOutputRedirected || ShouldOutputPlainText(isHost, supportsVirtualTerminal))
|
||||
{
|
||||
outputRendering = OutputRendering.PlainText;
|
||||
}
|
||||
|
||||
s = sd.ToString(outputRendering);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
internal enum FormatStyle
|
||||
{
|
||||
Reset,
|
||||
FormatAccent,
|
||||
ErrorAccent,
|
||||
Error,
|
||||
Warning,
|
||||
Verbose,
|
||||
Debug,
|
||||
}
|
||||
|
||||
internal static string GetFormatStyleString(FormatStyle formatStyle)
|
||||
{
|
||||
// redirected console gets plaintext output to preserve existing behavior
|
||||
if (!InternalTestHooks.BypassOutputRedirectionCheck &&
|
||||
((PSStyle.Instance.OutputRendering == OutputRendering.PlainText) ||
|
||||
(formatStyle == FormatStyle.Error && Console.IsErrorRedirected) ||
|
||||
(formatStyle != FormatStyle.Error && Console.IsOutputRedirected)))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
PSStyle psstyle = PSStyle.Instance;
|
||||
switch (formatStyle)
|
||||
{
|
||||
case FormatStyle.Reset:
|
||||
return psstyle.Reset;
|
||||
case FormatStyle.FormatAccent:
|
||||
return psstyle.Formatting.FormatAccent;
|
||||
case FormatStyle.ErrorAccent:
|
||||
return psstyle.Formatting.ErrorAccent;
|
||||
case FormatStyle.Error:
|
||||
return psstyle.Formatting.Error;
|
||||
case FormatStyle.Warning:
|
||||
return psstyle.Formatting.Warning;
|
||||
case FormatStyle.Verbose:
|
||||
return psstyle.Formatting.Verbose;
|
||||
case FormatStyle.Debug:
|
||||
return psstyle.Formatting.Debug;
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1970,6 +2071,7 @@ namespace System.Management.Automation.Internal
|
||||
internal static bool BypassAppLockerPolicyCaching;
|
||||
internal static bool BypassOnlineHelpRetrieval;
|
||||
internal static bool ForcePromptForChoiceDefaultOption;
|
||||
internal static bool BypassOutputRedirectionCheck;
|
||||
|
||||
// Stop/Restart/Rename Computer tests
|
||||
internal static bool TestStopComputer;
|
||||
|
||||
@@ -619,6 +619,16 @@ namespace System.Management.Automation.Host
|
||||
}
|
||||
|
||||
resultText = resultText.TrimEnd();
|
||||
|
||||
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
|
||||
{
|
||||
var text = new ValueStringDecorated(resultText);
|
||||
if (text.IsDecorated)
|
||||
{
|
||||
resultText = text.ToString(OutputRendering.PlainText);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (TranscriptionOption transcript in TranscriptionData.Transcripts.Prepend<TranscriptionOption>(TranscriptionData.SystemTranscript))
|
||||
{
|
||||
if (transcript != null)
|
||||
|
||||
@@ -153,6 +153,9 @@
|
||||
<data name="OutputEncodingDescription" xml:space="preserve">
|
||||
<value>The text encoding used when piping text to a native executable file</value>
|
||||
</data>
|
||||
<data name="PSStyleDescription" xml:space="preserve">
|
||||
<value>Configuration controlling how text is rendered.</value>
|
||||
</data>
|
||||
<data name="PSEmailServerDescription" xml:space="preserve">
|
||||
<value>Variable to contain the name of the email server. This can be used instead of the HostName parameter in the Send-MailMessage cmdlet.</value>
|
||||
</data>
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'OutputRendering tests' {
|
||||
BeforeAll {
|
||||
$PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRendering')))
|
||||
$th = New-TestHost
|
||||
$rs = [runspacefactory]::Createrunspace($th)
|
||||
$rs.open()
|
||||
$ps = [powershell]::Create()
|
||||
$ps.Runspace = $rs
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$PSDefaultParameterValues.Remove('It:Skip')
|
||||
}
|
||||
|
||||
BeforeEach {
|
||||
if ($null -ne $PSStyle) {
|
||||
$oldOutputRendering = $PSStyle.OutputRendering
|
||||
}
|
||||
}
|
||||
|
||||
AfterEach {
|
||||
if ($null -ne $PSStyle) {
|
||||
$PSStyle.OutputRendering = $oldOutputRendering
|
||||
}
|
||||
|
||||
$ps.Commands.Clear()
|
||||
}
|
||||
|
||||
It 'OutputRendering works for "<outputRendering>" to the host' -TestCases @(
|
||||
@{ outputRendering = 'automatic'; ansi = $true }
|
||||
@{ outputRendering = 'host' ; ansi = $true }
|
||||
@{ outputRendering = 'ansi' ; ansi = $true }
|
||||
@{ outputRendering = 'plaintext'; ansi = $false }
|
||||
) {
|
||||
param($outputRendering, $ansi)
|
||||
|
||||
$out = pwsh -noprofile -command "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassOutputRedirectionCheck', `$true); `$PSStyle.OutputRendering = '$outputRendering'; write-host '$($PSStyle.Foreground.Green)hello'"
|
||||
|
||||
if ($ansi) {
|
||||
$out | Should -BeLike "*`e*" -Because ($out | Format-Hex | Out-String)
|
||||
}
|
||||
else {
|
||||
$out | Should -Not -BeLike "*`e*" -Because ($out | Format-Hex | Out-String)
|
||||
}
|
||||
}
|
||||
|
||||
It 'OutputRendering works for "<outputRendering>" to the pipeline' -TestCases @(
|
||||
@{ outputRendering = 'automatic'; ansi = $true }
|
||||
@{ outputRendering = 'host' ; ansi = $false }
|
||||
@{ outputRendering = 'ansi' ; ansi = $true }
|
||||
@{ outputRendering = 'plaintext'; ansi = $false }
|
||||
) {
|
||||
param($outputRendering, $ansi)
|
||||
|
||||
$PSStyle.OutputRendering = $outputRendering
|
||||
$out = "$($PSStyle.Foreground.Green)hello" | Out-String
|
||||
|
||||
if ($ansi) {
|
||||
$out | Should -BeLike "*`e*" -Because ($out | Format-Hex | Out-String)
|
||||
}
|
||||
else {
|
||||
$out | Should -Not -BeLike "*`e*" -Because ($out | Format-Hex | Out-String)
|
||||
}
|
||||
}
|
||||
|
||||
# Error isn't covered here because it has custom formatting
|
||||
It 'OutputRendering is correct for <stream>' -TestCases @(
|
||||
@{ stream = 'Verbose' }
|
||||
@{ stream = 'Debug' }
|
||||
@{ stream = 'Warning' }
|
||||
) {
|
||||
param($stream)
|
||||
|
||||
if ($stream -ne 'Warning')
|
||||
{
|
||||
$switch = "-$stream"
|
||||
}
|
||||
|
||||
$out = pwsh -noprofile -command "[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassOutputRedirectionCheck', `$true); write-$stream $switch 'hello'"
|
||||
$out | Should -BeExactly "$($PSStyle.Formatting.$stream)$($stream.ToUpper()): hello"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'Tests for $PSStyle automatic variable' {
|
||||
BeforeAll {
|
||||
$PSDefaultParameterValues.Add('It:Skip', (-not $EnabledExperimentalFeatures.Contains('PSAnsiRendering')))
|
||||
$styleDefaults = @{
|
||||
Reset = "`e[0m"
|
||||
BlinkOff = "`e[5m"
|
||||
Blink = "`e[25m"
|
||||
BoldOff = "`e[22m"
|
||||
Bold = "`e[1m"
|
||||
HiddenOff = "`e[28m"
|
||||
Hidden = "`e[8m"
|
||||
ReverseOff = "`e[27m"
|
||||
Reverse = "`e[7m"
|
||||
ItalicOff = "`e[23m"
|
||||
Italic = "`e[3m"
|
||||
UnderlineOff = "`e[24m"
|
||||
Underline = "`e[4m"
|
||||
}
|
||||
|
||||
$formattingDefaults = @{
|
||||
FormatAccent = "`e[32;1m"
|
||||
ErrorAccent = "`e[36;1m"
|
||||
Error = "`e[31;1m"
|
||||
Debug = "`e[33;1m"
|
||||
Verbose = "`e[33;1m"
|
||||
Warning = "`e[33;1m"
|
||||
}
|
||||
|
||||
$foregroundDefaults = @{
|
||||
Black = "`e[30m"
|
||||
White = "`e[37m"
|
||||
DarkGray = "`e[90m"
|
||||
LightGray = "`e[97m"
|
||||
Red = "`e[31m"
|
||||
LightRed = "`e[91m"
|
||||
Magenta = "`e[35m"
|
||||
LightMagenta = "`e[95m"
|
||||
Blue = "`e[34m"
|
||||
LightBlue = "`e[94m"
|
||||
Cyan = "`e[36m"
|
||||
LightCyan = "`e[96m"
|
||||
Green = "`e[32m"
|
||||
LightGreen = "`e[92m"
|
||||
Yellow = "`e[33m"
|
||||
LightYellow = "`e[93m"
|
||||
}
|
||||
|
||||
$backgroundDefaults = @{
|
||||
Black = "`e[40m"
|
||||
White = "`e[47m"
|
||||
DarkGray = "`e[100m"
|
||||
LightGray = "`e[107m"
|
||||
Red = "`e[41m"
|
||||
LightRed = "`e[101m"
|
||||
Magenta = "`e[45m"
|
||||
LightMagenta = "`e[105m"
|
||||
Blue = "`e[44m"
|
||||
LightBlue = "`e[104m"
|
||||
Cyan = "`e[46m"
|
||||
LightCyan = "`e[106m"
|
||||
Green = "`e[42m"
|
||||
LightGreen = "`e[102m"
|
||||
Yellow = "`e[43m"
|
||||
LightYellow = "`e[103m"
|
||||
}
|
||||
|
||||
function Get-TestCases($hashtable) {
|
||||
$testcases = [System.Collections.Generic.List[hashtable]]::new()
|
||||
foreach ($key in $hashtable.Keys) {
|
||||
$testcases.Add(
|
||||
@{ Key = $key; Value = $hashtable[$key] }
|
||||
)
|
||||
}
|
||||
|
||||
return $testcases
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$PSDefaultParameterValues.Remove('It:Skip')
|
||||
}
|
||||
|
||||
It '$PSStyle has correct default for OutputRendering' {
|
||||
$PSStyle | Should -Not -BeNullOrEmpty
|
||||
$PSStyle.OutputRendering | Should -BeExactly 'Automatic'
|
||||
}
|
||||
|
||||
It '$PSStyle has correct defaults for style <key>' -TestCases (Get-TestCases $styleDefaults) {
|
||||
param($key, $value)
|
||||
|
||||
$PSStyle.$key | Should -BeExactly $value
|
||||
}
|
||||
|
||||
It '$PSStyle.Formatting has correct default for <key>' -TestCases (Get-TestCases $formattingDefaults) {
|
||||
param($key, $value)
|
||||
|
||||
$PSStyle.Formatting.$key | Should -BeExactly $value
|
||||
}
|
||||
|
||||
It '$PSStyle.Foreground has correct default for <key>' -TestCases (Get-TestCases $foregroundDefaults) {
|
||||
param($key, $value)
|
||||
|
||||
$PSStyle.Foreground.$key | Should -BeExactly $value
|
||||
}
|
||||
|
||||
It '$PSStyle.Background has correct default for <key>' -TestCases (Get-TestCases $backgroundDefaults) {
|
||||
param($key, $value)
|
||||
|
||||
$PSStyle.Background.$key | Should -BeExactly $value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user