From fe5096dceb7bee433cd9875fe3b0cf03cfaff916 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Wed, 7 Apr 2021 00:28:55 +0200 Subject: [PATCH] Fixes color system detection bug If an application runs on Windows 10.0.15063 or above, on a runtime prior to net5.0, the color system detection will fail and fall back to 8-bit color support. The reason for this is because the behavior of Environment.OSVersion.Version differs between runtimes. Unless you're running on net5.0, both the major and build version components will not reflect those in the actual Windows version. --- .../Internal/Colors/ColorSystemDetector.cs | 68 +++++++++++++++---- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/Spectre.Console/Internal/Colors/ColorSystemDetector.cs b/src/Spectre.Console/Internal/Colors/ColorSystemDetector.cs index c494500..597af4b 100644 --- a/src/Spectre.Console/Internal/Colors/ColorSystemDetector.cs +++ b/src/Spectre.Console/Internal/Colors/ColorSystemDetector.cs @@ -1,41 +1,47 @@ using System; using System.Runtime.InteropServices; + +#if !NET5_0 using System.Text.RegularExpressions; +#endif namespace Spectre.Console { internal static class ColorSystemDetector { // Adapted from https://github.com/willmcgugan/rich/blob/f0c29052c22d1e49579956a9207324d9072beed7/rich/console.py#L391 - // which I think is battletested enough to trust. public static ColorSystem Detect(bool supportsAnsi) { + // No colors? if (Environment.GetEnvironmentVariables().Contains("NO_COLOR")) { - // No colors supported return ColorSystem.NoColors; } + // Windows? if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (!supportsAnsi) { + // Figure out what we should do here. + // Does really all Windows terminals support + // eight-bit colors? Probably not... return ColorSystem.EightBit; } - var os = Environment.OSVersion; - var major = os.Version.Major; - var build = os.Version.Build; - - if (major > 10) + // Windows 10.0.15063 and above support true color, + // and we can probably assume that the next major + // version of Windows will support true color as well. + if (GetWindowsVersionInformation(out var major, out var build)) { - // Future Patrik will thank me. - return ColorSystem.TrueColor; - } - - if (major == 10 && build >= 15063) - { - return ColorSystem.TrueColor; + if (major == 10 && build >= 15063) + { + return ColorSystem.TrueColor; + } + else if (major > 10) + { + return ColorSystem.TrueColor; + } } } else @@ -51,7 +57,41 @@ namespace Spectre.Console } } + // Should we default to eight-bit colors? return ColorSystem.EightBit; } + + // See https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/environment-osversion-returns-correct-version + private static bool GetWindowsVersionInformation(out int major, out int build) + { + major = 0; + build = 0; + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return false; + } + +#if NET5_0 + // The reason we're not always using this, is because it + // will return wrong values on other runtimes than net5.0 + var version = Environment.OSVersion.Version; + major = version.Major; + build = version.Build; + return true; +#else + var regex = new Regex("Microsoft Windows (?'major'[0-9]*).(?'minor'[0-9]*).(?'build'[0-9]*)\\s*$"); + var match = regex.Match(RuntimeInformation.OSDescription); + if (match.Success && int.TryParse(match.Groups["major"].Value, out major)) + { + if (int.TryParse(match.Groups["build"].Value, out build)) + { + return true; + } + } + + return false; +#endif + } } }