From d045b508f41e2c3fe9763768a5adfc58a5439907 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 26 Sep 2023 15:51:45 -0700 Subject: [PATCH] Choose the inline prediction color based on the environment (#3808) --- PSReadLine/Cmdlets.cs | 55 ++++++++++++++++++++++++++--------- PSReadLine/PlatformWindows.cs | 5 +--- PSReadLine/ReadLine.cs | 2 -- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/PSReadLine/Cmdlets.cs b/PSReadLine/Cmdlets.cs index 22218560..7fecf4b4 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,40 @@ 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; + + // 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. + DefaultListPredictionTooltipColor = DefaultInlinePredictionColor; + DefaultAddToHistoryHandler = s => PSConsoleReadLine.GetDefaultAddToHistoryOption(s); + } + public PSConsoleReadLineOptions(string hostName, bool usingLegacyConsole) { ResetColors(); @@ -285,8 +316,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 +335,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 +584,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 +859,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 +931,7 @@ protected override void EndProcessing() } } - private readonly Lazy _dynamicParameters = - new Lazy(CreateDynamicParametersResult); + private readonly Lazy _dynamicParameters = new(CreateDynamicParametersResult); private static RuntimeDefinedParameterDictionary CreateDynamicParametersResult() { @@ -1027,7 +1054,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 86b4a73c..ef3a7eae 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(); } diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 2da14ff7..c06120db 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