Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Color Console - a simple class to add color to .NET Console commands more easily.
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace MainColorConsole
{
class Program
{
static void Main(string[] args)
{
ColorConsole.WriteWrappedHeader("Color Console Examples");
Console.WriteLine("\nUsing a splash of color in your Console code more easily... (plain text)\n");
ColorConsole.WriteLine("Color me this - in Red", ConsoleColor.Red);
ColorConsole.WriteWrappedHeader("Off with their green Heads!", headerColor: ConsoleColor.Green);
ColorConsole.WriteWarning("\nWorking...\n");
Console.WriteLine("Writing some mixed colors: (plain text)");
ColorConsole.WriteEmbeddedColorLine(
"Launch the site with [darkcyan]https://localhost:5200[/darkcyan] and press [yellow]Ctrl-c[/yellow] to exit.\n");
ColorConsole.WriteSuccess("The operation completed successfully.");
}
}
/// <summary>
/// Console Color Helper class that provides coloring to individual commands
/// </summary>
public static class ColorConsole
{
/// <summary>
/// WriteLine with color
/// </summary>
/// <param name="text"></param>
/// <param name="color"></param>
public static void WriteLine(string text, ConsoleColor? color = null)
{
if (color.HasValue)
{
var oldColor = System.Console.ForegroundColor;
if (color == oldColor)
Console.WriteLine(text);
else
{
Console.ForegroundColor = color.Value;
Console.WriteLine(text);
Console.ForegroundColor = oldColor;
}
}
else
Console.WriteLine(text);
}
/// <summary>
/// Writes out a line with a specific color as a string
/// </summary>
/// <param name="text">Text to write</param>
/// <param name="color">A console color. Must match ConsoleColors collection names (case insensitive)</param>
public static void WriteLine(string text, string color)
{
if (string.IsNullOrEmpty(color))
{
WriteLine(text);
return;
}
if (!Enum.TryParse(color, true, out ConsoleColor col))
{
WriteLine(text);
}
else
{
WriteLine(text, col);
}
}
/// <summary>
/// Write with color
/// </summary>
/// <param name="text"></param>
/// <param name="color"></param>
public static void Write(string text, ConsoleColor? color = null)
{
if (color.HasValue)
{
var oldColor = System.Console.ForegroundColor;
if (color == oldColor)
Console.Write(text);
else
{
Console.ForegroundColor = color.Value;
Console.Write(text);
Console.ForegroundColor = oldColor;
}
}
else
Console.Write(text);
}
/// <summary>
/// Writes out a line with color specified as a string
/// </summary>
/// <param name="text">Text to write</param>
/// <param name="color">A console color. Must match ConsoleColors collection names (case insensitive)</param>
public static void Write(string text, string color)
{
if (string.IsNullOrEmpty(color))
{
Write(text);
return;
}
if (!ConsoleColor.TryParse(color, true, out ConsoleColor col))
{
Write(text);
}
else
{
Write(text, col);
}
}
#region Wrappers and Templates
/// <summary>
/// Writes a line of header text wrapped in a in a pair of lines of dashes:
/// -----------
/// Header Text
/// -----------
/// and allows you to specify a color for the header. The dashes are colored
/// </summary>
/// <param name="headerText">Header text to display</param>
/// <param name="wrapperChar">wrapper character (-)</param>
/// <param name="headerColor">Color for header text (yellow)</param>
/// <param name="dashColor">Color for dashes (gray)</param>
public static void WriteWrappedHeader(string headerText,
char wrapperChar = '-',
ConsoleColor headerColor = ConsoleColor.Yellow,
ConsoleColor dashColor = ConsoleColor.DarkGray)
{
if (string.IsNullOrEmpty(headerText))
return;
string line = new string(wrapperChar, headerText.Length);
WriteLine(line,dashColor);
WriteLine(headerText, headerColor);
WriteLine(line,dashColor);
}
private static Lazy<Regex> colorBlockRegEx = new Lazy<Regex>(
()=> new Regex("\\[(?<color>.*?)\\](?<text>[^[]*)\\[/\\k<color>\\]", RegexOptions.IgnoreCase),
isThreadSafe: true);
/// <summary>
/// Allows a string to be written with embedded color values using:
/// This is [red]Red[/red] text and this is [cyan]Blue[/blue] text
/// </summary>
/// <param name="text">Text to display</param>
/// <param name="baseTextColor">Base text color</param>
public static void WriteEmbeddedColorLine(string text, ConsoleColor? baseTextColor = null)
{
if (baseTextColor == null)
baseTextColor = Console.ForegroundColor;
if (string.IsNullOrEmpty(text))
{
WriteLine(string.Empty);
return;
}
int at = text.IndexOf("[");
int at2 = text.IndexOf("]");
if (at == -1 || at2 <= at)
{
WriteLine(text, baseTextColor);
return;
}
while (true)
{
var match = colorBlockRegEx.Value.Match(text);
if (match.Length < 1)
{
Write(text, baseTextColor);
break;
}
// write up to expression
Write(text.Substring(0, match.Index), baseTextColor);
// strip out the expression
string highlightText = match.Groups["text"].Value;
string colorVal = match.Groups["color"].Value;
Write(highlightText, colorVal);
// remainder of string
text = text.Substring(match.Index + match.Value.Length);
}
Console.WriteLine();
}
#endregion
#region Success, Error, Info, Warning Wrappers
/// <summary>
/// Write a Success Line - green
/// </summary>
/// <param name="text">Text to write out</param>
public static void WriteSuccess(string text)
{
WriteLine(text, ConsoleColor.Green);
}
/// <summary>
/// Write a Error Line - Red
/// </summary>
/// <param name="text">Text to write out</param>
public static void WriteError(string text)
{
WriteLine(text, ConsoleColor.Red);
}
/// <summary>
/// Write a Warning Line - Yellow
/// </summary>
/// <param name="text">Text to Write out</param>
public static void WriteWarning(string text)
{
WriteLine(text, ConsoleColor.DarkYellow);
}
/// <summary>
/// Write a Info Line - dark cyan
/// </summary>
/// <param name="text">Text to write out</param>
public static void WriteInfo(string text)
{
WriteLine(text, ConsoleColor.DarkCyan);
}
#endregion
}
}
@jslicer

This comment has been minimized.

Copy link

jslicer commented Jul 11, 2020

On first glance, I'm thinking string line = new StringBuilder().Insert(0, wrapperChar.ToString(), headerText.Length).ToString(); has three times the number of allocations over the simpler string line = new string(wrapperChar, headerText.Length);. Thoughts?

@RickStrahl

This comment has been minimized.

Copy link
Owner Author

RickStrahl commented Jul 13, 2020

Totally right. Totally forgot that that's available for char values, but not for strings which is what I used the above for typically. Updated. Thanks.

@jslicer

This comment has been minimized.

Copy link

jslicer commented Jul 13, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.