写一个小的命令行工具,用不同的颜色输出会很好。这可能吗?


当前回答

我只是想在使用console。writeline()时调整文本颜色; 所以我不得不写

Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("my message");
Console.ResetColor();

每次我想写点什么

所以我发明了我的WriteLine()方法,并一直在Program类中使用它而不是console。

public static void WriteLine(string buffer, ConsoleColor foreground = ConsoleColor.DarkGreen, ConsoleColor backgroundColor = ConsoleColor.Black)
{
   Console.ForegroundColor = foreground;
   Console.BackgroundColor = backgroundColor;
   Console.WriteLine(buffer);
   Console.ResetColor();
}

为了让它更简单,我还写了一个Readline()方法,像这样:

public static string ReadLine()
{
   var line = Console.ReadLine();
   return line ?? string.Empty;
}

现在我们要做的就是在控制台中写入或读取一些东西:

static void Main(string[] args) {
   WriteLine("hello this is a colored text");
   var answer = Readline();
}

其他回答

是的,可能如下所示。这些颜色可以在控制台应用程序中使用,以红色等方式查看一些错误。

Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;//after this line every text will be white on blue background
Console.WriteLine("White on blue.");
Console.WriteLine("Another line.");
Console.ResetColor();//reset to the defoult colour

下面是我编写的一个简单方法,用于编写带有内联颜色变化的控制台消息。它只支持一种颜色,但它符合我的需要。

// usage: WriteColor("This is my [message] with inline [color] changes.", ConsoleColor.Yellow);
static void WriteColor(string message, ConsoleColor color)
{
    var pieces = Regex.Split(message, @"(\[[^\]]*\])");

    for(int i=0;i<pieces.Length;i++)
    {
        string piece = pieces[i];
        
        if (piece.StartsWith("[") && piece.EndsWith("]"))
        {
            Console.ForegroundColor = color;
            piece = piece.Substring(1,piece.Length-2);          
        }
        
        Console.Write(piece);
        Console.ResetColor();
    }
    
    Console.WriteLine();
}

我发现给控制台输出片段着色的最简单方法是在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}");

上面的注释都是可靠的响应,但是注意它们不是线程安全的。如果您正在用多个线程写入控制台,更改颜色将添加一个竞争条件,可能会产生一些奇怪的输出。不过修复起来很简单:

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();
        }
    }
}