private static void TryWriteFootnotes(this StandardStreamWriter stream, string?footnotes) { if (!string.IsNullOrWhiteSpace(footnotes)) { stream.WithForegroundColor(ConsoleColor.DarkGray, (o) => o.WriteLine(TextUtils.AdjustNewLines(footnotes))); stream.WriteLine(); } }
private static void WriteTableHeader(this StandardStreamWriter stream, IEnumerable <string> headers, int[] columnWidths, int totalWidth) { if (headers.Any()) { for (int i = 0; i < columnWidths.Length; ++i) { string header = headers.ElementAtOrDefault(i) ?? string.Empty; int targetWidth = columnWidths[i]; stream.Write(' '); stream.WithForegroundColor(ConsoleColor.DarkYellow, (o) => o.Write(header.PadRight(targetWidth))); if (i + 1 < columnWidths.Length) { stream.WithForegroundColor(ConsoleColor.Magenta, (o) => o.Write(" |")); } } stream.WriteLine(); //Write middle line stream.WriteBorder(totalWidth); } }
/// <summary> /// Writes a table to the console. /// </summary> public static void Write <TKey, TElement>(StandardStreamWriter stream, IEnumerable <IGrouping <TKey, TElement> > collection, IEnumerable <string> headers, string?footnotes, params Expression <Func <TElement, string> >[] values) { int columnsCount = values.Length; Func <TElement, string>[] columnFunctions = values.Select(x => x.Compile()) .ToArray(); int[] columnWidths = (from cf in columnFunctions let x = (collection.Any() ? collection.SelectMany(x => x).Select(cf).Max(x => x.Length) : 0) select x).ToArray(); AdjustColumnWidths(headers, columnsCount, columnWidths); int totalWidth = columnWidths.Sum() - 1 + (columnsCount) * 3; //Write top border stream.WriteBorder(totalWidth); stream.WriteTableHeader(headers, columnWidths, totalWidth); foreach (IGrouping <TKey, TElement> group in collection) { TKey groupKey = group.Key; int countInGroup = group.Count(); stream.WriteBorder(totalWidth, '-'); stream.WithForegroundColor(ConsoleColor.DarkYellow, (o) => o.WriteLine($" {groupKey} ({countInGroup}) ".PadBoth(totalWidth))); stream.WriteBorder(totalWidth, '-'); //Write table body stream.WriteTableBody(group, columnFunctions, columnWidths); } // Write bottom border and try write footnotes stream.WriteBorder(totalWidth); stream.TryWriteFootnotes(footnotes); }
private static void WriteTableBody <TElement>(this StandardStreamWriter stream, IEnumerable <TElement> collection, Func <TElement, string>[] columnFunctions, int[] columnWidths) { foreach (TElement item in collection) { for (int i = 0; i < columnWidths.Length; ++i) { Func <TElement, string> column = columnFunctions[i]; stream.Write(' '); string value = columnFunctions[i].Invoke(item); int targetWidth = columnWidths[i]; stream.Write(value.PadRight(targetWidth)); if (i + 1 < columnWidths.Length) { stream.WithForegroundColor(ConsoleColor.Magenta, (o) => o.Write(" |")); } } stream.WriteLine(); } }
private static void WriteException(this StandardStreamWriter output, Exception exception, int indentLevel) { Type exceptionType = exception.GetType(); string indentationShared = new string(' ', 4 * indentLevel); string indentationLocal = new string(' ', 2); // Fully qualified exception type output.Write(indentationShared); output.WithForegroundColor(ConsoleColor.DarkGray, (o) => { o.Write(exceptionType.Namespace); o.Write('.'); }); output.WithForegroundColor(ConsoleColor.White, (o) => o.Write(exceptionType.Name)); output.Write(": "); // Exception message output.WithForegroundColor(ConsoleColor.Red, (o) => o.WriteLine(exception.Message)); // Recurse into inner exceptions if (exception.InnerException is not null) { output.WriteException(exception.InnerException, indentLevel + 1); } if (exception.StackTrace is null) { return; } // Try to parse and pretty-print the stack trace try { foreach (StackFrame stackFrame in StackTraceParser.ParseMany(exception.StackTrace)) { output.Write(indentationShared); output.Write(indentationLocal); output.WithForegroundColor(ConsoleColor.Green, (o) => o.Write("at ")); // "Typin.Demo.Commands.BookAddCommand." output.WithForegroundColor(ConsoleColor.DarkGray, (o) => { o.Write(stackFrame.ParentType); o.Write('.'); }); // "ExecuteAsync" output.WithForegroundColor(ConsoleColor.Yellow, (o) => o.Write(stackFrame.MethodName)); output.Write('('); for (int i = 0; i < stackFrame.Parameters.Count; ++i) { StackFrameParameter parameter = stackFrame.Parameters[i]; // "IConsole" output.WithForegroundColor(ConsoleColor.Blue, (o) => o.Write(parameter.Type)); if (!string.IsNullOrWhiteSpace(parameter.Name)) { output.Write(' '); // "console" output.WithForegroundColor(ConsoleColor.White, (o) => o.Write(parameter.Name)); } // Separator if (stackFrame.Parameters.Count > 1 && i < stackFrame.Parameters.Count - 1) { output.Write(", "); } } output.Write(") "); // Location if (!string.IsNullOrWhiteSpace(stackFrame.FilePath)) { output.WithForegroundColor(ConsoleColor.Magenta, (o) => o.Write("in")); output.WriteLine(); output.Write(indentationShared); output.Write(indentationLocal); output.Write(indentationLocal); // "C:\Projects\Typin\Typin.Demo\Commands\" var stackFrameDirectoryPath = Path.GetDirectoryName(stackFrame.FilePath); output.WithForegroundColor(ConsoleColor.DarkGray, (o) => { o.Write(stackFrameDirectoryPath); o.Write(Path.DirectorySeparatorChar); }); // "BookAddCommand.cs" string stackFrameFileName = Path.GetFileName(stackFrame.FilePath) ?? string.Empty; output.WithForegroundColor(ConsoleColor.Cyan, (o) => o.Write(stackFrameFileName)); if (!string.IsNullOrWhiteSpace(stackFrame.LineNumber)) { output.Write(':'); // "35" output.WithForegroundColor(ConsoleColor.Magenta, (o) => o.Write(stackFrame.LineNumber)); } } output.WriteLine(); } } // If any point of parsing has failed - print the stack trace without any formatting catch { output.WriteLine(exception.StackTrace); } }
private static void WriteBorder(this StandardStreamWriter stream, int totalWidth, char ch = '=') { stream.WithForegroundColor(ConsoleColor.Magenta, (o) => o.WriteLine(new string(ch, totalWidth))); }