1020304050607080901001101201301401501601701801902002102202302402502602702802903003103203303403503603703803904004104204304404504604704804905005105205305405505605705805906006106206306406506606706806907007107207307407507607707807908008108208308408508608708808909009109209309409509609709809901000101010201030104010501060107010801090110011101120 module trial.reporters.specprogress; import std.stdio; import std.array; import std.conv; import std.datetime; import std.algorithm; import trial.interfaces; import trial.reporters.writer; import trial.reporters.stats; import trial.reporters.spec; class SpecProgressReporter : SpecReporter, ISuiteLifecycleListener, ILifecycleListener { private { alias UpdateFunction = void delegate(CueInfo info); struct CueInfo { string id; string name; long duration; SysTime begin; } size_t oldTextLength; StatStorage storage; string[] path; CueInfo[] cues; } this(StatStorage storage) { super(); this.storage = storage; writer.writeln(""); } this(ReportWriter writer, StatStorage storage) { super(writer); this.storage = storage; writer.writeln(""); } void clearProgress() { writer.goTo(1); writer.write("\n" ~ " ".replicate(oldTextLength)); writer.goTo(1); oldTextLength = 0; } void begin(ulong) {} void end(SuiteResult[]) {} void update() { writer.hideCursor; auto now = Clock.currTime; auto progress = cues.map!(cue => "*[" ~ (cue.duration - (now - cue.begin).total!"seconds").to!string ~ "s]" ~ cue.name).join(" ").to!string; auto spaces = ""; if(oldTextLength > progress.length) { spaces = " ".replicate(oldTextLength - progress.length); } writer.goTo(1); writer.write("\n" ~ progress ~ spaces ~ " "); oldTextLength = progress.length; writer.showCursor; } void removeCue(string id) { cues = cues.filter!(a => a.id != id).array; } void begin(ref SuiteResult suite) { auto stat = storage.find(suite.name); auto duration = (stat.end - stat.begin).total!"seconds"; cues ~= CueInfo(suite.name, suite.name, duration, Clock.currTime); update; } void end(ref SuiteResult suite) { removeCue(suite.name); update; } override { void begin(string suite, ref TestResult test) { super.begin(suite, test); auto stat = storage.find(suite ~ "." ~ test.name); auto duration = (stat.end - stat.begin).total!"seconds"; cues ~= CueInfo(suite ~ "." ~ test.name, test.name, duration, Clock.currTime); update; } void end(string suite, ref TestResult test) { clearProgress; super.end(suite, test); removeCue(suite ~ "." ~ test.name); writer.writeln(""); update; } } }
module trial.reporters.specprogress; import std.stdio; import std.array; import std.conv; import std.datetime; import std.algorithm; import trial.interfaces; import trial.reporters.writer; import trial.reporters.stats; import trial.reporters.spec; class SpecProgressReporter : SpecReporter, ISuiteLifecycleListener, ILifecycleListener { private { alias UpdateFunction = void delegate(CueInfo info); struct CueInfo { string id; string name; long duration; SysTime begin; } size_t oldTextLength; StatStorage storage; string[] path; CueInfo[] cues; } this(StatStorage storage) { super(); this.storage = storage; writer.writeln(""); } this(ReportWriter writer, StatStorage storage) { super(writer); this.storage = storage; writer.writeln(""); } void clearProgress() { writer.goTo(1); writer.write("\n" ~ " ".replicate(oldTextLength)); writer.goTo(1); oldTextLength = 0; } void begin(ulong) {} void end(SuiteResult[]) {} void update() { writer.hideCursor; auto now = Clock.currTime; auto progress = cues.map!(cue => "*[" ~ (cue.duration - (now - cue.begin).total!"seconds").to!string ~ "s]" ~ cue.name).join(" ").to!string; auto spaces = ""; if(oldTextLength > progress.length) { spaces = " ".replicate(oldTextLength - progress.length); } writer.goTo(1); writer.write("\n" ~ progress ~ spaces ~ " "); oldTextLength = progress.length; writer.showCursor; } void removeCue(string id) { cues = cues.filter!(a => a.id != id).array; } void begin(ref SuiteResult suite) { auto stat = storage.find(suite.name); auto duration = (stat.end - stat.begin).total!"seconds"; cues ~= CueInfo(suite.name, suite.name, duration, Clock.currTime); update; } void end(ref SuiteResult suite) { removeCue(suite.name); update; } override { void begin(string suite, ref TestResult test) { super.begin(suite, test); auto stat = storage.find(suite ~ "." ~ test.name); auto duration = (stat.end - stat.begin).total!"seconds"; cues ~= CueInfo(suite ~ "." ~ test.name, test.name, duration, Clock.currTime); update; } void end(string suite, ref TestResult test) { clearProgress; super.end(suite, test); removeCue(suite ~ "." ~ test.name); writer.writeln(""); update; } } }