fix scheme name resolution, and schema load on WSL (#5327)
This PR fixes the scheme resolution bug outlined in #5326 The approach is as follows: * In [SchemeManager.cs], find the first scheme parser that actually successfully parses the scheme, as opposed to the existing code, which finds the first scheme parser which _says it can parse the scheme_, as that logic spuriously returns `true` currently. * In [XmlSchemeParser.cs] and [JsonParser.cs], ensure that the contents of the file are read and the contents passed to XmlDocument.LoadXXX, as this fails with an UriException on WSL otherwise. * Remove `CanParse` as it is superfluous. The check for a valid scheme parser should not just check an extension but also if the file exists - this is best done by the `ParseScheme` function as it already returns null on failure. * Add `FileExtension` to the interface because we need it lifted now. Closes #5326
This commit is contained in:
parent
44e80d40b6
commit
436fac6afa
|
@ -91,9 +91,8 @@ namespace ColorTool
|
|||
public static ColorScheme GetScheme(string schemeName, bool reportErrors = false)
|
||||
{
|
||||
return GetParsers()
|
||||
.Where(parser => parser.CanParse(schemeName))
|
||||
.Select(parser => parser.ParseScheme(schemeName, reportErrors))
|
||||
.FirstOrDefault();
|
||||
.FirstOrDefault(x => x != null);
|
||||
}
|
||||
|
||||
public static IEnumerable<ISchemeParser> GetParsers()
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ColorTool.SchemeParsers
|
|||
interface ISchemeParser
|
||||
{
|
||||
string Name { get; }
|
||||
bool CanParse(string schemeName);
|
||||
string FileExtension { get; }
|
||||
ColorScheme ParseScheme(string schemeName, bool reportErrors = false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,193 +1,190 @@
|
|||
//
|
||||
// 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.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class IniSchemeParser : SchemeParserBase
|
||||
{
|
||||
[DllImport("kernel32")]
|
||||
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
|
||||
|
||||
protected override string FileExtension { get; } = ".ini";
|
||||
|
||||
// These are in Windows Color table order - BRG, not RGB.
|
||||
internal static readonly IReadOnlyList<string> ColorNames = new[]
|
||||
{
|
||||
"DARK_BLACK",
|
||||
"DARK_BLUE",
|
||||
"DARK_GREEN",
|
||||
"DARK_CYAN",
|
||||
"DARK_RED",
|
||||
"DARK_MAGENTA",
|
||||
"DARK_YELLOW",
|
||||
"DARK_WHITE",
|
||||
"BRIGHT_BLACK",
|
||||
"BRIGHT_BLUE",
|
||||
"BRIGHT_GREEN",
|
||||
"BRIGHT_CYAN",
|
||||
"BRIGHT_RED",
|
||||
"BRIGHT_MAGENTA",
|
||||
"BRIGHT_YELLOW",
|
||||
"BRIGHT_WHITE"
|
||||
};
|
||||
|
||||
public override string Name { get; } = "INI File Parser";
|
||||
|
||||
public override bool CanParse(string schemeName) =>
|
||||
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
string filename = FindIniScheme(schemeName);
|
||||
if (filename == null) return null;
|
||||
|
||||
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 < ColorTableSize; i++)
|
||||
{
|
||||
string name = ColorNames[i];
|
||||
StringBuilder buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString("table", name, null, buffer, 512, filename);
|
||||
|
||||
tableStrings[i] = buffer.ToString();
|
||||
if (tableStrings[i].Length <= 0)
|
||||
{
|
||||
success = false;
|
||||
if (reportErrors)
|
||||
{
|
||||
Console.WriteLine(string.Format(Resources.IniParseError, filename, name, tableStrings[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
try
|
||||
{
|
||||
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 = (ColorNames as IList<string>).IndexOf(foreground);
|
||||
var backgroundIndex = (ColorNames as IList<string>).IndexOf(background);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
popupForegroundColor = colorTable[foregroundIndex];
|
||||
popupBackgroundColor = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (ReadAttributes("screen", out foreground, out background))
|
||||
{
|
||||
var foregroundIndex = (ColorNames as IList<string>).IndexOf(foreground);
|
||||
var backgroundIndex = (ColorNames as IList<string>).IndexOf(background);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
foregroundColor = colorTable[foregroundIndex];
|
||||
backgroundColor = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
if (reportErrors)
|
||||
{
|
||||
Console.WriteLine(string.Format(Resources.IniLoadError, filename));
|
||||
}
|
||||
|
||||
colorTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (colorTable != null)
|
||||
{
|
||||
var consoleAttributes = new ConsoleAttributes(backgroundColor, foregroundColor, popupBackgroundColor, popupForegroundColor);
|
||||
return new ColorScheme(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
bool ReadAttributes(string section, out string foreground, out string background)
|
||||
{
|
||||
foreground = null;
|
||||
background = null;
|
||||
|
||||
StringBuilder buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString(section, "FOREGROUND", null, buffer, 512, filename);
|
||||
foreground = buffer.ToString();
|
||||
if (!ColorNames.Contains(foreground))
|
||||
return false;
|
||||
|
||||
|
||||
buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString(section, "BACKGROUND", null, buffer, 512, filename);
|
||||
background = buffer.ToString();
|
||||
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 string FindIniScheme(string schemeName)
|
||||
{
|
||||
return SchemeManager.GetSearchPaths(schemeName, FileExtension).FirstOrDefault(File.Exists);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class IniSchemeParser : SchemeParserBase
|
||||
{
|
||||
[DllImport("kernel32")]
|
||||
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
|
||||
|
||||
public override string FileExtension { get; } = ".ini";
|
||||
|
||||
// These are in Windows Color table order - BRG, not RGB.
|
||||
internal static readonly IReadOnlyList<string> ColorNames = new[]
|
||||
{
|
||||
"DARK_BLACK",
|
||||
"DARK_BLUE",
|
||||
"DARK_GREEN",
|
||||
"DARK_CYAN",
|
||||
"DARK_RED",
|
||||
"DARK_MAGENTA",
|
||||
"DARK_YELLOW",
|
||||
"DARK_WHITE",
|
||||
"BRIGHT_BLACK",
|
||||
"BRIGHT_BLUE",
|
||||
"BRIGHT_GREEN",
|
||||
"BRIGHT_CYAN",
|
||||
"BRIGHT_RED",
|
||||
"BRIGHT_MAGENTA",
|
||||
"BRIGHT_YELLOW",
|
||||
"BRIGHT_WHITE"
|
||||
};
|
||||
|
||||
public override string Name { get; } = "INI File Parser";
|
||||
|
||||
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
string filename = FindIniScheme(schemeName);
|
||||
if (filename == null) return null;
|
||||
|
||||
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 < ColorTableSize; i++)
|
||||
{
|
||||
string name = ColorNames[i];
|
||||
StringBuilder buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString("table", name, null, buffer, 512, filename);
|
||||
|
||||
tableStrings[i] = buffer.ToString();
|
||||
if (tableStrings[i].Length <= 0)
|
||||
{
|
||||
success = false;
|
||||
if (reportErrors)
|
||||
{
|
||||
Console.WriteLine(string.Format(Resources.IniParseError, filename, name, tableStrings[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
try
|
||||
{
|
||||
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 = (ColorNames as IList<string>).IndexOf(foreground);
|
||||
var backgroundIndex = (ColorNames as IList<string>).IndexOf(background);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
popupForegroundColor = colorTable[foregroundIndex];
|
||||
popupBackgroundColor = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (ReadAttributes("screen", out foreground, out background))
|
||||
{
|
||||
var foregroundIndex = (ColorNames as IList<string>).IndexOf(foreground);
|
||||
var backgroundIndex = (ColorNames as IList<string>).IndexOf(background);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
foregroundColor = colorTable[foregroundIndex];
|
||||
backgroundColor = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
if (reportErrors)
|
||||
{
|
||||
Console.WriteLine(string.Format(Resources.IniLoadError, filename));
|
||||
}
|
||||
|
||||
colorTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (colorTable != null)
|
||||
{
|
||||
var consoleAttributes = new ConsoleAttributes(backgroundColor, foregroundColor, popupBackgroundColor, popupForegroundColor);
|
||||
return new ColorScheme(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
bool ReadAttributes(string section, out string foreground, out string background)
|
||||
{
|
||||
foreground = null;
|
||||
background = null;
|
||||
|
||||
StringBuilder buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString(section, "FOREGROUND", null, buffer, 512, filename);
|
||||
foreground = buffer.ToString();
|
||||
if (!ColorNames.Contains(foreground))
|
||||
return false;
|
||||
|
||||
|
||||
buffer = new StringBuilder(512);
|
||||
GetPrivateProfileString(section, "BACKGROUND", null, buffer, 512, filename);
|
||||
background = buffer.ToString();
|
||||
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 string FindIniScheme(string schemeName)
|
||||
{
|
||||
return SchemeManager.GetSearchPaths(schemeName, FileExtension).FirstOrDefault(File.Exists);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,141 +1,142 @@
|
|||
//
|
||||
// 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.Xml;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class JsonParser : SchemeParserBase
|
||||
{
|
||||
protected override string FileExtension { get; } = ".json";
|
||||
private static readonly IReadOnlyList<string> 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 override string Name { get; } = "concfg Parser";
|
||||
|
||||
public override bool CanParse(string schemeName) =>
|
||||
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
|
||||
{
|
||||
XmlDocument xmlDoc = LoadJsonFile(schemeName);
|
||||
if (xmlDoc == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
XmlNode root = xmlDoc.DocumentElement;
|
||||
XmlNodeList children = root.ChildNodes;
|
||||
uint[] colorTable = new uint[ColorTableSize]; ;
|
||||
for (int i = 0; i < ColorTableSize; i++)
|
||||
{
|
||||
string name = ConcfgColorNames[i];
|
||||
var node = children.OfType<XmlNode>().Where(n => n.Name == name).Single();
|
||||
colorTable[i] = ParseColor(node.InnerText);
|
||||
}
|
||||
|
||||
|
||||
uint? popupForeground = null;
|
||||
uint? popupBackground = null;
|
||||
|
||||
var popupNode = children.OfType<XmlNode>().Where(n => n.Name == "popup_colors").SingleOrDefault();
|
||||
if (popupNode != null)
|
||||
{
|
||||
var parts = popupNode.InnerText.Split(',');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var foregroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[0]);
|
||||
var backgroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[1]);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
popupForeground = colorTable[foregroundIndex];
|
||||
popupBackground = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint? screenForeground = null;
|
||||
uint? screenBackground = null;
|
||||
|
||||
var screenNode = children.OfType<XmlNode>().Where(n => n.Name == "screen_colors").SingleOrDefault();
|
||||
if (screenNode != null)
|
||||
{
|
||||
var parts = screenNode.InnerText.Split(',');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var foregroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[0]);
|
||||
var backgroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[1]);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
screenForeground = colorTable[foregroundIndex];
|
||||
screenBackground = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var consoleAttributes = new ConsoleAttributes(screenBackground, screenForeground, popupBackground, popupForeground);
|
||||
return new ColorScheme(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
if (reportErrors)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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.Xml;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class JsonParser : SchemeParserBase
|
||||
{
|
||||
public override string FileExtension { get; } = ".json";
|
||||
private static readonly IReadOnlyList<string> 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 override string Name { get; } = "concfg Parser";
|
||||
|
||||
public override ColorScheme ParseScheme(string schemeName, bool reportErrors = false)
|
||||
{
|
||||
XmlDocument xmlDoc = LoadJsonFile(schemeName);
|
||||
if (xmlDoc == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
XmlNode root = xmlDoc.DocumentElement;
|
||||
XmlNodeList children = root.ChildNodes;
|
||||
uint[] colorTable = new uint[ColorTableSize]; ;
|
||||
for (int i = 0; i < ColorTableSize; i++)
|
||||
{
|
||||
string name = ConcfgColorNames[i];
|
||||
var node = children.OfType<XmlNode>().Where(n => n.Name == name).Single();
|
||||
colorTable[i] = ParseColor(node.InnerText);
|
||||
}
|
||||
|
||||
|
||||
uint? popupForeground = null;
|
||||
uint? popupBackground = null;
|
||||
|
||||
var popupNode = children.OfType<XmlNode>().Where(n => n.Name == "popup_colors").SingleOrDefault();
|
||||
if (popupNode != null)
|
||||
{
|
||||
var parts = popupNode.InnerText.Split(',');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var foregroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[0]);
|
||||
var backgroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[1]);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
popupForeground = colorTable[foregroundIndex];
|
||||
popupBackground = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint? screenForeground = null;
|
||||
uint? screenBackground = null;
|
||||
|
||||
var screenNode = children.OfType<XmlNode>().Where(n => n.Name == "screen_colors").SingleOrDefault();
|
||||
if (screenNode != null)
|
||||
{
|
||||
var parts = screenNode.InnerText.Split(',');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var foregroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[0]);
|
||||
var backgroundIndex = (ConcfgColorNames as IList<string>).IndexOf(parts[1]);
|
||||
if (foregroundIndex != -1 && backgroundIndex != -1)
|
||||
{
|
||||
screenForeground = colorTable[foregroundIndex];
|
||||
screenBackground = colorTable[backgroundIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var consoleAttributes = new ConsoleAttributes(screenBackground, screenForeground, popupBackground, popupForeground);
|
||||
return new ColorScheme(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
if (reportErrors)
|
||||
{
|
||||
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 XmlDocument LoadJsonFile(string schemeName) =>
|
||||
SchemeManager
|
||||
.GetSearchPaths(schemeName, FileExtension)
|
||||
.Select(path =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = File.ReadAllBytes(path);
|
||||
var reader = JsonReaderWriterFactory.CreateJsonReader(data, XmlDictionaryReaderQuotas.Max);
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(reader);
|
||||
return xmlDoc;
|
||||
}
|
||||
catch (XmlException) { }
|
||||
catch (IOException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Unexpected Exception: {e}.\nBailing...");
|
||||
throw;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.FirstOrDefault(x => x != null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -12,17 +13,13 @@ namespace ColorTool.SchemeParsers
|
|||
|
||||
public abstract string Name { get; }
|
||||
|
||||
public abstract bool CanParse(string schemeName);
|
||||
|
||||
public abstract ColorScheme ParseScheme(string schemeName, bool reportErrors = false);
|
||||
|
||||
// Common elements and helpers
|
||||
protected abstract string FileExtension { get; }
|
||||
public abstract string FileExtension { get; }
|
||||
|
||||
protected string ExtractSchemeName(string schemeFileName)
|
||||
{
|
||||
return schemeFileName.Substring(0, schemeFileName.Length - FileExtension.Length);
|
||||
}
|
||||
protected string ExtractSchemeName(string schemeFileName) =>
|
||||
Path.ChangeExtension(schemeFileName, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,148 +1,149 @@
|
|||
//
|
||||
// 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.Xml;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class XmlSchemeParser : SchemeParserBase
|
||||
{
|
||||
// In Windows Color Table order
|
||||
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
|
||||
};
|
||||
|
||||
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";
|
||||
|
||||
protected override string FileExtension { get; } = ".itermcolors";
|
||||
|
||||
public override string Name { get; } = "iTerm Parser";
|
||||
|
||||
public override bool CanParse(string schemeName) =>
|
||||
string.Equals(Path.GetExtension(schemeName), FileExtension, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
public override 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<XmlNode>().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(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
|
||||
private static bool ParseRgbFromXml(XmlNode components, ref uint rgb)
|
||||
{
|
||||
int r = -1;
|
||||
int g = -1;
|
||||
int b = -1;
|
||||
|
||||
foreach (XmlNode c in components.ChildNodes)
|
||||
{
|
||||
if (c.Name == "key")
|
||||
{
|
||||
if (c.InnerText == RedKey)
|
||||
{
|
||||
r = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (c.InnerText == GreenKey)
|
||||
{
|
||||
g = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (c.InnerText == BlueKey)
|
||||
{
|
||||
b = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r < 0 || g < 0 || b < 0)
|
||||
{
|
||||
Console.WriteLine(Resources.InvalidColor);
|
||||
return false;
|
||||
}
|
||||
rgb = RGB(r, g, b);
|
||||
return true;
|
||||
}
|
||||
|
||||
private XmlDocument LoadXmlScheme(string schemeName)
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument(); // Create an XML document object
|
||||
foreach (string path in SchemeManager.GetSearchPaths(schemeName, FileExtension)
|
||||
.Where(File.Exists))
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlDoc.Load(path);
|
||||
return xmlDoc;
|
||||
}
|
||||
catch (XmlException /*e*/) { /* failed to parse */ }
|
||||
catch (IOException /*e*/) { /* failed to find */ }
|
||||
catch (UnauthorizedAccessException /*e*/) { /* unauthorized */ }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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.Xml;
|
||||
using static ColorTool.ConsoleAPI;
|
||||
|
||||
namespace ColorTool.SchemeParsers
|
||||
{
|
||||
class XmlSchemeParser : SchemeParserBase
|
||||
{
|
||||
// In Windows Color Table order
|
||||
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
|
||||
};
|
||||
|
||||
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";
|
||||
|
||||
public override string FileExtension { get; } = ".itermcolors";
|
||||
|
||||
public override string Name { get; } = "iTerm Parser";
|
||||
|
||||
public override 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<XmlNode>().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(ExtractSchemeName(schemeName), colorTable, consoleAttributes);
|
||||
}
|
||||
|
||||
private static bool ParseRgbFromXml(XmlNode components, ref uint rgb)
|
||||
{
|
||||
int r = -1;
|
||||
int g = -1;
|
||||
int b = -1;
|
||||
|
||||
foreach (XmlNode c in components.ChildNodes)
|
||||
{
|
||||
if (c.Name == "key")
|
||||
{
|
||||
if (c.InnerText == RedKey)
|
||||
{
|
||||
r = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (c.InnerText == GreenKey)
|
||||
{
|
||||
g = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else if (c.InnerText == BlueKey)
|
||||
{
|
||||
b = (int)(255 * Convert.ToDouble(c.NextSibling.InnerText, CultureInfo.InvariantCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r < 0 || g < 0 || b < 0)
|
||||
{
|
||||
Console.WriteLine(Resources.InvalidColor);
|
||||
return false;
|
||||
}
|
||||
rgb = RGB(r, g, b);
|
||||
return true;
|
||||
}
|
||||
|
||||
private XmlDocument LoadXmlScheme(string schemeName) =>
|
||||
SchemeManager
|
||||
.GetSearchPaths(schemeName, FileExtension)
|
||||
.Select(path =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(path);
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(text);
|
||||
return xmlDoc;
|
||||
}
|
||||
catch (XmlException) { }
|
||||
catch (IOException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Unexpected Exception: {e}.\nBailing...");
|
||||
throw;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.FirstOrDefault(x => x != null);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue