From 8e5bd41a477db743beca6bf43d31c9f7e745bd28 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 1 Dec 2023 13:17:46 +0100 Subject: [PATCH] allow using ANSI escape sequences for the console sink --- ExtremelySimpleLogger/ConsoleSink.cs | 16 +++++++--- ExtremelySimpleLogger/Extensions.cs | 45 ++++++++++++++++++++++++++++ Sample/Program.cs | 2 +- 3 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 ExtremelySimpleLogger/Extensions.cs diff --git a/ExtremelySimpleLogger/ConsoleSink.cs b/ExtremelySimpleLogger/ConsoleSink.cs index 8abe01e..880d29c 100644 --- a/ExtremelySimpleLogger/ConsoleSink.cs +++ b/ExtremelySimpleLogger/ConsoleSink.cs @@ -19,13 +19,16 @@ namespace ExtremelySimpleLogger { {LogLevel.Fatal, ConsoleColor.DarkRed} }; private readonly TextWriter console; + private readonly bool useAnsiCodes; /// /// Creates a new console sink with the given settings. /// /// Whether to log to instead of . - public ConsoleSink(bool error = false) { + /// Whether to wrap log output text in ANSI escape codes using instead of using the and . This may work better on some terminals. + public ConsoleSink(bool error = false, bool useAnsiCodes = false) { this.console = error ? Console.Error : Console.Out; + this.useAnsiCodes = useAnsiCodes; } /// @@ -65,10 +68,15 @@ namespace ExtremelySimpleLogger { protected override void Log(Logger logger, LogLevel level, string s) { lock (this.console) { var color = this.GetColor(level); - if (color.HasValue) - Console.ForegroundColor = color.Value; + if (color.HasValue) { + if (this.useAnsiCodes) { + s = s.WrapAnsiCode(color.Value); + } else { + Console.ForegroundColor = color.Value; + } + } this.console.WriteLine(s); - if (color.HasValue) + if (color.HasValue && !this.useAnsiCodes) Console.ResetColor(); } } diff --git a/ExtremelySimpleLogger/Extensions.cs b/ExtremelySimpleLogger/Extensions.cs new file mode 100644 index 0000000..7364d17 --- /dev/null +++ b/ExtremelySimpleLogger/Extensions.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; + +namespace ExtremelySimpleLogger { + /// + /// A set of extension methods for logging-related activities, like converting to ANSI color codes. + /// + public static class Extensions { + + private static readonly int[] AnsiCodes = new[] { + ConsoleColor.Black, ConsoleColor.DarkRed, ConsoleColor.DarkGreen, ConsoleColor.DarkYellow, + ConsoleColor.DarkBlue, ConsoleColor.DarkMagenta, ConsoleColor.DarkCyan, ConsoleColor.Gray, + ConsoleColor.DarkGray, ConsoleColor.Red, ConsoleColor.Green, ConsoleColor.Yellow, + ConsoleColor.Blue, ConsoleColor.Magenta, ConsoleColor.Cyan, ConsoleColor.White + }.Select((s, i) => (int) s).ToArray(); + + /// + /// Converts the given to its ANSI escape sequence representation. If the supplied is , the reset escape sequence for the given color type will be returned. + /// + /// The color. If , the reset escape sequence for the given color type will be returned. + /// Whether to return a background color. If this is , a foreground color is returned instead. + /// The ANSI escape sequence representation of the given . + /// If the is not in defined range. + public static string ToAnsiCode(this ConsoleColor? color, bool background = false) { + if (color.HasValue) { + if (color < 0 || (int) color >= Extensions.AnsiCodes.Length) + throw new ArgumentOutOfRangeException(nameof(color), color, null); + return $"\x1B[{(background ? 48 : 38)};5;{Extensions.AnsiCodes[(int) color]}m"; + } + return $"\x1B[{(background ? 49 : 39)}m"; + } + + /// + /// Wraps the given string in the ANSI escape sequence representation of the given and the appropriate reset escape sequence using . + /// + /// The string to wrap. + /// The color. + /// Whether to use as a background color. If this is , a foreground color is used instead. + /// The given string, wrapped in ANSI color codes. + public static string WrapAnsiCode(this string s, ConsoleColor color, bool background = false) { + return Extensions.ToAnsiCode(color, background) + s + Extensions.ToAnsiCode(null, background); + } + + } +} diff --git a/Sample/Program.cs b/Sample/Program.cs index 2620791..6f4b43a 100644 --- a/Sample/Program.cs +++ b/Sample/Program.cs @@ -12,7 +12,7 @@ namespace Sample { var sinks = new List { new FileSink("Log.txt", true), // We only want to log messages with a higher importance in the console - new ConsoleSink {MinimumLevel = LogLevel.Info}, + new ConsoleSink() {MinimumLevel = LogLevel.Info}, // we allow a total of 5 files in our directory sink before old ones start being deleted new DirectorySink("AllLogs", 5) };