From 7daea0a25c3cf954485abd47803e1c8bf6bdd6ef Mon Sep 17 00:00:00 2001 From: Will Fuqua Date: Tue, 23 Apr 2019 21:10:16 +0700 Subject: [PATCH] pull logic out of Program.cs There aren't any user-facing changes in this commit, just pulling logic out of Program.cs. All that remains in Program.cs is command line parsing. - The functions that wrote to the registry, the console, and the virtual terminal (--xterm) are now in their own files, implementing the `IConsoleTarget` interface - Move the utility method UIntToColor into ColorScheme, where it can be used as an indexer, e.g. myColorScheme[i] returns a System.Drawing.Color - The "export to INI" functionality is now in a "SchemeWriters" namespace; Parsers are now in a "SchemeParsers" namespace - Printing the color table is now in the ColorTable class. --- tools/ColorTool/ColorTool/ColorScheme.cs | 12 +- tools/ColorTool/ColorTool/ColorTable.cs | 232 ++++++++ tools/ColorTool/ColorTool/ConsoleAPI.cs | 5 +- .../ColorTool/ColorTool/ConsoleAttributes.cs | 3 +- .../ConsoleTargets/CurrentConsoleTarget.cs | 51 ++ .../ConsoleTargets/DefaultConsoleTarget.cs | 28 + .../ConsoleTargets/IConsoleTarget.cs | 15 + .../VirtualTerminalConsoleTarget.cs | 67 +++ tools/ColorTool/ColorTool/Program.cs | 499 +----------------- tools/ColorTool/ColorTool/Scheme.cs | 41 -- tools/ColorTool/ColorTool/SchemeManager.cs | 112 ++++ .../{ => SchemeParsers}/ISchemeParser.cs | 4 +- .../{ => SchemeParsers}/IniSchemeParser.cs | 8 +- .../{ => SchemeParsers}/JsonParser.cs | 13 +- .../{ => SchemeParsers}/XmlSchemeParser.cs | 8 +- .../SchemeWriters/IniSchemeWriter.cs | 66 +++ 16 files changed, 617 insertions(+), 547 deletions(-) create mode 100644 tools/ColorTool/ColorTool/ColorTable.cs create mode 100644 tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs create mode 100644 tools/ColorTool/ColorTool/ConsoleTargets/DefaultConsoleTarget.cs create mode 100644 tools/ColorTool/ColorTool/ConsoleTargets/IConsoleTarget.cs create mode 100644 tools/ColorTool/ColorTool/ConsoleTargets/VirtualTerminalConsoleTarget.cs delete mode 100644 tools/ColorTool/ColorTool/Scheme.cs create mode 100644 tools/ColorTool/ColorTool/SchemeManager.cs rename tools/ColorTool/ColorTool/{ => SchemeParsers}/ISchemeParser.cs (74%) rename tools/ColorTool/ColorTool/{ => SchemeParsers}/IniSchemeParser.cs (97%) rename tools/ColorTool/ColorTool/{ => SchemeParsers}/JsonParser.cs (94%) rename tools/ColorTool/ColorTool/{ => SchemeParsers}/XmlSchemeParser.cs (96%) create mode 100644 tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs diff --git a/tools/ColorTool/ColorTool/ColorScheme.cs b/tools/ColorTool/ColorTool/ColorScheme.cs index f930f31e5..507558f57 100644 --- a/tools/ColorTool/ColorTool/ColorScheme.cs +++ b/tools/ColorTool/ColorTool/ColorScheme.cs @@ -1,9 +1,10 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // using System; +using System.Drawing; using System.Linq; namespace ColorTool @@ -13,6 +14,15 @@ namespace ColorTool public uint[] colorTable = null; public ConsoleAttributes consoleAttributes; + public Color this[int index] => UIntToColor(colorTable[index]); + + private static Color UIntToColor(uint color) + { + byte r = (byte)(color >> 0); + byte g = (byte)(color >> 8); + byte b = (byte)(color >> 16); + return Color.FromArgb(r, g, b); + } public int CalculateIndex(uint value) => colorTable.Select((color, idx) => Tuple.Create(color, idx)) diff --git a/tools/ColorTool/ColorTool/ColorTable.cs b/tools/ColorTool/ColorTool/ColorTable.cs new file mode 100644 index 000000000..7f5e3742c --- /dev/null +++ b/tools/ColorTool/ColorTool/ColorTable.cs @@ -0,0 +1,232 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using System; + +namespace ColorTool +{ + class ColorTable + { + static int DARK_BLACK = 0; + static int DARK_BLUE = 1; + static int DARK_GREEN = 2; + static int DARK_CYAN = 3; + static int DARK_RED = 4; + static int DARK_MAGENTA = 5; + static int DARK_YELLOW = 6; + static int DARK_WHITE = 7; + static int BRIGHT_BLACK = 8; + static int BRIGHT_BLUE = 9; + static int BRIGHT_GREEN = 10; + static int BRIGHT_CYAN = 11; + static int BRIGHT_RED = 12; + static int BRIGHT_MAGENTA = 13; + static int BRIGHT_YELLOW = 14; + static int BRIGHT_WHITE = 15; + + // This is the order of colors when output by the table. + static int[] outputFgs = { + BRIGHT_WHITE , + DARK_BLACK , + BRIGHT_BLACK , + DARK_RED , + BRIGHT_RED , + DARK_GREEN , + BRIGHT_GREEN , + DARK_YELLOW , + BRIGHT_YELLOW , + DARK_BLUE , + BRIGHT_BLUE , + DARK_MAGENTA , + BRIGHT_MAGENTA , + DARK_CYAN , + BRIGHT_CYAN , + DARK_WHITE , + BRIGHT_WHITE + }; + + + static int[] saneBgs = { + DARK_BLACK , + DARK_RED , + DARK_GREEN , + DARK_YELLOW , + DARK_BLUE , + DARK_MAGENTA , + DARK_CYAN , + DARK_WHITE + }; + + + public static void PrintTable() + { + ConsoleColor[] colors = (ConsoleColor[])ConsoleColor.GetValues(typeof(ConsoleColor)); + // Save the current background and foreground colors. + ConsoleColor currentBackground = Console.BackgroundColor; + ConsoleColor currentForeground = Console.ForegroundColor; + string test = " gYw "; + string[] FGs = { + "m", + "1m", + "30m", + "1;30m", + "31m", + "1;31m", + "32m", + "1;32m", + "33m", + "1;33m", + "34m", + "1;34m", + "35m", + "1;35m", + "36m", + "1;36m", + "37m", + "1;37m" + }; + string[] BGs = { + "m", + "40m", + "41m", + "42m", + "43m", + "44m", + "45m", + "46m", + "47m" + }; + + Console.Write("\t"); + for (int bg = 0; bg < BGs.Length; bg++) + { + if (bg > 0) Console.Write(" "); + Console.Write(" "); + Console.Write(bg == 0 ? " " : BGs[bg]); + Console.Write(" "); + } + Console.WriteLine(); + + for (int fg = 0; fg < FGs.Length; fg++) + { + Console.ForegroundColor = currentForeground; + Console.BackgroundColor = currentBackground; + + if (fg >= 0) Console.Write(FGs[fg] + "\t"); + + if (fg == 0) Console.ForegroundColor = currentForeground; + else Console.ForegroundColor = colors[outputFgs[fg - 1]]; + + for (int bg = 0; bg < BGs.Length; bg++) + { + if (bg > 0) Console.Write(" "); + if (bg == 0) + Console.BackgroundColor = currentBackground; + else Console.BackgroundColor = colors[saneBgs[bg - 1]]; + Console.Write(test); + Console.BackgroundColor = currentBackground; + } + Console.Write("\n"); + + } + Console.Write("\n"); + + // Reset foreground and background colors + Console.ForegroundColor = currentForeground; + Console.BackgroundColor = currentBackground; + } + + public static void PrintTableWithVt() + { + // Save the current background and foreground colors. + string test = " gYw "; + string[] FGs = { + "m", + "1m", + "30m", + "1;30m", + "31m", + "1;31m", + "32m", + "1;32m", + "33m", + "1;33m", + "34m", + "1;34m", + "35m", + "1;35m", + "36m", + "1;36m", + "37m", + "1;37m" + }; + string[] BGs = { + "m", + "40m", + "41m", + "42m", + "43m", + "44m", + "45m", + "46m", + "47m" + }; + + Console.Write("\t"); + for (int bg = 0; bg < BGs.Length; bg++) + { + if (bg > 0) Console.Write(" "); + Console.Write(" "); + Console.Write(bg == 0 ? " " : BGs[bg]); + Console.Write(" "); + } + Console.WriteLine(); + + for (int fg = 0; fg < FGs.Length; fg++) + { + Console.Write("\x1b[m"); + + if (fg >= 0) + { + Console.Write(FGs[fg] + "\t"); + } + + if (fg == 0) + { + Console.Write("\x1b[39m"); + } + else + { + Console.Write("\x1b[" + FGs[fg]); + } + + for (int bg = 0; bg < BGs.Length; bg++) + { + if (bg > 0) + { + Console.Write(" "); + } + if (bg == 0) + { + Console.Write("\x1b[49m"); + } + else + { + Console.Write("\x1b[" + BGs[bg]); + } + + Console.Write(test); + Console.Write("\x1b[49m"); + } + Console.Write("\n"); + + } + Console.Write("\n"); + + // Reset foreground and background colors + Console.Write("\x1b[m"); + } + } +} diff --git a/tools/ColorTool/ColorTool/ConsoleAPI.cs b/tools/ColorTool/ColorTool/ConsoleAPI.cs index 3219d34e0..1f1c62309 100644 --- a/tools/ColorTool/ColorTool/ConsoleAPI.cs +++ b/tools/ColorTool/ColorTool/ConsoleAPI.cs @@ -1,5 +1,5 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // @@ -60,6 +60,9 @@ namespace ColorTool public static int STD_OUTPUT_HANDLE = -11; + + public static IntPtr GetStdOutputHandle() => GetStdHandle(STD_OUTPUT_HANDLE); + [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetStdHandle(int nStdHandle); diff --git a/tools/ColorTool/ColorTool/ConsoleAttributes.cs b/tools/ColorTool/ColorTool/ConsoleAttributes.cs index ac2d9bceb..17b5c7387 100644 --- a/tools/ColorTool/ColorTool/ConsoleAttributes.cs +++ b/tools/ColorTool/ColorTool/ConsoleAttributes.cs @@ -1,5 +1,5 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // @@ -12,6 +12,5 @@ namespace ColorTool public uint? popupForeground; public uint? popupBackground; - } } diff --git a/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs b/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs new file mode 100644 index 000000000..97a9c95ba --- /dev/null +++ b/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs @@ -0,0 +1,51 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using System; +using static ColorTool.ConsoleAPI; + +namespace ColorTool.ConsoleTargets +{ + /// + /// A console target that writes to the currently open console. + /// + class CurrentConsoleTarget : IConsoleTarget + { + public void ApplyColorScheme(ColorScheme colorScheme, bool quietMode) + { + CONSOLE_SCREEN_BUFFER_INFO_EX csbiex = CONSOLE_SCREEN_BUFFER_INFO_EX.Create(); + IntPtr hOut = GetStdOutputHandle(); + bool success = GetConsoleScreenBufferInfoEx(hOut, ref csbiex); + if (!success) + { + throw new InvalidOperationException("Could not obtain console screen buffer"); + } + + csbiex.srWindow.Bottom++; + for (int i = 0; i < 16; i++) + { + csbiex.ColorTable[i] = colorScheme.colorTable[i]; + } + if (colorScheme.consoleAttributes.background != null && colorScheme.consoleAttributes.foreground != null) + { + int fgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.foreground.Value); + int bgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.background.Value); + csbiex.wAttributes = (ushort)(fgidx | (bgidx << 4)); + } + if (colorScheme.consoleAttributes.popupBackground != null && colorScheme.consoleAttributes.popupForeground != null) + { + int fgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.popupForeground.Value); + int bgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.popupBackground.Value); + csbiex.wPopupAttributes = (ushort)(fgidx | (bgidx << 4)); + } + SetConsoleScreenBufferInfoEx(hOut, ref csbiex); + + if (!quietMode) + { + ColorTable.PrintTable(); + } + } + } +} diff --git a/tools/ColorTool/ColorTool/ConsoleTargets/DefaultConsoleTarget.cs b/tools/ColorTool/ColorTool/ConsoleTargets/DefaultConsoleTarget.cs new file mode 100644 index 000000000..bb3648701 --- /dev/null +++ b/tools/ColorTool/ColorTool/ConsoleTargets/DefaultConsoleTarget.cs @@ -0,0 +1,28 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using Microsoft.Win32; +using System; + +namespace ColorTool.ConsoleTargets +{ + /// + /// A console target that writes to the Windows registry to modify system defaults + /// + class DefaultConsoleTarget : IConsoleTarget + { + public void ApplyColorScheme(ColorScheme colorScheme, bool quietMode) + { + //TODO + RegistryKey consoleKey = Registry.CurrentUser.OpenSubKey("Console", true); + for (int i = 0; i < colorScheme.colorTable.Length; i++) + { + string valueName = "ColorTable" + (i < 10 ? "0" : "") + i; + consoleKey.SetValue(valueName, colorScheme.colorTable[i], RegistryValueKind.DWord); + } + Console.WriteLine(Resources.WroteToDefaults); + } + } +} diff --git a/tools/ColorTool/ColorTool/ConsoleTargets/IConsoleTarget.cs b/tools/ColorTool/ColorTool/ConsoleTargets/IConsoleTarget.cs new file mode 100644 index 000000000..a1a2b9d2a --- /dev/null +++ b/tools/ColorTool/ColorTool/ConsoleTargets/IConsoleTarget.cs @@ -0,0 +1,15 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +namespace ColorTool.ConsoleTargets +{ + /// + /// A console that can have a color scheme applied to it. + /// + interface IConsoleTarget + { + void ApplyColorScheme(ColorScheme colorScheme, bool quietMode); + } +} diff --git a/tools/ColorTool/ColorTool/ConsoleTargets/VirtualTerminalConsoleTarget.cs b/tools/ColorTool/ColorTool/ConsoleTargets/VirtualTerminalConsoleTarget.cs new file mode 100644 index 000000000..ea660ab16 --- /dev/null +++ b/tools/ColorTool/ColorTool/ConsoleTargets/VirtualTerminalConsoleTarget.cs @@ -0,0 +1,67 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using System; +using System.Drawing; +using static ColorTool.ConsoleAPI; + +namespace ColorTool.ConsoleTargets +{ + /// + /// A console target that writes to the currently open console, using VT sequences. + /// + class VirtualTerminalConsoleTarget : IConsoleTarget + { + // Use a Console index in to get a VT index out. + static readonly int[] VT_INDICIES = { + 0, // DARK_BLACK + 4, // DARK_BLUE + 2, // DARK_GREEN + 6, // DARK_CYAN + 1, // DARK_RED + 5, // DARK_MAGENTA + 3, // DARK_YELLOW + 7, // DARK_WHITE + 8+0, // BRIGHT_BLACK + 8+4, // BRIGHT_BLUE + 8+2, // BRIGHT_GREEN + 8+6, // BRIGHT_CYAN + 8+1, // BRIGHT_RED + 8+5, // BRIGHT_MAGENTA + 8+3, // BRIGHT_YELLOW + 8+7,// BRIGHT_WHITE + }; + + public void ApplyColorScheme(ColorScheme colorScheme, bool quietMode) + { + IntPtr hOut = GetStdOutputHandle(); + uint originalMode; + uint requestedMode; + bool succeeded = GetConsoleMode(hOut, out originalMode); + if (succeeded) + { + requestedMode = originalMode | (uint)ConsoleAPI.ConsoleOutputModes.ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(hOut, requestedMode); + } + + for (int i = 0; i < colorScheme.colorTable.Length; i++) + { + int vtIndex = VT_INDICIES[i]; + Color color = colorScheme[i]; + string s = $"\x1b]4;{vtIndex};rgb:{color.R:X}/{color.G:X}/{color.B:X}\x7"; + Console.Write(s); + } + if (!quietMode) + { + ColorTable.PrintTableWithVt(); + } + + if (succeeded) + { + SetConsoleMode(hOut, originalMode); + } + } + } +} diff --git a/tools/ColorTool/ColorTool/Program.cs b/tools/ColorTool/ColorTool/Program.cs index 3496d606d..36fe40fe3 100644 --- a/tools/ColorTool/ColorTool/Program.cs +++ b/tools/ColorTool/ColorTool/Program.cs @@ -1,110 +1,17 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // -using Microsoft.Win32; +using ColorTool.ConsoleTargets; +using ColorTool.SchemeWriters; using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using static ColorTool.ConsoleAPI; namespace ColorTool { class Program { - static int DARK_BLACK = 0; - static int DARK_BLUE = 1; - static int DARK_GREEN = 2; - static int DARK_CYAN = 3; - static int DARK_RED = 4; - static int DARK_MAGENTA = 5; - static int DARK_YELLOW = 6; - static int DARK_WHITE = 7; - static int BRIGHT_BLACK = 8; - static int BRIGHT_BLUE = 9; - static int BRIGHT_GREEN = 10; - static int BRIGHT_CYAN = 11; - static int BRIGHT_RED = 12; - static int BRIGHT_MAGENTA = 13; - static int BRIGHT_YELLOW = 14; - static int BRIGHT_WHITE = 15; - - static int[] saneFgs = { - DARK_BLACK , - DARK_RED , - DARK_GREEN , - DARK_YELLOW , - DARK_BLUE , - DARK_MAGENTA , - DARK_CYAN , - DARK_WHITE , - BRIGHT_BLACK , - BRIGHT_RED , - BRIGHT_GREEN , - BRIGHT_YELLOW , - BRIGHT_MAGENTA , - BRIGHT_BLUE , - BRIGHT_CYAN , - BRIGHT_WHITE - }; - - // This is the order of colors when output by the table. - static int[] outputFgs = { - BRIGHT_WHITE , - DARK_BLACK , - BRIGHT_BLACK , - DARK_RED , - BRIGHT_RED , - DARK_GREEN , - BRIGHT_GREEN , - DARK_YELLOW , - BRIGHT_YELLOW , - DARK_BLUE , - BRIGHT_BLUE , - DARK_MAGENTA , - BRIGHT_MAGENTA , - DARK_CYAN , - BRIGHT_CYAN , - DARK_WHITE , - BRIGHT_WHITE - }; - - static int[] saneBgs = { - DARK_BLACK , - DARK_RED , - DARK_GREEN , - DARK_YELLOW , - DARK_BLUE , - DARK_MAGENTA , - DARK_CYAN , - DARK_WHITE - }; - - // Use a Console index in to get a VT index out. - static int[] VT_INDICIES = { - 0, // DARK_BLACK - 4, // DARK_BLUE - 2, // DARK_GREEN - 6, // DARK_CYAN - 1, // DARK_RED - 5, // DARK_MAGENTA - 3, // DARK_YELLOW - 7, // DARK_WHITE - 8+0, // BRIGHT_BLACK - 8+4, // BRIGHT_BLUE - 8+2, // BRIGHT_GREEN - 8+6, // BRIGHT_CYAN - 8+1, // BRIGHT_RED - 8+5, // BRIGHT_MAGENTA - 8+3, // BRIGHT_YELLOW - 8+7,// BRIGHT_WHITE - }; - static bool quietMode = false; static bool reportErrors = false; static bool setDefaults = false; @@ -114,7 +21,7 @@ namespace ColorTool static void Usage() { Console.WriteLine(Resources.Usage, - string.Join($"{Environment.NewLine} ", GetParsers().Select(p => p.Name))); + string.Join($"{Environment.NewLine} ", SchemeManager.GetParsers().Select(p => p.Name))); } static void OutputUsage() @@ -129,368 +36,6 @@ namespace ColorTool Console.WriteLine($"colortool v{info.FileVersion}"); } - static void PrintTable() - { - ConsoleColor[] colors = (ConsoleColor[])ConsoleColor.GetValues(typeof(ConsoleColor)); - // Save the current background and foreground colors. - ConsoleColor currentBackground = Console.BackgroundColor; - ConsoleColor currentForeground = Console.ForegroundColor; - string test = " gYw "; - string[] FGs = { - "m", - "1m", - "30m", - "1;30m", - "31m", - "1;31m", - "32m", - "1;32m", - "33m", - "1;33m", - "34m", - "1;34m", - "35m", - "1;35m", - "36m", - "1;36m", - "37m", - "1;37m" - }; - string[] BGs = { - "m", - "40m", - "41m", - "42m", - "43m", - "44m", - "45m", - "46m", - "47m" - }; - - Console.Write("\t"); - for (int bg = 0; bg < BGs.Length; bg++) - { - if (bg > 0) Console.Write(" "); - Console.Write(" "); - Console.Write(bg == 0 ? " " : BGs[bg]); - Console.Write(" "); - } - Console.WriteLine(); - - for (int fg = 0; fg < FGs.Length; fg++) - { - Console.ForegroundColor = currentForeground; - Console.BackgroundColor = currentBackground; - - if (fg >= 0) Console.Write(FGs[fg] + "\t"); - - if (fg == 0) Console.ForegroundColor = currentForeground; - else Console.ForegroundColor = colors[outputFgs[fg - 1]]; - - for (int bg = 0; bg < BGs.Length; bg++) - { - if (bg > 0) Console.Write(" "); - if (bg == 0) - Console.BackgroundColor = currentBackground; - else Console.BackgroundColor = colors[saneBgs[bg - 1]]; - Console.Write(test); - Console.BackgroundColor = currentBackground; - } - Console.Write("\n"); - - } - Console.Write("\n"); - - // Reset foreground and background colors - Console.ForegroundColor = currentForeground; - Console.BackgroundColor = currentBackground; - } - - static void PrintTableWithVt() - { - // Save the current background and foreground colors. - string test = " gYw "; - string[] FGs = { - "m", - "1m", - "30m", - "1;30m", - "31m", - "1;31m", - "32m", - "1;32m", - "33m", - "1;33m", - "34m", - "1;34m", - "35m", - "1;35m", - "36m", - "1;36m", - "37m", - "1;37m" - }; - string[] BGs = { - "m", - "40m", - "41m", - "42m", - "43m", - "44m", - "45m", - "46m", - "47m" - }; - - Console.Write("\t"); - for (int bg = 0; bg < BGs.Length; bg++) - { - if (bg > 0) Console.Write(" "); - Console.Write(" "); - Console.Write(bg == 0 ? " " : BGs[bg]); - Console.Write(" "); - } - Console.WriteLine(); - - for (int fg = 0; fg < FGs.Length; fg++) - { - Console.Write("\x1b[m"); - - if (fg >= 0) - { - Console.Write(FGs[fg] + "\t"); - } - - if (fg == 0) - { - Console.Write("\x1b[39m"); - } - else - { - Console.Write("\x1b[" + FGs[fg]); - } - - for (int bg = 0; bg < BGs.Length; bg++) - { - if (bg > 0) - { - Console.Write(" "); - } - if (bg == 0) - { - Console.Write("\x1b[49m"); - } - else - { - Console.Write("\x1b[" + BGs[bg]); - } - - Console.Write(test); - Console.Write("\x1b[49m"); - } - Console.Write("\n"); - - } - Console.Write("\n"); - - // Reset foreground and background colors - Console.Write("\x1b[m"); - } - - private static IntPtr GetStdOutputHandle() - { - return GetStdHandle(STD_OUTPUT_HANDLE); - } - - static void PrintSchemes() - { - var schemeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schemes"); - - if (Directory.Exists(schemeDirectory)) - { - IntPtr handle = GetStdOutputHandle(); - GetConsoleMode(handle, out var mode); - SetConsoleMode(handle, mode | 0x4); - - int consoleWidth = Console.WindowWidth; - string fgText = " gYw "; - foreach (string schemeName in Directory.GetFiles(schemeDirectory).Select(Path.GetFileName)) - { - ColorScheme colorScheme = GetScheme(schemeName, false); - if (colorScheme != null) - { - string colors = string.Empty; - for (var index = 0; index < 8; index++) - { - uint t = colorScheme.colorTable[index]; - var color = UIntToColor(t); - // Set the background color to the color in the scheme, plus some text to show how it looks - colors += $"\x1b[48;2;{color.R};{color.G};{color.B}m{fgText}"; - } - // Align scheme colors right, or on newline if it doesn't fit - int schemeTextLength = fgText.Length * 8; - int bufferLength = consoleWidth - (schemeName.Length + schemeTextLength); - - string bufferString = bufferLength >= 0 - ? new string(' ', bufferLength) - : "\n" + new string(' ', consoleWidth - schemeTextLength); - - string outputString = schemeName + bufferString + colors; - Console.WriteLine(outputString); - Console.ResetColor(); - } - } - } - } - - static void PrintSchemesDirectory() - { - string schemeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schemes"); - Console.WriteLine(schemeDirectory); - } - - private static Color UIntToColor(uint color) - { - byte r = (byte)(color >> 0); - byte g = (byte)(color >> 8); - byte b = (byte)(color >> 16); - return Color.FromArgb(r, g, b); - } - - static bool SetProperties(ColorScheme colorScheme) - { - CONSOLE_SCREEN_BUFFER_INFO_EX csbiex = CONSOLE_SCREEN_BUFFER_INFO_EX.Create(); - IntPtr hOut = GetStdOutputHandle(); - bool success = GetConsoleScreenBufferInfoEx(hOut, ref csbiex); - if (success) - { - csbiex.srWindow.Bottom++; - for (int i = 0; i < 16; i++) - { - csbiex.ColorTable[i] = colorScheme.colorTable[i]; - } - if (colorScheme.consoleAttributes.background != null && colorScheme.consoleAttributes.foreground != null) - { - int fgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.foreground.Value); - int bgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.background.Value); - csbiex.wAttributes = (ushort)(fgidx | (bgidx << 4)); - } - if (colorScheme.consoleAttributes.popupBackground != null && colorScheme.consoleAttributes.popupForeground != null) - { - int fgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.popupForeground.Value); - int bgidx = colorScheme.CalculateIndex(colorScheme.consoleAttributes.popupBackground.Value); - csbiex.wPopupAttributes = (ushort)(fgidx | (bgidx << 4)); - } - SetConsoleScreenBufferInfoEx(hOut, ref csbiex); - } - if (success) - { - if (!quietMode) - { - PrintTable(); - } - } - return success; - } - - static bool SetPropertiesWithVt(ColorScheme colorScheme) - { - IntPtr hOut = GetStdOutputHandle(); - uint originalMode; - uint requestedMode; - bool succeeded = GetConsoleMode(hOut, out originalMode); - if (succeeded) - { - requestedMode = originalMode | (uint)ConsoleAPI.ConsoleOutputModes.ENABLE_VIRTUAL_TERMINAL_PROCESSING; - SetConsoleMode(hOut, requestedMode); - - } - - for (int i = 0; i < colorScheme.colorTable.Length; i++) - { - int vtIndex = VT_INDICIES[i]; - Color color = UIntToColor(colorScheme.colorTable[i]); - string s = $"\x1b]4;{vtIndex};rgb:{color.R:X}/{color.G:X}/{color.B:X}\x7"; - Console.Write(s); - } - if (!quietMode) - { - PrintTableWithVt(); - } - - if (succeeded) - { - SetConsoleMode(hOut, originalMode); - } - - return true; - } - static bool SetDefaults(ColorScheme colorScheme) - { - //TODO - RegistryKey consoleKey = Registry.CurrentUser.OpenSubKey("Console", true); - for (int i = 0; i < colorScheme.colorTable.Length; i++) - { - string valueName = "ColorTable" + (i < 10 ? "0" : "") + i; - consoleKey.SetValue(valueName, colorScheme.colorTable[i], RegistryValueKind.DWord); - } - Console.WriteLine(Resources.WroteToDefaults); - return true; - } - - static bool ExportCurrentAsIni(string outputPath) - { - CONSOLE_SCREEN_BUFFER_INFO_EX csbiex = CONSOLE_SCREEN_BUFFER_INFO_EX.Create(); - IntPtr hOut = GetStdOutputHandle(); - bool success = GetConsoleScreenBufferInfoEx(hOut, ref csbiex); - if (success) - { - try - { - // StreamWriter can fail for a variety of file system reasons so catch exceptions and print message. - using (System.IO.StreamWriter file = new System.IO.StreamWriter(outputPath)) - { - file.WriteLine("[table]"); - for (int i = 0; i < 16; i++) - { - string line = IniSchemeParser.COLOR_NAMES[i]; - line += " = "; - uint color = csbiex.ColorTable[i]; - uint r = color & (0x000000ff); - uint g = (color & (0x0000ff00)) >> 8; - uint b = (color & (0x00ff0000)) >> 16; - line += r + "," + g + "," + b; - file.WriteLine(line); - } - - file.WriteLine(); - file.WriteLine("[screen]"); - var forgroundIndex = csbiex.wAttributes & 0xF; - var backgroundIndex = csbiex.wAttributes >> 4; - file.WriteLine($"FOREGROUND = {IniSchemeParser.COLOR_NAMES[forgroundIndex]}"); - file.WriteLine($"BACKGROUND = {IniSchemeParser.COLOR_NAMES[backgroundIndex]}"); - - file.WriteLine(); - file.WriteLine("[popup]"); - forgroundIndex = csbiex.wPopupAttributes & 0xF; - backgroundIndex = csbiex.wPopupAttributes >> 4; - file.WriteLine($"FOREGROUND = {IniSchemeParser.COLOR_NAMES[forgroundIndex]}"); - file.WriteLine($"BACKGROUND = {IniSchemeParser.COLOR_NAMES[backgroundIndex]}"); - } - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - } - } - else - { - Console.WriteLine("Failed to get console information."); - } - return success; - } - static void Main(string[] args) { if (args.Length < 1) @@ -505,7 +50,7 @@ namespace ColorTool { case "-c": case "--current": - PrintTable(); + ColorTable.PrintTable(); return; case "-e": case "--errors": @@ -535,7 +80,7 @@ namespace ColorTool return; case "-l": case "--location": - PrintSchemesDirectory(); + SchemeManager.PrintSchemesDirectory(); return; case "-x": case "--xterm": @@ -546,7 +91,7 @@ namespace ColorTool case "--output": if (i + 1 < args.Length) { - ExportCurrentAsIni(args[i + 1]); + new IniSchemeWriter().ExportCurrentAsIni(args[i + 1]); } else { @@ -555,7 +100,7 @@ namespace ColorTool return; case "-s": case "--schemes": - PrintSchemes(); + SchemeManager.PrintSchemes(); return; default: break; @@ -564,7 +109,7 @@ namespace ColorTool string schemeName = args[args.Length - 1]; - ColorScheme colorScheme = GetScheme(schemeName, reportErrors); + ColorScheme colorScheme = SchemeManager.GetScheme(schemeName, reportErrors); if (colorScheme == null) { @@ -574,39 +119,19 @@ namespace ColorTool if (setDefaults) { - SetDefaults(colorScheme); + new DefaultConsoleTarget().ApplyColorScheme(colorScheme, quietMode); } if (setProperties) { if (setUnixStyle) { - SetPropertiesWithVt(colorScheme); + new VirtualTerminalConsoleTarget().ApplyColorScheme(colorScheme, quietMode); } else { - SetProperties(colorScheme); + new CurrentConsoleTarget().ApplyColorScheme(colorScheme, quietMode); } } } - - private static IEnumerable GetParsers() - { - return typeof(Program).Assembly.GetTypes() - .Where(t => !t.IsAbstract && typeof(ISchemeParser).IsAssignableFrom(t)) - .Select(t => (ISchemeParser)Activator.CreateInstance(t)); - } - - private static ColorScheme GetScheme(string schemeName, bool reportErrors = false) - { - foreach (var parser in GetParsers()) - { - ColorScheme scheme = parser.ParseScheme(schemeName, reportErrors); - if (scheme != null) - { - return scheme; - } - } - return null; - } } } diff --git a/tools/ColorTool/ColorTool/Scheme.cs b/tools/ColorTool/ColorTool/Scheme.cs deleted file mode 100644 index 3d7eb6ce7..000000000 --- a/tools/ColorTool/ColorTool/Scheme.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the terms described in the LICENSE file in the root of this project. -// - -using System.Collections.Generic; -using System.IO; - -namespace ColorTool -{ - static class Scheme - { - public static IEnumerable GetSearchPaths(string schemeName, string extension) - { - // Search order, for argument "name", where 'exe' is the dir of the exe. - // 1. ./name - // 2. ./name.ext - // 3. ./schemes/name - // 4. ./schemes/name.ext - // 5. exe/schemes/name - // 6. exe/schemes/name.ext - // 7. name (as an absolute path) - - string cwd = "./"; - yield return cwd + schemeName; - - string filename = schemeName + extension; - yield return cwd + filename; - - string cwdSchemes = "./schemes/"; - yield return cwdSchemes + schemeName; - yield return cwdSchemes + filename; - - string exeDir = Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location).FullName; - string exeSchemes = exeDir + "/schemes/"; - yield return exeSchemes + schemeName; - yield return exeSchemes + filename; - yield return schemeName; - } - } -} \ No newline at end of file diff --git a/tools/ColorTool/ColorTool/SchemeManager.cs b/tools/ColorTool/ColorTool/SchemeManager.cs new file mode 100644 index 000000000..09b3ee341 --- /dev/null +++ b/tools/ColorTool/ColorTool/SchemeManager.cs @@ -0,0 +1,112 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using ColorTool.SchemeParsers; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using static ColorTool.ConsoleAPI; + +namespace ColorTool +{ + static class SchemeManager + { + public static IEnumerable GetSearchPaths(string schemeName, string extension) + { + // Search order, for argument "name", where 'exe' is the dir of the exe. + // 1. ./name + // 2. ./name.ext + // 3. ./schemes/name + // 4. ./schemes/name.ext + // 5. exe/schemes/name + // 6. exe/schemes/name.ext + // 7. name (as an absolute path) + + string cwd = "./"; + yield return cwd + schemeName; + + string filename = schemeName + extension; + yield return cwd + filename; + + string cwdSchemes = "./schemes/"; + yield return cwdSchemes + schemeName; + yield return cwdSchemes + filename; + + string exeDir = Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location).FullName; + string exeSchemes = exeDir + "/schemes/"; + yield return exeSchemes + schemeName; + yield return exeSchemes + filename; + yield return schemeName; + } + + public static void PrintSchemesDirectory() + { + string schemeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schemes"); + Console.WriteLine(schemeDirectory); + } + + + public static void PrintSchemes() + { + var schemeDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schemes"); + + if (Directory.Exists(schemeDirectory)) + { + IntPtr handle = GetStdOutputHandle(); + GetConsoleMode(handle, out var mode); + SetConsoleMode(handle, mode | 0x4); + + int consoleWidth = Console.WindowWidth; + string fgText = " gYw "; + foreach (string schemeName in Directory.GetFiles(schemeDirectory).Select(Path.GetFileName)) + { + ColorScheme colorScheme = GetScheme(schemeName, false); + if (colorScheme != null) + { + string colors = string.Empty; + for (var index = 0; index < 8; index++) + { + var color = colorScheme[index]; + // Set the background color to the color in the scheme, plus some text to show how it looks + colors += $"\x1b[48;2;{color.R};{color.G};{color.B}m{fgText}"; + } + // Align scheme colors right, or on newline if it doesn't fit + int schemeTextLength = fgText.Length * 8; + int bufferLength = consoleWidth - (schemeName.Length + schemeTextLength); + + string bufferString = bufferLength >= 0 + ? new string(' ', bufferLength) + : "\n" + new string(' ', consoleWidth - schemeTextLength); + + string outputString = schemeName + bufferString + colors; + Console.WriteLine(outputString); + Console.ResetColor(); + } + } + } + } + + public static ColorScheme GetScheme(string schemeName, bool reportErrors = false) + { + foreach (var parser in GetParsers()) + { + ColorScheme scheme = parser.ParseScheme(schemeName, reportErrors); + if (scheme != null) + { + return scheme; + } + } + return null; + } + + public static IEnumerable GetParsers() + { + return typeof(Program).Assembly.GetTypes() + .Where(t => !t.IsAbstract && typeof(ISchemeParser).IsAssignableFrom(t)) + .Select(t => (ISchemeParser)Activator.CreateInstance(t)); + } + } +} \ No newline at end of file diff --git a/tools/ColorTool/ColorTool/ISchemeParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/ISchemeParser.cs similarity index 74% rename from tools/ColorTool/ColorTool/ISchemeParser.cs rename to tools/ColorTool/ColorTool/SchemeParsers/ISchemeParser.cs index 015315094..c90c0bdb7 100644 --- a/tools/ColorTool/ColorTool/ISchemeParser.cs +++ b/tools/ColorTool/ColorTool/SchemeParsers/ISchemeParser.cs @@ -1,9 +1,9 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // -namespace ColorTool +namespace ColorTool.SchemeParsers { interface ISchemeParser { diff --git a/tools/ColorTool/ColorTool/IniSchemeParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/IniSchemeParser.cs similarity index 97% rename from tools/ColorTool/ColorTool/IniSchemeParser.cs rename to tools/ColorTool/ColorTool/SchemeParsers/IniSchemeParser.cs index be332d600..ee8800141 100644 --- a/tools/ColorTool/ColorTool/IniSchemeParser.cs +++ b/tools/ColorTool/ColorTool/SchemeParsers/IniSchemeParser.cs @@ -1,5 +1,5 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // @@ -7,11 +7,11 @@ using System; using System.Linq; using System.Text; using System.Runtime.InteropServices; -using static ColorTool.ConsoleAPI; using System.IO; using System.Collections.Generic; +using static ColorTool.ConsoleAPI; -namespace ColorTool +namespace ColorTool.SchemeParsers { class IniSchemeParser : ISchemeParser { @@ -74,7 +74,7 @@ namespace ColorTool static string FindIniScheme(string schemeName) { - return Scheme.GetSearchPaths(schemeName, ".ini").FirstOrDefault(File.Exists); + return SchemeManager.GetSearchPaths(schemeName, ".ini").FirstOrDefault(File.Exists); } public ColorScheme ParseScheme(string schemeName, bool reportErrors = false) diff --git a/tools/ColorTool/ColorTool/JsonParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs similarity index 94% rename from tools/ColorTool/ColorTool/JsonParser.cs rename to tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs index dde2145df..abb1f9933 100644 --- a/tools/ColorTool/ColorTool/JsonParser.cs +++ b/tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs @@ -1,14 +1,17 @@ -using System; +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Json; -using System.Text; -using System.Threading.Tasks; using System.Xml; using static ColorTool.ConsoleAPI; -namespace ColorTool +namespace ColorTool.SchemeParsers { class JsonParser : ISchemeParser { @@ -42,7 +45,7 @@ namespace ColorTool static XmlDocument loadJsonFile(string schemeName) { XmlDocument xmlDoc = new XmlDocument(); - foreach (string path in Scheme.GetSearchPaths(schemeName, ".json") + foreach (string path in SchemeManager.GetSearchPaths(schemeName, ".json") .Where(File.Exists)) { try diff --git a/tools/ColorTool/ColorTool/XmlSchemeParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs similarity index 96% rename from tools/ColorTool/ColorTool/XmlSchemeParser.cs rename to tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs index 615a399bb..412f5739d 100644 --- a/tools/ColorTool/ColorTool/XmlSchemeParser.cs +++ b/tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs @@ -1,16 +1,16 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft. All rights reserved. // Licensed under the terms described in the LICENSE file in the root of this project. // + using System; using System.Globalization; using System.IO; using System.Linq; -using System.Linq.Expressions; using System.Xml; using static ColorTool.ConsoleAPI; -namespace ColorTool +namespace ColorTool.SchemeParsers { class XmlSchemeParser : ISchemeParser { @@ -82,7 +82,7 @@ namespace ColorTool static XmlDocument loadXmlScheme(string schemeName) { XmlDocument xmlDoc = new XmlDocument(); // Create an XML document object - foreach (string path in Scheme.GetSearchPaths(schemeName, ".itermcolors") + foreach (string path in SchemeManager.GetSearchPaths(schemeName, ".itermcolors") .Where(File.Exists)) { try diff --git a/tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs b/tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs new file mode 100644 index 000000000..18b4bb665 --- /dev/null +++ b/tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs @@ -0,0 +1,66 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +using ColorTool.SchemeParsers; +using System; +using static ColorTool.ConsoleAPI; + +namespace ColorTool.SchemeWriters +{ + class IniSchemeWriter + { + public bool ExportCurrentAsIni(string outputPath) + { + CONSOLE_SCREEN_BUFFER_INFO_EX csbiex = CONSOLE_SCREEN_BUFFER_INFO_EX.Create(); + IntPtr hOut = GetStdOutputHandle(); + bool success = GetConsoleScreenBufferInfoEx(hOut, ref csbiex); + if (success) + { + try + { + // StreamWriter can fail for a variety of file system reasons so catch exceptions and print message. + using (System.IO.StreamWriter file = new System.IO.StreamWriter(outputPath)) + { + file.WriteLine("[table]"); + for (int i = 0; i < 16; i++) + { + string line = IniSchemeParser.COLOR_NAMES[i]; + line += " = "; + uint color = csbiex.ColorTable[i]; + uint r = color & (0x000000ff); + uint g = (color & (0x0000ff00)) >> 8; + uint b = (color & (0x00ff0000)) >> 16; + line += r + "," + g + "," + b; + file.WriteLine(line); + } + + file.WriteLine(); + file.WriteLine("[screen]"); + var forgroundIndex = csbiex.wAttributes & 0xF; + var backgroundIndex = csbiex.wAttributes >> 4; + file.WriteLine($"FOREGROUND = {IniSchemeParser.COLOR_NAMES[forgroundIndex]}"); + file.WriteLine($"BACKGROUND = {IniSchemeParser.COLOR_NAMES[backgroundIndex]}"); + + file.WriteLine(); + file.WriteLine("[popup]"); + forgroundIndex = csbiex.wPopupAttributes & 0xF; + backgroundIndex = csbiex.wPopupAttributes >> 4; + file.WriteLine($"FOREGROUND = {IniSchemeParser.COLOR_NAMES[forgroundIndex]}"); + file.WriteLine($"BACKGROUND = {IniSchemeParser.COLOR_NAMES[backgroundIndex]}"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + else + { + Console.WriteLine("Failed to get console information."); + } + return success; + } + } +}