1 /++ 2 + License: MIT 3 +/ 4 5 module asciitable; 6 7 import std.string; 8 9 struct Row 10 { 11 string[] columns; 12 this(string[] data) 13 { 14 this.columns = data; 15 } 16 } 17 18 struct AsciiTable 19 { 20 ulong[] minimumWidths; 21 Row[] rows; 22 this(W...)(W minimumWidths) 23 { 24 this.minimumWidths = [minimumWidths]; 25 } 26 27 AsciiTable add(V...)(V values) 28 { 29 if (values.length != minimumWidths.length) 30 { 31 throw new Exception("All rows must have length %s".format(minimumWidths.length)); 32 } 33 rows ~= Row([values]); 34 return this; 35 } 36 37 string toString(string linePrefix = "") 38 { 39 import std.algorithm; 40 import std.string; 41 42 foreach (row; rows) 43 { 44 foreach (idx, column; row.columns) 45 { 46 minimumWidths[idx] = max(minimumWidths[idx], column.length + 1); 47 } 48 } 49 string res = ""; 50 foreach (row; rows) 51 { 52 if (res.length > 0) 53 { 54 res ~= "\n"; 55 } 56 res ~= linePrefix; 57 foreach (idx, column; row.columns) 58 { 59 res ~= leftJustify(column, minimumWidths[idx], ' '); 60 } 61 } 62 return res; 63 } 64 } 65 66 @("asciitable") unittest 67 { 68 import unit_threaded; 69 70 auto table = AsciiTable(10, 3, 5); 71 table.add("1", "2", "3"); 72 table.add("4", "5", "6"); 73 table.toString.shouldEqual("1 2 3 \n" ~ "4 5 6 \n"); 74 }