namespace XFESystem.Console; /// An RGB terminal color, independent of the host operating system. public readonly record struct TerminalColor(byte Red, byte Green, byte Blue) { public static TerminalColor ThemeForeground => new(117, 201, 245); public static TerminalColor ThemeBackground => new(12, 19, 33); public string Hex => $"#{Red:X2}{Green:X2}{Blue:X2}"; public static TerminalColor FromConsoleColor(ConsoleColor color) { var index = color switch { ConsoleColor.Black => 0, ConsoleColor.DarkRed => 1, ConsoleColor.DarkGreen => 2, ConsoleColor.DarkYellow => 3, ConsoleColor.DarkBlue => 4, ConsoleColor.DarkMagenta => 5, ConsoleColor.DarkCyan => 6, ConsoleColor.Gray => 7, ConsoleColor.DarkGray => 8, ConsoleColor.Red => 9, ConsoleColor.Green => 10, ConsoleColor.Yellow => 11, ConsoleColor.Blue => 12, ConsoleColor.Magenta => 13, ConsoleColor.Cyan => 14, ConsoleColor.White => 15, _ => throw new ArgumentOutOfRangeException(nameof(color)) }; return FromIndexed((byte)index); } /// Resolve the xterm 16-color palette, 6×6×6 cube and grayscale ramp. public static TerminalColor FromIndexed(byte index) { if (index < Palette.Length) return Palette[index]; if (index >= 232) { var gray = (byte)(8 + (index - 232) * 10); return new(gray, gray, gray); } var cube = index - 16; return new(Cube(cube / 36), Cube(cube / 6 % 6), Cube(cube % 6)); } private static byte Cube(int component) => component == 0 ? (byte)0 : (byte)(55 + component * 40); private static readonly TerminalColor[] Palette = [ new(0, 0, 0), new(128, 0, 0), new(0, 128, 0), new(128, 128, 0), new(0, 0, 128), new(128, 0, 128), new(0, 128, 128), new(192, 192, 192), new(128, 128, 128), new(255, 0, 0), new(0, 255, 0), new(255, 255, 0), new(0, 0, 255), new(255, 0, 255), new(0, 255, 255), new(255, 255, 255) ]; }