using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; namespace CC_Functions.Commandline { /// /// Provides functions for parsing enumerables to powershell-like tables /// public static class TableParser { /// /// Parses the enumerable to a table using with the specified headers and transformed to strings with the specified /// selector /// /// The values to display /// The headers for columns /// Functions to get data for the cells /// The type of the elements in the enumerable /// The generated table public static string ToStringTable(this IEnumerable values, string[] columnHeaders, params Func[] valueSelectors) => ToStringTable(values.ToArray(), columnHeaders, valueSelectors); /// /// Parses the array to a table using with the specified headers and transformed to strings with the specified selector /// /// The values to display /// The headers for columns /// Functions to get data for the cells /// The type of the elements in the array /// The generated table public static string ToStringTable(this T[] values, string[] columnHeaders, params Func[] valueSelectors) { Debug.Assert(columnHeaders.Length == valueSelectors.Length); string[,] arrValues = new string[values.Length + 1, valueSelectors.Length]; // Fill headers for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) arrValues[0, colIndex] = columnHeaders[colIndex]; // Fill table rows for (int rowIndex = 1; rowIndex < arrValues.GetLength(0); rowIndex++) for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { object value = valueSelectors[colIndex].Invoke(values[rowIndex - 1]); arrValues[rowIndex, colIndex] = value != null ? value.ToString() : "null"; } return ToStringTable(arrValues); } /// /// Parses the array to a table /// /// The cells of the table /// The generated table public static string ToStringTable(this string[,] arrValues) { int[] maxColumnsWidth = GetMaxColumnsWidth(arrValues); string headerSpliter = new string('-', maxColumnsWidth.Sum(i => i + 3) - 1); StringBuilder sb = new StringBuilder(); for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++) { for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) { // Print cell string cell = arrValues[rowIndex, colIndex]; cell = cell.PadRight(maxColumnsWidth[colIndex]); sb.Append(" | "); sb.Append(cell); } // Print end of line sb.Append(" | "); sb.AppendLine(); // Print splitter if (rowIndex == 0) { sb.AppendFormat(" |{0}| ", headerSpliter); sb.AppendLine(); } } return sb.ToString(); } private static int[] GetMaxColumnsWidth(string[,] arrValues) { int[] maxColumnsWidth = new int[arrValues.GetLength(1)]; for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++) for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++) { int newLength = arrValues[rowIndex, colIndex].Length; int oldLength = maxColumnsWidth[colIndex]; if (newLength > oldLength) maxColumnsWidth[colIndex] = newLength; } return maxColumnsWidth; } /// /// Parses the enumerable to a table, transformed to strings with the specified selector /// /// The values to display /// Functions to get data for the cells /// The type of the elements in the enumerable /// The generated table public static string ToStringTable(this IEnumerable values, params Expression>[] valueSelectors) { string[] headers = valueSelectors.Select(func => GetProperty(func).Name).ToArray(); Func[] selectors = valueSelectors.Select(exp => exp.Compile()).ToArray(); return ToStringTable(values, headers, selectors); } private static PropertyInfo GetProperty(Expression> expresstion) { if (expresstion.Body is UnaryExpression expression) if (expression.Operand is MemberExpression memberExpression) return memberExpression.Member as PropertyInfo; if (expresstion.Body is MemberExpression body) return body.Member as PropertyInfo; return null; } } }