diff --git a/tools/ColorTool/ColorTool/ColorScheme.cs b/tools/ColorTool/ColorTool/ColorScheme.cs
index f930f31e548..62c0eb47d1a 100644
--- a/tools/ColorTool/ColorTool/ColorScheme.cs
+++ b/tools/ColorTool/ColorTool/ColorScheme.cs
@@ -1,31 +1,74 @@
//
-// 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
{
+ ///
+ /// Represents a colorscheme that can be applied to a console.
+ ///
public class ColorScheme
{
- public uint[] colorTable = null;
- public ConsoleAttributes consoleAttributes;
+ public ColorScheme(uint[] colorTable, ConsoleAttributes consoleAttributes)
+ {
+ ColorTable = colorTable;
+ ConsoleAttributes = consoleAttributes;
+ }
+
+ public uint[] ColorTable { get; }
+ public ConsoleAttributes ConsoleAttributes { get; }
+
+ public ushort? ScreenColorAttributes =>
+ CalculateBackgroundForegroundAttributes(
+ this.ConsoleAttributes.Background,
+ this.ConsoleAttributes.Foreground
+ );
+
+ public ushort? PopupColorAttributes =>
+ CalculateBackgroundForegroundAttributes(
+ this.ConsoleAttributes.PopupBackground,
+ this.ConsoleAttributes.PopupForeground
+ );
+
+ 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);
+ }
+ private ushort? CalculateBackgroundForegroundAttributes(uint? background, uint? foreground)
+ {
+ if(!(background.HasValue && foreground.HasValue))
+ {
+ return null;
+ }
+ int fgidx = this.CalculateIndex(foreground.Value);
+ int bgidx = this.CalculateIndex(background.Value);
+ var attributes = (ushort)(fgidx | (bgidx << 4));
+ return attributes;
+ }
public int CalculateIndex(uint value) =>
- colorTable.Select((color, idx) => Tuple.Create(color, idx))
+ ColorTable.Select((color, idx) => Tuple.Create(color, idx))
.OrderBy(Difference(value))
.First().Item2;
private static Func, double> Difference(uint c1) =>
- // heuristic 1: nearest neighbor in RGB space
- // tup => Distance(RGB(c1), RGB(tup.Item1));
- // heuristic 2: nearest neighbor in RGB space
- // tup => Distance(HSV(c1), HSV(tup.Item1));
- // heuristic 3: weighted RGB L2 distance
- tup => WeightedRGBSimilarity(c1, tup.Item1);
+ // heuristic 1: nearest neighbor in RGB space
+ // tup => Distance(RGB(c1), RGB(tup.Item1));
+ // heuristic 2: nearest neighbor in RGB space
+ // tup => Distance(HSV(c1), HSV(tup.Item1));
+ // heuristic 3: weighted RGB L2 distance
+ tup => WeightedRGBSimilarity(c1, tup.Item1);
private static double WeightedRGBSimilarity(uint c1, uint c2)
{
@@ -36,9 +79,6 @@ private static double WeightedRGBSimilarity(uint c1, uint c2)
return Math.Sqrt(dist[0] * (2 + rbar / 256.0) + dist[1] * 4 + dist[2] * (2 + (255 - rbar) / 256.0));
}
- private static double Distance(uint[] c1c, uint[] c2c)
- => Math.Sqrt(c1c.Zip(c2c, (a, b) => Math.Pow((int)a - (int)b, 2)).Sum());
-
internal static uint[] RGB(uint c) => new[] { c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF };
internal static uint[] HSV(uint c)
@@ -77,17 +117,17 @@ internal void Dump()
for (int i = 0; i < 16; ++i)
{
- _dump($"Color[{i}]", colorTable[i]);
+ _dump($"Color[{i}]", ColorTable[i]);
}
- if (consoleAttributes.foreground != null)
+ if (ConsoleAttributes.Foreground != null)
{
- _dump("FG ", consoleAttributes.foreground.Value);
+ _dump("FG ", ConsoleAttributes.Foreground.Value);
}
- if (consoleAttributes.background != null)
+ if (ConsoleAttributes.Background != null)
{
- _dump("BG ", consoleAttributes.background.Value);
+ _dump("BG ", ConsoleAttributes.Background.Value);
}
}
}
diff --git a/tools/ColorTool/ColorTool/ColorTable.cs b/tools/ColorTool/ColorTool/ColorTable.cs
new file mode 100644
index 00000000000..29470ac1124
--- /dev/null
+++ b/tools/ColorTool/ColorTool/ColorTable.cs
@@ -0,0 +1,205 @@
+//
+// 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;
+
+namespace ColorTool
+{
+ ///
+ /// Displays the color table that demonstrates the current colorscheme.
+ ///
+ static class ColorTable
+ {
+ private const int DarkBlack = 0;
+ private const int DarkBlue = 1;
+ private const int DarkGreen = 2;
+ private const int DarkCyan = 3;
+ private const int DarkRed = 4;
+ private const int DarkMagenta = 5;
+ private const int DarkYellow = 6;
+ private const int DarkWhite = 7;
+ private const int BrightBlack = 8;
+ private const int BrightBlue = 9;
+ private const int BrightGreen = 10;
+ private const int BrightCyan = 11;
+ private const int BrightRed = 12;
+ private const int BrightMagenta = 13;
+ private const int BrightYellow = 14;
+ private const int BrightWhite = 15;
+
+ // This is the order of colors when output by the table.
+ private static readonly IReadOnlyList Foregrounds = new[]
+ {
+ BrightWhite,
+ DarkBlack,
+ BrightBlack,
+ DarkRed,
+ BrightRed,
+ DarkGreen,
+ BrightGreen,
+ DarkYellow,
+ BrightYellow,
+ DarkBlue,
+ BrightBlue,
+ DarkMagenta,
+ BrightMagenta,
+ DarkCyan,
+ BrightCyan,
+ DarkWhite,
+ BrightWhite
+ };
+
+ private static readonly IReadOnlyList Backgrounds = new[]
+ {
+ DarkBlack,
+ DarkRed,
+ DarkGreen,
+ DarkYellow,
+ DarkBlue,
+ DarkMagenta,
+ DarkCyan,
+ DarkWhite
+ };
+
+ private const string TestText = " gYw ";
+
+ private static readonly IReadOnlyList AnsiForegroundSequences = new[]
+ {
+ "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"
+ };
+
+ private static readonly IReadOnlyList AnsiBackgroundSequences = new[]
+ {
+ "m",
+ "40m",
+ "41m",
+ "42m",
+ "43m",
+ "44m",
+ "45m",
+ "46m",
+ "47m"
+ };
+
+ 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;
+
+ Console.Write("\t");
+ for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
+ {
+ if (bg > 0) Console.Write(" ");
+ Console.Write(" ");
+ Console.Write(bg == 0 ? " " : AnsiBackgroundSequences[bg]);
+ Console.Write(" ");
+ }
+ Console.WriteLine();
+
+ for (int fg = 0; fg < AnsiForegroundSequences.Count; fg++)
+ {
+ Console.ForegroundColor = currentForeground;
+ Console.BackgroundColor = currentBackground;
+
+ if (fg >= 0) Console.Write(AnsiForegroundSequences[fg] + "\t");
+
+ if (fg == 0) Console.ForegroundColor = currentForeground;
+ else Console.ForegroundColor = colors[Foregrounds[fg - 1]];
+
+ for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
+ {
+ if (bg > 0) Console.Write(" ");
+ if (bg == 0)
+ Console.BackgroundColor = currentBackground;
+ else Console.BackgroundColor = colors[Backgrounds[bg - 1]];
+ Console.Write(TestText);
+ Console.BackgroundColor = currentBackground;
+ }
+ Console.Write("\n");
+ }
+ Console.Write("\n");
+
+ // Reset foreground and background colors
+ Console.ForegroundColor = currentForeground;
+ Console.BackgroundColor = currentBackground;
+ }
+
+ public static void PrintTableWithVt()
+ {
+ Console.Write("\t");
+ for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
+ {
+ if (bg > 0) Console.Write(" ");
+ Console.Write(" ");
+ Console.Write(bg == 0 ? " " : AnsiBackgroundSequences[bg]);
+ Console.Write(" ");
+ }
+ Console.WriteLine();
+
+ for (int fg = 0; fg < AnsiForegroundSequences.Count; fg++)
+ {
+ Console.Write("\x1b[m");
+
+ if (fg >= 0)
+ {
+ Console.Write(AnsiForegroundSequences[fg] + "\t");
+ }
+
+ if (fg == 0)
+ {
+ Console.Write("\x1b[39m");
+ }
+ else
+ {
+ Console.Write("\x1b[" + AnsiForegroundSequences[fg]);
+ }
+
+ for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
+ {
+ if (bg > 0)
+ {
+ Console.Write(" ");
+ }
+ if (bg == 0)
+ {
+ Console.Write("\x1b[49m");
+ }
+ else
+ {
+ Console.Write("\x1b[" + AnsiBackgroundSequences[bg]);
+ }
+
+ Console.Write(TestText);
+ 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/ColorTool.csproj b/tools/ColorTool/ColorTool/ColorTool.csproj
index 5cfeab4d923..a1df3abb456 100644
--- a/tools/ColorTool/ColorTool/ColorTool.csproj
+++ b/tools/ColorTool/ColorTool/ColorTool.csproj
@@ -2,7 +2,8 @@
Exe
- net46
+ net461
false
+ latest
diff --git a/tools/ColorTool/ColorTool/ConsoleAPI.cs b/tools/ColorTool/ColorTool/ConsoleAPI.cs
index 3219d34e01f..8df31f64dc3 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.
//
@@ -8,9 +8,11 @@
namespace ColorTool
{
- class ConsoleAPI
+ static class ConsoleAPI
{
- ////////////////////////////////////////////////////////////////////////
+ private const int StdOutputHandle = -11;
+ public const int ColorTableSize = 16;
+
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
@@ -58,7 +60,7 @@ public static CONSOLE_SCREEN_BUFFER_INFO_EX Create()
}
}
- public static int STD_OUTPUT_HANDLE = -11;
+ public static IntPtr GetStdOutputHandle() => GetStdHandle(StdOutputHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
@@ -83,13 +85,10 @@ IntPtr lpReserved
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
- ////////////////////////////////////////////////////////////////////////
public static uint RGB(int r, int g, int b)
{
return (uint)r + (((uint)g) << 8) + (((uint)b) << 16);
}
-
- public const int COLOR_TABLE_SIZE = 16;
}
}
diff --git a/tools/ColorTool/ColorTool/ConsoleAttributes.cs b/tools/ColorTool/ColorTool/ConsoleAttributes.cs
index ac2d9bceb38..40234528fc3 100644
--- a/tools/ColorTool/ColorTool/ConsoleAttributes.cs
+++ b/tools/ColorTool/ColorTool/ConsoleAttributes.cs
@@ -1,17 +1,26 @@
//
-// 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
{
- public struct ConsoleAttributes
+ ///
+ /// Keeps track of the color table indices for the background/foreground in a colorscheme.
+ ///
+ public readonly struct ConsoleAttributes
{
- public uint? foreground;
- public uint? background;
-
- public uint? popupForeground;
- public uint? popupBackground;
+ public ConsoleAttributes(uint? background, uint? foreground, uint? popupBackground, uint? popupForeground)
+ {
+ Background = background;
+ Foreground = foreground;
+ PopupBackground = popupBackground;
+ PopupForeground = popupForeground;
+ }
+ public uint? Foreground { get; }
+ public uint? Background { get; }
+ public uint? PopupForeground { get; }
+ public uint? PopupBackground { get; }
}
}
diff --git a/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs b/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs
new file mode 100644
index 00000000000..f116d75cd12
--- /dev/null
+++ b/tools/ColorTool/ColorTool/ConsoleTargets/CurrentConsoleTarget.cs
@@ -0,0 +1,47 @@
+//
+// 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.ScreenColorAttributes is ushort wAttrs)
+ {
+ csbiex.wAttributes = wAttrs;
+ }
+ if(colorScheme.PopupColorAttributes is ushort wPopupAttrs)
+ {
+ csbiex.wPopupAttributes = wPopupAttrs;
+ }
+ 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 00000000000..1948078119d
--- /dev/null
+++ b/tools/ColorTool/ColorTool/ConsoleTargets/DefaultConsoleTarget.cs
@@ -0,0 +1,36 @@
+//
+// 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)
+ {
+ 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);
+ }
+ if(colorScheme.ScreenColorAttributes is ushort screenColors)
+ {
+ consoleKey.SetValue("ScreenColors", screenColors, RegistryValueKind.DWord);
+ }
+ if(colorScheme.PopupColorAttributes is ushort popupColors)
+ {
+ consoleKey.SetValue("PopupColors", popupColors, 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 00000000000..a1a2b9d2a85
--- /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 00000000000..bbc24d96b06
--- /dev/null
+++ b/tools/ColorTool/ColorTool/ConsoleTargets/VirtualTerminalConsoleTarget.cs
@@ -0,0 +1,69 @@
+//
+// 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.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.
+ public static readonly IReadOnlyList VirtualTerminalIndices = new[]
+ {
+ 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 = VirtualTerminalIndices[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 3496d606dea..b9d12f47855 100644
--- a/tools/ColorTool/ColorTool/Program.cs
+++ b/tools/ColorTool/ColorTool/Program.cs
@@ -1,497 +1,25 @@
//
-// 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 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;
+ private static bool quietMode = false;
+ private static bool reportErrors = false;
+ private static bool setDefaults = false;
+ private static bool setProperties = true;
+ private static bool setUnixStyle = false;
- 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;
- static bool setProperties = true;
- static bool setUnixStyle = false;
-
- static void Usage()
- {
- Console.WriteLine(Resources.Usage,
- string.Join($"{Environment.NewLine} ", GetParsers().Select(p => p.Name)));
- }
-
- static void OutputUsage()
- {
- Console.WriteLine(Resources.OutputUsage);
- }
-
- static void Version()
- {
- var assembly = System.Reflection.Assembly.GetExecutingAssembly();
- var info = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
- 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)
+ public static void Main(string[] args)
{
if (args.Length < 1)
{
@@ -505,7 +33,7 @@ static void Main(string[] args)
{
case "-c":
case "--current":
- PrintTable();
+ ColorTable.PrintTable();
return;
case "-e":
case "--errors":
@@ -535,7 +63,7 @@ static void Main(string[] args)
return;
case "-l":
case "--location":
- PrintSchemesDirectory();
+ SchemeManager.PrintSchemesDirectory();
return;
case "-x":
case "--xterm":
@@ -546,7 +74,7 @@ static void Main(string[] args)
case "--output":
if (i + 1 < args.Length)
{
- ExportCurrentAsIni(args[i + 1]);
+ new IniSchemeWriter().ExportCurrentAsIni(args[i + 1]);
}
else
{
@@ -555,7 +83,7 @@ static void Main(string[] args)
return;
case "-s":
case "--schemes":
- PrintSchemes();
+ SchemeManager.PrintSchemes();
return;
default:
break;
@@ -564,7 +92,7 @@ static void Main(string[] args)
string schemeName = args[args.Length - 1];
- ColorScheme colorScheme = GetScheme(schemeName, reportErrors);
+ ColorScheme colorScheme = SchemeManager.GetScheme(schemeName, reportErrors);
if (colorScheme == null)
{
@@ -572,41 +100,51 @@ static void Main(string[] args)
return;
}
- if (setDefaults)
+ foreach (var target in GetConsoleTargets())
{
- SetDefaults(colorScheme);
- }
- if (setProperties)
- {
- if (setUnixStyle)
- {
- SetPropertiesWithVt(colorScheme);
- }
- else
- {
- SetProperties(colorScheme);
- }
+ target.ApplyColorScheme(colorScheme, quietMode);
}
}
- private static IEnumerable GetParsers()
+ private static void Usage()
{
- return typeof(Program).Assembly.GetTypes()
- .Where(t => !t.IsAbstract && typeof(ISchemeParser).IsAssignableFrom(t))
- .Select(t => (ISchemeParser)Activator.CreateInstance(t));
+ Console.WriteLine(Resources.Usage,
+ string.Join($"{Environment.NewLine} ", SchemeManager.GetParsers().Select(p => p.Name)));
+ }
+
+ private static void OutputUsage()
+ {
+ Console.WriteLine(Resources.OutputUsage);
}
- private static ColorScheme GetScheme(string schemeName, bool reportErrors = false)
+ private static void Version()
{
- foreach (var parser in GetParsers())
+ var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+ var info = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
+ Console.WriteLine($"colortool v{info.FileVersion}");
+ }
+
+ ///
+ /// Returns an enumerable of consoles that we want to apply the colorscheme to.
+ /// The contents of this enumerable depends on the user's provided command line flags.
+ ///
+ private static IEnumerable GetConsoleTargets()
+ {
+ if (setDefaults)
+ {
+ yield return new DefaultConsoleTarget();
+ }
+ if (setProperties)
{
- ColorScheme scheme = parser.ParseScheme(schemeName, reportErrors);
- if (scheme != null)
+ if (setUnixStyle)
+ {
+ yield return new VirtualTerminalConsoleTarget();
+ }
+ else
{
- return scheme;
+ yield return new CurrentConsoleTarget();
}
}
- return null;
}
}
}
diff --git a/tools/ColorTool/ColorTool/Scheme.cs b/tools/ColorTool/ColorTool/Scheme.cs
deleted file mode 100644
index 3d7eb6ce726..00000000000
--- 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 00000000000..1f84a74601c
--- /dev/null
+++ b/tools/ColorTool/ColorTool/SchemeManager.cs
@@ -0,0 +1,106 @@
+//
+// 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)
+ {
+ return GetParsers()
+ .Where(parser => parser.CanParse(schemeName))
+ .Select(parser => parser.ParseScheme(schemeName, reportErrors))
+ .FirstOrDefault();
+ }
+
+ 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 66%
rename from tools/ColorTool/ColorTool/ISchemeParser.cs
rename to tools/ColorTool/ColorTool/SchemeParsers/ISchemeParser.cs
index 01531509432..cb4ebce6aff 100644
--- a/tools/ColorTool/ColorTool/ISchemeParser.cs
+++ b/tools/ColorTool/ColorTool/SchemeParsers/ISchemeParser.cs
@@ -1,14 +1,14 @@
//
-// 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
{
string Name { get; }
-
+ bool CanParse(string schemeName);
ColorScheme ParseScheme(string schemeName, bool reportErrors = false);
}
}
diff --git a/tools/ColorTool/ColorTool/IniSchemeParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/IniSchemeParser.cs
similarity index 74%
rename from tools/ColorTool/ColorTool/IniSchemeParser.cs
rename to tools/ColorTool/ColorTool/SchemeParsers/IniSchemeParser.cs
index be332d6002a..e4e1add8242 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,19 +7,22 @@
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
{
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
+ private const string FileExtension = ".ini";
+
// These are in Windows Color table order - BRG, not RGB.
- public static string[] COLOR_NAMES = {
+ internal static readonly IReadOnlyList ColorNames = new[]
+ {
"DARK_BLACK",
"DARK_BLUE",
"DARK_GREEN",
@@ -38,44 +41,10 @@ class IniSchemeParser : ISchemeParser
"BRIGHT_WHITE"
};
- public string Name => "INI File Parser";
-
- static uint ParseHex(string arg)
- {
- System.Drawing.Color col = System.Drawing.ColorTranslator.FromHtml(arg);
- return RGB(col.R, col.G, col.B);
- }
-
- static uint ParseRgb(string arg)
- {
- int[] components = { 0, 0, 0 };
- string[] args = arg.Split(',');
- if (args.Length != components.Length) throw new Exception("Invalid color format \"" + arg + "\"");
- if (args.Length != 3) throw new Exception("Invalid color format \"" + arg + "\"");
- for (int i = 0; i < args.Length; i++)
- {
- components[i] = Int32.Parse(args[i]);
- }
-
- return RGB(components[0], components[1], components[2]);
- }
+ public string Name { get; } = "INI File Parser";
- static uint ParseColor(string arg)
- {
- if (arg[0] == '#')
- {
- return ParseHex(arg.Substring(1));
- }
- else
- {
- return ParseRgb(arg);
- }
- }
-
- static string FindIniScheme(string schemeName)
- {
- return Scheme.GetSearchPaths(schemeName, ".ini").FirstOrDefault(File.Exists);
- }
+ public bool CanParse(string schemeName) =>
+ string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
@@ -84,16 +53,16 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
string filename = FindIniScheme(schemeName);
if (filename == null) return null;
- string[] tableStrings = new string[COLOR_TABLE_SIZE];
+ string[] tableStrings = new string[ColorTableSize];
uint[] colorTable = null;
uint? foregroundColor = null;
uint? backgroundColor = null;
uint? popupForegroundColor = null;
uint? popupBackgroundColor = null;
- for (int i = 0; i < COLOR_TABLE_SIZE; i++)
+ for (int i = 0; i < ColorTableSize; i++)
{
- string name = COLOR_NAMES[i];
+ string name = ColorNames[i];
StringBuilder buffer = new StringBuilder(512);
GetPrivateProfileString("table", name, null, buffer, 512, filename);
@@ -113,16 +82,16 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
try
{
- colorTable = new uint[COLOR_TABLE_SIZE];
- for (int i = 0; i < COLOR_TABLE_SIZE; i++)
+ colorTable = new uint[ColorTableSize];
+ for (int i = 0; i < ColorTableSize; i++)
{
colorTable[i] = ParseColor(tableStrings[i]);
}
if (ReadAttributes("popup", out var foreground, out var background))
{
- var foregroundIndex = (COLOR_NAMES as IList).IndexOf(foreground);
- var backgroundIndex = (COLOR_NAMES as IList).IndexOf(background);
+ var foregroundIndex = (ColorNames as IList).IndexOf(foreground);
+ var backgroundIndex = (ColorNames as IList).IndexOf(background);
if (foregroundIndex != -1 && backgroundIndex != -1)
{
popupForegroundColor = colorTable[foregroundIndex];
@@ -132,8 +101,8 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
if (ReadAttributes("screen", out foreground, out background))
{
- var foregroundIndex = (COLOR_NAMES as IList).IndexOf(foreground);
- var backgroundIndex = (COLOR_NAMES as IList).IndexOf(background);
+ var foregroundIndex = (ColorNames as IList).IndexOf(foreground);
+ var backgroundIndex = (ColorNames as IList).IndexOf(background);
if (foregroundIndex != -1 && backgroundIndex != -1)
{
foregroundColor = colorTable[foregroundIndex];
@@ -154,8 +123,8 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
if (colorTable != null)
{
- var consoleAttributes = new ConsoleAttributes { background = backgroundColor, foreground = foregroundColor, popupBackground = popupBackgroundColor, popupForeground = popupForegroundColor };
- return new ColorScheme { colorTable = colorTable, consoleAttributes = consoleAttributes };
+ var consoleAttributes = new ConsoleAttributes(backgroundColor, foregroundColor, popupBackgroundColor, popupForegroundColor);
+ return new ColorScheme(colorTable, consoleAttributes);
}
else
{
@@ -170,18 +139,55 @@ bool ReadAttributes(string section, out string foreground, out string background
StringBuilder buffer = new StringBuilder(512);
GetPrivateProfileString(section, "FOREGROUND", null, buffer, 512, filename);
foreground = buffer.ToString();
- if (!COLOR_NAMES.Contains(foreground))
+ if (!ColorNames.Contains(foreground))
return false;
buffer = new StringBuilder(512);
GetPrivateProfileString(section, "BACKGROUND", null, buffer, 512, filename);
background = buffer.ToString();
- if (!COLOR_NAMES.Contains(background))
+ if (!ColorNames.Contains(background))
return false;
return true;
}
}
+
+ private static uint ParseHex(string arg)
+ {
+ System.Drawing.Color col = System.Drawing.ColorTranslator.FromHtml(arg);
+ return RGB(col.R, col.G, col.B);
+ }
+
+ private static uint ParseRgb(string arg)
+ {
+ int[] components = { 0, 0, 0 };
+ string[] args = arg.Split(',');
+ if (args.Length != components.Length) throw new Exception("Invalid color format \"" + arg + "\"");
+ if (args.Length != 3) throw new Exception("Invalid color format \"" + arg + "\"");
+ for (int i = 0; i < args.Length; i++)
+ {
+ components[i] = Int32.Parse(args[i]);
+ }
+
+ return RGB(components[0], components[1], components[2]);
+ }
+
+ private static uint ParseColor(string arg)
+ {
+ if (arg[0] == '#')
+ {
+ return ParseHex(arg.Substring(1));
+ }
+ else
+ {
+ return ParseRgb(arg);
+ }
+ }
+
+ private static string FindIniScheme(string schemeName)
+ {
+ return SchemeManager.GetSearchPaths(schemeName, FileExtension).FirstOrDefault(File.Exists);
+ }
}
}
diff --git a/tools/ColorTool/ColorTool/JsonParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs
similarity index 57%
rename from tools/ColorTool/ColorTool/JsonParser.cs
rename to tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs
index dde2145df68..37218ba18ac 100644
--- a/tools/ColorTool/ColorTool/JsonParser.cs
+++ b/tools/ColorTool/ColorTool/SchemeParsers/JsonParser.cs
@@ -1,78 +1,59 @@
-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
{
- static string[] CONCFG_COLOR_NAMES = {
- "black", // DARK_BLACK
- "dark_blue", // DARK_BLUE
- "dark_green", // DARK_GREEN
- "dark_cyan", // DARK_CYAN
- "dark_red", // DARK_RED
- "dark_magenta", // DARK_MAGENTA
- "dark_yellow", // DARK_YELLOW
- "gray", // DARK_WHITE
- "dark_gray", // BRIGHT_BLACK
- "blue", // BRIGHT_BLUE
- "green", // BRIGHT_GREEN
- "cyan", // BRIGHT_CYAN
- "red", // BRIGHT_RED
- "magenta", // BRIGHT_MAGENTA
- "yellow", // BRIGHT_YELLOW
- "white" // BRIGHT_WHITE
+ private const string FileExtension = ".json";
+ private static readonly IReadOnlyList ConcfgColorNames = new[]
+ {
+ "black", // Dark Black
+ "dark_blue", // Dark Blue
+ "dark_green", // Dark Green
+ "dark_cyan", // Dark Cyan
+ "dark_red", // Dark Red
+ "dark_magenta", // Dark Magenta
+ "dark_yellow", // Dark Yellow
+ "gray", // Dark White
+ "dark_gray", // Bright Black
+ "blue", // Bright Blue
+ "green", // Bright Green
+ "cyan", // Bright Cyan
+ "red", // Bright Red
+ "magenta", // Bright Magenta
+ "yellow", // Bright Yellow
+ "white" // Bright White
};
- public string Name => "concfg Parser";
-
- static uint ParseColor(string arg)
- {
- System.Drawing.Color col = System.Drawing.ColorTranslator.FromHtml(arg);
- return RGB(col.R, col.G, col.B);
- }
+ public string Name { get; } = "concfg Parser";
- static XmlDocument loadJsonFile(string schemeName)
- {
- XmlDocument xmlDoc = new XmlDocument();
- foreach (string path in Scheme.GetSearchPaths(schemeName, ".json")
- .Where(File.Exists))
- {
- try
- {
- var data = File.ReadAllBytes(path);
- var reader = JsonReaderWriterFactory.CreateJsonReader(data, System.Xml.XmlDictionaryReaderQuotas.Max);
- xmlDoc.Load(reader);
- return xmlDoc;
- }
- catch (XmlException /*e*/) { /* failed to parse */ }
- catch (IOException /*e*/) { /* failed to find */ }
- catch (UnauthorizedAccessException /*e*/) { /* unauthorized */ }
- }
-
- return null;
- }
+ public bool CanParse(string schemeName) =>
+ string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
{
- XmlDocument xmlDoc = loadJsonFile(schemeName);
+ XmlDocument xmlDoc = LoadJsonFile(schemeName);
if (xmlDoc == null) return null;
try
{
XmlNode root = xmlDoc.DocumentElement;
XmlNodeList children = root.ChildNodes;
- uint[] colorTable = new uint[COLOR_TABLE_SIZE]; ;
- for (int i = 0; i < COLOR_TABLE_SIZE; i++)
+ uint[] colorTable = new uint[ColorTableSize]; ;
+ for (int i = 0; i < ColorTableSize; i++)
{
- string name = CONCFG_COLOR_NAMES[i];
+ string name = ConcfgColorNames[i];
var node = children.OfType().Where(n => n.Name == name).Single();
colorTable[i] = ParseColor(node.InnerText);
}
@@ -87,8 +68,8 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
var parts = popupNode.InnerText.Split(',');
if (parts.Length == 2)
{
- var foregroundIndex = (CONCFG_COLOR_NAMES as IList).IndexOf(parts[0]);
- var backgroundIndex = (CONCFG_COLOR_NAMES as IList).IndexOf(parts[1]);
+ var foregroundIndex = (ConcfgColorNames as IList).IndexOf(parts[0]);
+ var backgroundIndex = (ConcfgColorNames as IList).IndexOf(parts[1]);
if (foregroundIndex != -1 && backgroundIndex != -1)
{
popupForeground = colorTable[foregroundIndex];
@@ -106,8 +87,8 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
var parts = screenNode.InnerText.Split(',');
if (parts.Length == 2)
{
- var foregroundIndex = (CONCFG_COLOR_NAMES as IList).IndexOf(parts[0]);
- var backgroundIndex = (CONCFG_COLOR_NAMES as IList).IndexOf(parts[1]);
+ var foregroundIndex = (ConcfgColorNames as IList).IndexOf(parts[0]);
+ var backgroundIndex = (ConcfgColorNames as IList).IndexOf(parts[1]);
if (foregroundIndex != -1 && backgroundIndex != -1)
{
screenForeground = colorTable[foregroundIndex];
@@ -116,18 +97,45 @@ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
}
}
- var consoleAttributes = new ConsoleAttributes { background = screenBackground, foreground = screenForeground, popupBackground = popupBackground, popupForeground = popupForeground };
- return new ColorScheme { colorTable = colorTable, consoleAttributes = consoleAttributes };
+ var consoleAttributes = new ConsoleAttributes(screenBackground, screenForeground, popupBackground, popupForeground);
+ return new ColorScheme(colorTable, consoleAttributes);
}
catch (Exception /*e*/)
{
if (reportErrors)
{
- Console.WriteLine("failes to load json scheme");
+ Console.WriteLine("failed to load json scheme");
}
return null;
}
}
+
+ private static uint ParseColor(string arg)
+ {
+ System.Drawing.Color col = System.Drawing.ColorTranslator.FromHtml(arg);
+ return RGB(col.R, col.G, col.B);
+ }
+
+ private static XmlDocument LoadJsonFile(string schemeName)
+ {
+ XmlDocument xmlDoc = new XmlDocument();
+ foreach (string path in SchemeManager.GetSearchPaths(schemeName, FileExtension)
+ .Where(File.Exists))
+ {
+ try
+ {
+ var data = File.ReadAllBytes(path);
+ var reader = JsonReaderWriterFactory.CreateJsonReader(data, System.Xml.XmlDictionaryReaderQuotas.Max);
+ xmlDoc.Load(reader);
+ return xmlDoc;
+ }
+ catch (XmlException /*e*/) { /* failed to parse */ }
+ catch (IOException /*e*/) { /* failed to find */ }
+ catch (UnauthorizedAccessException /*e*/) { /* unauthorized */ }
+ }
+
+ return null;
+ }
}
}
diff --git a/tools/ColorTool/ColorTool/XmlSchemeParser.cs b/tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs
similarity index 54%
rename from tools/ColorTool/ColorTool/XmlSchemeParser.cs
rename to tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs
index 615a399bb31..4747fd01570 100644
--- a/tools/ColorTool/ColorTool/XmlSchemeParser.cs
+++ b/tools/ColorTool/ColorTool/SchemeParsers/XmlSchemeParser.cs
@@ -1,47 +1,94 @@
//
-// 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.Collections.Generic;
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
{
// In Windows Color Table order
- static string[] PLIST_COLOR_NAMES = {
- "Ansi 0 Color", // DARK_BLACK
- "Ansi 4 Color", // DARK_BLUE
- "Ansi 2 Color", // DARK_GREEN
- "Ansi 6 Color", // DARK_CYAN
- "Ansi 1 Color", // DARK_RED
- "Ansi 5 Color", // DARK_MAGENTA
- "Ansi 3 Color", // DARK_YELLOW
- "Ansi 7 Color", // DARK_WHITE
- "Ansi 8 Color", // BRIGHT_BLACK
- "Ansi 12 Color", // BRIGHT_BLUE
- "Ansi 10 Color", // BRIGHT_GREEN
- "Ansi 14 Color", // BRIGHT_CYAN
- "Ansi 9 Color", // BRIGHT_RED
- "Ansi 13 Color", // BRIGHT_MAGENTA
- "Ansi 11 Color", // BRIGHT_YELLOW
- "Ansi 15 Color" // BRIGHT_WHITE
+ private static readonly string[] PListColorNames =
+ {
+ "Ansi 0 Color", // Dark Black
+ "Ansi 4 Color", // Dark Blue
+ "Ansi 2 Color", // Dark Green
+ "Ansi 6 Color", // Dark Cyan
+ "Ansi 1 Color", // Dark Red
+ "Ansi 5 Color", // Dark Magenta
+ "Ansi 3 Color", // Dark Yellow
+ "Ansi 7 Color", // Dark White
+ "Ansi 8 Color", // Bright Black
+ "Ansi 12 Color", // Bright Blue
+ "Ansi 10 Color", // Bright Green
+ "Ansi 14 Color", // Bright Cyan
+ "Ansi 9 Color", // Bright Red
+ "Ansi 13 Color", // Bright Magenta
+ "Ansi 11 Color", // Bright Yellow
+ "Ansi 15 Color" // Bright White
};
- static string FG_KEY = "Foreground Color";
- static string BG_KEY = "Background Color";
- static string RED_KEY = "Red Component";
- static string GREEN_KEY = "Green Component";
- static string BLUE_KEY = "Blue Component";
- public string Name => "iTerm Parser";
+ private const string ForegroundKey = "Foreground Color";
+ private const string BackgroundKey = "Background Color";
+ private const string RedKey = "Red Component";
+ private const string GreenKey = "Green Component";
+ private const string BlueKey = "Blue Component";
+ private const string FileExtension = ".itermcolors";
+
+ public string Name { get; } = "iTerm Parser";
+
+ public bool CanParse(string schemeName) =>
+ string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
+
+ public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
+ {
+ XmlDocument xmlDoc = LoadXmlScheme(schemeName); // Create an XML document object
+ if (xmlDoc == null) return null;
+ XmlNode root = xmlDoc.GetElementsByTagName("dict")[0];
+ XmlNodeList children = root.ChildNodes;
+
+ uint[] colorTable = new uint[ColorTableSize];
+ uint? fgColor = null, bgColor = null;
+ int colorsFound = 0;
+ bool success = false;
+ foreach (var tableEntry in children.OfType().Where(_ => _.Name == "key"))
+ {
+ uint rgb = 0;
+ int index = -1;
+ XmlNode components = tableEntry.NextSibling;
+ success = ParseRgbFromXml(components, ref rgb);
+ if (!success) { break; }
+ else if (tableEntry.InnerText == ForegroundKey) { fgColor = rgb; }
+ else if (tableEntry.InnerText == BackgroundKey) { bgColor = rgb; }
+ else if (-1 != (index = Array.IndexOf(PListColorNames, tableEntry.InnerText)))
+ { colorTable[index] = rgb; colorsFound++; }
+ }
+ if (colorsFound < ColorTableSize)
+ {
+ if (reportErrors)
+ {
+ Console.WriteLine(Resources.InvalidNumberOfColors);
+ }
+ success = false;
+ }
+ if (!success)
+ {
+ return null;
+ }
+
+ var consoleAttributes = new ConsoleAttributes(bgColor, fgColor, null, null);
+ return new ColorScheme(colorTable, consoleAttributes);
+ }
- static bool parseRgbFromXml(XmlNode components, ref uint rgb)
+ private static bool ParseRgbFromXml(XmlNode components, ref uint rgb)
{
int r = -1;
int g = -1;
@@ -51,15 +98,15 @@ static bool parseRgbFromXml(XmlNode components, ref uint rgb)
{
if (c.Name == "key")
{
- if (c.InnerText == RED_KEY)
+ if (c.InnerText == RedKey)
{
r = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
}
- else if (c.InnerText == GREEN_KEY)
+ else if (c.InnerText == GreenKey)
{
g = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
}
- else if (c.InnerText == BLUE_KEY)
+ else if (c.InnerText == BlueKey)
{
b = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
}
@@ -78,11 +125,10 @@ static bool parseRgbFromXml(XmlNode components, ref uint rgb)
return true;
}
-
- static XmlDocument loadXmlScheme(string schemeName)
+ private 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, FileExtension)
.Where(File.Exists))
{
try
@@ -97,46 +143,5 @@ static XmlDocument loadXmlScheme(string schemeName)
return null;
}
-
-
- public ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
- {
- XmlDocument xmlDoc = loadXmlScheme(schemeName); // Create an XML document object
- if (xmlDoc == null) return null;
- XmlNode root = xmlDoc.GetElementsByTagName("dict")[0];
- XmlNodeList children = root.ChildNodes;
-
- uint[] colorTable = new uint[COLOR_TABLE_SIZE];
- uint? fgColor = null, bgColor = null;
- int colorsFound = 0;
- bool success = false;
- foreach (var tableEntry in children.OfType().Where(_ => _.Name == "key"))
- {
- uint rgb = 0;
- int index = -1;
- XmlNode components = tableEntry.NextSibling;
- success = parseRgbFromXml(components, ref rgb);
- if (!success) { break; }
- else if (tableEntry.InnerText == FG_KEY) { fgColor = rgb; }
- else if (tableEntry.InnerText == BG_KEY) { bgColor = rgb; }
- else if (-1 != (index = Array.IndexOf(PLIST_COLOR_NAMES, tableEntry.InnerText)))
- { colorTable[index] = rgb; colorsFound++; }
- }
- if (colorsFound < COLOR_TABLE_SIZE)
- {
- if (reportErrors)
- {
- Console.WriteLine(Resources.InvalidNumberOfColors);
- }
- success = false;
- }
- if (!success)
- {
- return null;
- }
-
- var consoleAttributes = new ConsoleAttributes { foreground = fgColor, background = bgColor };
- return new ColorScheme { colorTable = colorTable, consoleAttributes = consoleAttributes };
- }
}
}
diff --git a/tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs b/tools/ColorTool/ColorTool/SchemeWriters/IniSchemeWriter.cs
new file mode 100644
index 00000000000..e72a35fe0c5
--- /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.ColorNames[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.ColorNames[forgroundIndex]}");
+ file.WriteLine($"BACKGROUND = {IniSchemeParser.ColorNames[backgroundIndex]}");
+
+ file.WriteLine();
+ file.WriteLine("[popup]");
+ forgroundIndex = csbiex.wPopupAttributes & 0xF;
+ backgroundIndex = csbiex.wPopupAttributes >> 4;
+ file.WriteLine($"FOREGROUND = {IniSchemeParser.ColorNames[forgroundIndex]}");
+ file.WriteLine($"BACKGROUND = {IniSchemeParser.ColorNames[backgroundIndex]}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+ else
+ {
+ Console.WriteLine("Failed to get console information.");
+ }
+ return success;
+ }
+ }
+}