写一个小的命令行工具,用不同的颜色输出会很好。这可能吗?
当前回答
我发现给控制台输出片段着色的最简单方法是在Windows控制台中使用ANSI转义序列。
public static int Main(string[] args)
{
string NL = Environment.NewLine; // shortcut
string NORMAL = Console.IsOutputRedirected ? "" : "\x1b[39m";
string RED = Console.IsOutputRedirected ? "" : "\x1b[91m";
string GREEN = Console.IsOutputRedirected ? "" : "\x1b[92m";
string YELLOW = Console.IsOutputRedirected ? "" : "\x1b[93m";
string BLUE = Console.IsOutputRedirected ? "" : "\x1b[94m";
string MAGENTA = Console.IsOutputRedirected ? "" : "\x1b[95m";
string CYAN = Console.IsOutputRedirected ? "" : "\x1b[96m";
string GREY = Console.IsOutputRedirected ? "" : "\x1b[97m";
string BOLD = Console.IsOutputRedirected ? "" : "\x1b[1m";
string NOBOLD = Console.IsOutputRedirected ? "" : "\x1b[22m";
string UNDERLINE = Console.IsOutputRedirected ? "" : "\x1b[4m";
string NOUNDERLINE = Console.IsOutputRedirected ? "" : "\x1b[24m";
string REVERSE = Console.IsOutputRedirected ? "" : "\x1b[7m";
string NOREVERSE = Console.IsOutputRedirected ? "" : "\x1b[27m";
Console.WriteLine($"This is {RED}Red{NORMAL}, {GREEN}Green{NORMAL}, {YELLOW}Yellow{NORMAL}, {BLUE}Blue{NORMAL}, {MAGENTA}Magenta{NORMAL}, {CYAN}Cyan{NORMAL}, {GREY}Grey{NORMAL}! ");
Console.WriteLine($"This is {BOLD}Bold{NOBOLD}, {UNDERLINE}Underline{NOUNDERLINE}, {REVERSE}Reverse{NOREVERSE}! ");
}
输出:
NOBOLD代码实际上是“正常强度”。详见维基百科链接页面上的“SGR(选择图形再现)参数”部分。
重定向测试避免将转义序列输出到文件中,如果输出被重定向。如果用户有一个非黑白配色方案,它将不会被重置,但你可以使用控制台功能来保存/恢复用户的配色方案在程序的开始和结束,如果这很重要的话。
其他回答
下面是一个优雅的实现,它使用了dotnet新的字符串插值特性。
[InterpolatedStringHandler]
public ref struct ConsoleInterpolatedStringHandler
{
private static readonly Dictionary<string, ConsoleColor> colors;
private readonly IList<Action> actions;
static ConsoleInterpolatedStringHandler() =>
colors = Enum.GetValues<ConsoleColor>().ToDictionary(x => x.ToString().ToLowerInvariant(), x => x);
public ConsoleInterpolatedStringHandler(int literalLength, int formattedCount)
{
actions = new List<Action>();
}
public void AppendLiteral(string s)
{
actions.Add(() => Console.Write(s));
}
public void AppendFormatted<T>(T t)
{
actions.Add(() => Console.Write(t));
}
public void AppendFormatted<T>(T t, string format)
{
if (!colors.TryGetValue(format, out var color))
throw new InvalidOperationException($"Color '{format}' not supported");
actions.Add(() =>
{
Console.ForegroundColor = color;
Console.Write(t);
Console.ResetColor();
});
}
internal void WriteLine() => Write(true);
internal void Write() => Write(false);
private void Write(bool newLine)
{
foreach (var action in actions)
action();
if (newLine)
Console.WriteLine();
}
}
要使用它,创建一个类,例如ExtendedConsole:
internal static class ExtendedConsole
{
public static void WriteLine(ConsoleInterpolatedStringHandler builder)
{
builder.WriteLine();
}
public static void Write(ConsoleInterpolatedStringHandler builder)
{
builder.Write();
}
}
然后,像这样使用它:
var @default = "default";
var blue = "blue";
var green = "green";
ExtendedConsole.WriteLine($"This should be {@default}, but this should be {blue:blue} and this should be {green:green}");
只是补充上面的答案,所有使用控制台。要改变同一行文本的颜色,可以这样写:
Console.Write("This test ");
Console.BackgroundColor = bTestSuccess ? ConsoleColor.DarkGreen : ConsoleColor.Red;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine((bTestSuccess ? "PASSED" : "FAILED"));
Console.ResetColor();
class Program
{
static void Main()
{
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("White on blue.");
Console.WriteLine("Another line.");
Console.ResetColor();
}
}
从这里拍的。
是的。请看这篇文章。这里有一个例子:
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("White on blue.");
上面的注释都是可靠的响应,但是注意它们不是线程安全的。如果您正在用多个线程写入控制台,更改颜色将添加一个竞争条件,可能会产生一些奇怪的输出。不过修复起来很简单:
public class ConsoleWriter
{
private static object _MessageLock= new object();
public void WriteMessage(string message)
{
lock (_MessageLock)
{
Console.BackgroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ResetColor();
}
}
}