1 module nxt.show; 2 3 import nxt.algorithm_ex: overlap; 4 5 /** Show Format. */ 6 enum Format { Text, HTML, }; 7 8 @trusted void browse(Args...)(string[] names, inout (Args) args) { 9 return fshow(Format.HTML, names, args); 10 } 11 @trusted void show(Args...)(string[] names, inout (Args) args) { 12 return fshow(Format.Text, names, args); 13 } 14 15 /** Group-Aligned Show of Slices `args`. 16 17 Copyright: Per Nordlöw 2014-. 18 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 19 Authors: $(WEB Per Nordlöw) 20 21 Use as debug print in algorithms where we need to present slices and their 22 relations. 23 24 TODO Calculate `names` from `args` or `args` from `names` using Mixins. 25 TODO Generalize to Ranges other than slices!? 26 TODO Support HTML 27 */ 28 @trusted void fshow(Args...)(Format format, string[] names, inout (Args) args) 29 { 30 import std.stdio: wr = write, wrln = writeln; 31 import std.algorithm: map, reduce, min, max; 32 import std.range : repeat, join; 33 import std..string: leftJustify, rightJustify; 34 import std.conv: to; 35 36 // determine overlap 37 static if (args.length == 2) { 38 const a01 = overlap(args[0], args[1]); 39 } 40 41 // maximum variable name length 42 const namesLengthMax = names.map!"a.length".reduce!max; 43 44 // smallest slice pointer 45 static if (true) { // if all args of same type 46 } 47 static if (args.length == 2) { auto unionPtr = min(args[0].ptr, args[1].ptr); } 48 static if (args.length == 3) { auto unionPtr = min(args[0].ptr, args[1].ptr, args[2].ptr); } 49 static if (args.length == 4) { auto unionPtr = min(args[0].ptr, args[1].ptr, args[2].ptr, args[3].ptr); } 50 51 // calculate maximum length of number 52 auto elementLengthMax = size_t.min; 53 size_t[][args.length] elementOffsets; // element offsets 54 string[][args.length] elementStrings_; 55 foreach (ix, arg; args) { 56 auto elementStrings = arg.map!(to!string); // calculate lengths of elements as strings 57 elementLengthMax = elementStrings.map!"a.length".reduce!max; // length of longest number as string 58 elementOffsets[ix] = new size_t[arg.length]; 59 } 60 61 // print arguments 62 foreach (ix, arg; args) { // for each argument 63 enum sep = ", "; // separator 64 const off = arg.ptr - unionPtr; // offset 65 wr(names[ix].leftJustify(namesLengthMax), ": "); // name header 66 if (off) { 67 wr(" ".repeat(1 + (off + 1) * sep.length + 68 off * namesLengthMax).join); 69 } 70 foreach (elt; arg) { 71 wr(to!string(elt).rightJustify(namesLengthMax), sep); 72 } 73 wrln(""); 74 } 75 76 // print overlaps 77 static if (args.length == 2) { 78 /* wrln("overlap(", names[0], ",", names[1], "): ", a01); */ 79 } 80 static if (args.length == 3) { 81 foreach (i, arg; args) { 82 enum j = (i+1) % args.length; 83 /* wrln("overlap(" ~ names[i].leftJustify(namesLengthMax) ~ ", " ~ names[j].leftJustify(namesLengthMax) ~ "): ", overlap(args[i], args[j])); */ 84 } 85 } 86 wrln(""); 87 } 88 unittest { 89 auto x = [-11111, -11, 22, 333333]; 90 91 auto x01 = x[0..1]; 92 auto x12 = x[1..2]; 93 auto x23 = x[2..3]; 94 auto x34 = x[3..4]; 95 96 show(["x12", "x"], x12, x); 97 show(["x", "x12"], x, x12); 98 show(["x", "x12", "x23"], x, x12, x23); 99 show(["x", "x23", "x12", "x34"], x, x23, x12, x34); 100 }