patterncsharpMinor
Console colorizer
Viewed 0 times
colorizerconsolestackoverflow
Problem
To be able to apply various colors to the console I created a
The element names are actually optional and can be any names. They are only required to parse the XML. What matters are the attribute and color names. I didn't know how to solve it with less effort without inventing a new markup.
```
internal class ConsoleColorizer
{
public static void Render(string xml)
{
Render(XElement.Parse(xml).Nodes());
}
public static void Render(IEnumerable xNodes)
{
Render(xNodes, null, null);
}
private static void Render(IEnumerable xNodes, ConsoleColor? lastForegroundColor, ConsoleColor? lastBackgroundColor)
{
foreach (var xChildNode in xNodes)
{
var xElement = xChildNode as XElement;
if (xElement != null)
{
Render(
xElement.Nodes(),
SetForegroundColor(xElement),
SetBackgroundColor(xElement)
);
}
else
{
RestoreForegroundColor(lastForegroundColor);
RestoreBackgroundColor(lastBackgroundColor);
Console.Write(((XText)xChildNode).Value);
}
}
Console.ResetColor();
}
private static ConsoleColor? SetForegroundColor(XElement xElement)
{
var foregroundColor = (ConsoleColor)0;
if (Enum.TryParse(xElement.Attribute("fg")?.Value, true, out foregroundColor))
{
return Console.ForegroundColor = foregroundColor;
}
return null;
}
private static ConsoleColor? SetBackgroundColor(XElement xElement)
{
var backgroundColor = (ConsoleColor)0;
if (Enum.TryParse(xElement.Attribute("bg")?.Value, true, out backgroundColor))
{
return Console.BackgroundColor = backgroundColor;
ConosoleColorizer. It's really simple. It just takes an XML and renders it to the console with the colors specified.The element names are actually optional and can be any names. They are only required to parse the XML. What matters are the attribute and color names. I didn't know how to solve it with less effort without inventing a new markup.
```
internal class ConsoleColorizer
{
public static void Render(string xml)
{
Render(XElement.Parse(xml).Nodes());
}
public static void Render(IEnumerable xNodes)
{
Render(xNodes, null, null);
}
private static void Render(IEnumerable xNodes, ConsoleColor? lastForegroundColor, ConsoleColor? lastBackgroundColor)
{
foreach (var xChildNode in xNodes)
{
var xElement = xChildNode as XElement;
if (xElement != null)
{
Render(
xElement.Nodes(),
SetForegroundColor(xElement),
SetBackgroundColor(xElement)
);
}
else
{
RestoreForegroundColor(lastForegroundColor);
RestoreBackgroundColor(lastBackgroundColor);
Console.Write(((XText)xChildNode).Value);
}
}
Console.ResetColor();
}
private static ConsoleColor? SetForegroundColor(XElement xElement)
{
var foregroundColor = (ConsoleColor)0;
if (Enum.TryParse(xElement.Attribute("fg")?.Value, true, out foregroundColor))
{
return Console.ForegroundColor = foregroundColor;
}
return null;
}
private static ConsoleColor? SetBackgroundColor(XElement xElement)
{
var backgroundColor = (ConsoleColor)0;
if (Enum.TryParse(xElement.Attribute("bg")?.Value, true, out backgroundColor))
{
return Console.BackgroundColor = backgroundColor;
Solution
This is dangerous:
That's an
((XText)xChildNode) you can't make the guarantee that the child node will be a text node. For example, say that I have this console message:var message =
@"
hallo
colored
console!
";
ConsoleColorizer.Render(message);That's an
InvalidCastException right there so only part of the message will be printed out.var backgroundColor = (ConsoleColor)0; is odd, it's about the only place I don't use var... ConsoleColor backgroundColor; is much clearer.Code Snippets
var message =
@"<text>
hallo
<!-- tag name is irrelevant, it's all in the attribute -->
<color fg=""yellow"">colored</color>
console!
</text>";
ConsoleColorizer.Render(message);Context
StackExchange Code Review Q#145139, answer score: 3
Revisions (0)
No revisions yet.