From de3e28dbf83c28e5e8dd3847777ab29b1fc26100 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 20 Sep 2023 17:57:19 -0700 Subject: [PATCH 1/2] Choose the inline prediction color based on the environment --- PSReadLine/Cmdlets.cs | 49 +++++++++++++++++++++++++---------- PSReadLine/PlatformWindows.cs | 5 +--- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/PSReadLine/Cmdlets.cs b/PSReadLine/Cmdlets.cs index 222185602..17f33d2f5 100644 --- a/PSReadLine/Cmdlets.cs +++ b/PSReadLine/Cmdlets.cs @@ -95,17 +95,14 @@ public class PSConsoleReadLineOptions // Find the most suitable color using https://stackoverflow.com/a/33206814 // Default prediction color settings: - // - use FG color 'dim white italic' for the inline-view suggestion text // - use FG color 'yellow' for the list-view suggestion text // - use BG color 'dark black' for the selected list-view suggestion text - public const string DefaultInlinePredictionColor = "\x1b[97;2;3m"; public const string DefaultListPredictionColor = "\x1b[33m"; public const string DefaultListPredictionSelectedColor = "\x1b[48;5;238m"; - public const string DefaultListPredictionTooltipColor = "\x1b[97;2;3m"; - public static EditMode DefaultEditMode = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? EditMode.Windows - : EditMode.Emacs; + public static readonly string DefaultInlinePredictionColor; + public static readonly string DefaultListPredictionTooltipColor; + public static readonly EditMode DefaultEditMode; public const string DefaultContinuationPrompt = ">> "; @@ -166,6 +163,34 @@ public class PSConsoleReadLineOptions /// public const int DefaultAnsiEscapeTimeout = 100; + static PSConsoleReadLineOptions() + { + // For inline-view suggestion text, we use the new FG color 'dim white italic' when possible, because it provides + // sufficient contrast in terminals that don't use a pure black background (like VSCode terminal). + // However, on Windows 10 and Windows Server, the ConHost doesn't support font effect VT sequences, such as 'dim' + // and 'italic', so we need to use the old FG color 'dark black' as in the v2.2.6. + const string newInlinePredictionColor = "\x1b[97;2;3m"; + const string oldInlinePredictionColor = "\x1b[38;5;238m"; + + ColorSetters = null; + DefaultEditMode = EditMode.Emacs; + DefaultInlinePredictionColor = newInlinePredictionColor; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + DefaultEditMode = EditMode.Windows; + DefaultInlinePredictionColor = + Environment.OSVersion.Version.Build >= 22621 // on Windows 11 22H2 or newer versions + || Environment.GetEnvironmentVariable("WT_SESSION") is not null // in Windows Terminal + ? newInlinePredictionColor + : oldInlinePredictionColor; + } + + // Use the same color for the list prediction tooltips. + DefaultListPredictionTooltipColor = DefaultInlinePredictionColor; + DefaultAddToHistoryHandler = s => PSConsoleReadLine.GetDefaultAddToHistoryOption(s); + } + public PSConsoleReadLineOptions(string hostName, bool usingLegacyConsole) { ResetColors(); @@ -285,8 +310,7 @@ public object ContinuationPromptColor /// or added to memory only, or added to both memory and history file. /// public Func AddToHistoryHandler { get; set; } - public static readonly Func DefaultAddToHistoryHandler = - s => PSConsoleReadLine.GetDefaultAddToHistoryOption(s); + public static readonly Func DefaultAddToHistoryHandler; /// /// This handler is called from ValidateAndAcceptLine. @@ -305,7 +329,6 @@ public object ContinuationPromptColor /// odd things with script blocks, we create a white-list of commands /// that do invoke the script block - this covers the most useful cases. /// - [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public HashSet CommandsToValidateScriptBlockArguments { get; set; } /// @@ -555,7 +578,7 @@ internal void ResetColors() SelectionColor = VTColorUtils.AsEscapeSequence(bg, fg); } - private static Dictionary> ColorSetters = null; + private static Dictionary> ColorSetters; internal void SetColor(string property, object value) { @@ -830,7 +853,6 @@ public class ChangePSReadLineKeyHandlerCommandBase : PSCmdlet [Parameter(Position = 0, Mandatory = true)] [Alias("Key")] [ValidateNotNullOrEmpty] - [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] public string[] Chord { get; set; } [Parameter] @@ -903,8 +925,7 @@ protected override void EndProcessing() } } - private readonly Lazy _dynamicParameters = - new Lazy(CreateDynamicParametersResult); + private readonly Lazy _dynamicParameters = new(CreateDynamicParametersResult); private static RuntimeDefinedParameterDictionary CreateDynamicParametersResult() { @@ -1027,7 +1048,7 @@ public static class VTColorUtils public const ConsoleColor UnknownColor = (ConsoleColor) (-1); private static readonly Dictionary ConsoleColors = - new Dictionary(StringComparer.OrdinalIgnoreCase) + new(StringComparer.OrdinalIgnoreCase) { {"Black", ConsoleColor.Black}, {"DarkBlue", ConsoleColor.DarkBlue}, diff --git a/PSReadLine/PlatformWindows.cs b/PSReadLine/PlatformWindows.cs index 86b4a73c5..ef3a7eae5 100644 --- a/PSReadLine/PlatformWindows.cs +++ b/PSReadLine/PlatformWindows.cs @@ -637,10 +637,7 @@ internal static extern int NtQueryInformationProcess( internal static int GetParentPid(Process process) { // (This is how ProcessCodeMethods in pwsh does it.) - PROCESS_BASIC_INFORMATION pbi; - int size; - var res = NtQueryInformationProcess(process.Handle, 0, out pbi, Marshal.SizeOf(), out size); - + var res = NtQueryInformationProcess(process.Handle, 0, out PROCESS_BASIC_INFORMATION pbi, Marshal.SizeOf(), out _); return res != 0 ? InvalidProcessId : pbi.InheritedFromUniqueProcessId.ToInt32(); } From b685671aef668ebe998e709a6478d797fc80d3f4 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 21 Sep 2023 11:17:00 -0700 Subject: [PATCH 2/2] Use the new color in test runs --- PSReadLine/Cmdlets.cs | 16 +++++++++++----- PSReadLine/ReadLine.cs | 2 -- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/PSReadLine/Cmdlets.cs b/PSReadLine/Cmdlets.cs index 17f33d2f5..7fecf4b4e 100644 --- a/PSReadLine/Cmdlets.cs +++ b/PSReadLine/Cmdlets.cs @@ -179,11 +179,17 @@ static PSConsoleReadLineOptions() if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { DefaultEditMode = EditMode.Windows; - DefaultInlinePredictionColor = - Environment.OSVersion.Version.Build >= 22621 // on Windows 11 22H2 or newer versions - || Environment.GetEnvironmentVariable("WT_SESSION") is not null // in Windows Terminal - ? newInlinePredictionColor - : oldInlinePredictionColor; + + // Our tests expect that the default inline-view color is set to the new color, so we configure + // the color based on system environment only if we are not in test runs. + if (AppDomain.CurrentDomain.FriendlyName is not "PSReadLine.Tests") + { + DefaultInlinePredictionColor = + Environment.OSVersion.Version.Build >= 22621 // on Windows 11 22H2 or newer versions + || Environment.GetEnvironmentVariable("WT_SESSION") is not null // in Windows Terminal + ? newInlinePredictionColor + : oldInlinePredictionColor; + } } // Use the same color for the list prediction tooltips. diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 2da14ff75..c06120dbf 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -25,8 +25,6 @@ namespace Microsoft.PowerShell { - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")] class ExitException : Exception { } public partial class PSConsoleReadLine : IPSConsoleReadLineMockableMethods