1 module progress.bar; 2 3 import progress; 4 5 static import std.algorithm; 6 import std.array : back, join; 7 import std.conv : to, text; 8 import std.format : format; 9 10 class Bar : Progress 11 { 12 size_t width = 32; 13 string delegate() suffix; 14 string bar_prefix; 15 string bar_suffix; 16 string empty_fill; 17 string fill; 18 19 this() 20 { 21 width = 32; 22 bar_prefix = " |"; 23 bar_suffix = "| "; 24 empty_fill = " "; 25 fill = "#"; 26 hide_cursor = true; 27 this.message = { return ""; }; 28 this.suffix = { return format!"%s/%s"(this.index, this.max); }; 29 if (hide_cursor) 30 file.write(HIDE_CURSOR); 31 } 32 33 override void force_update() 34 { 35 size_t filled_length = cast(size_t)(this.width * this.progress); 36 size_t empty_length = this.width - filled_length; 37 string message = this.message(); 38 string bar = repeat(this.fill, filled_length); 39 string empty = repeat(this.empty_fill, empty_length); 40 string suffix_ = this.suffix(); 41 this.writeln(message, this.bar_prefix, bar, empty, this.bar_suffix, suffix_); 42 } 43 } 44 45 class ChargingBar : Bar 46 { 47 this() 48 { 49 super(); 50 bar_prefix = " "; 51 bar_suffix = " "; 52 empty_fill = "∙"; 53 fill = "█"; 54 suffix = { return text(this.percent, '%'); }; 55 } 56 } 57 58 class FillingSquaresBar : ChargingBar 59 { 60 this() 61 { 62 super(); 63 empty_fill = "▢"; 64 fill = "▣"; 65 } 66 } 67 68 class FillingCirclesBar : ChargingBar 69 { 70 this() 71 { 72 super(); 73 empty_fill = "◯"; 74 fill = "◉"; 75 } 76 } 77 78 class IncrementalBar : Bar 79 { 80 string[] phases; 81 this() 82 { 83 super(); 84 phases = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"]; 85 } 86 87 override void force_update() 88 { 89 immutable size_t nphases = this.phases.length; 90 size_t expanded_length = cast(size_t)(nphases * this.width * this.progress); 91 size_t filled_length = cast(size_t)(this.width * this.progress); 92 size_t empty_length = this.width - filled_length; 93 size_t phase = expanded_length - (filled_length * nphases); 94 95 string message = this.message(); 96 string bar = repeat(phases.back, filled_length); 97 string current = (phase <= nphases) ? this.phases[phase] : ""; 98 string empty = repeat(this.empty_fill, std.algorithm.max(0, empty_length)); 99 string suffix_ = this.suffix(); 100 this.writeln(message, this.bar_prefix, bar, current, empty, this.bar_suffix, suffix_); 101 } 102 } 103 104 class ShadyBar : IncrementalBar 105 { 106 this() 107 { 108 super(); 109 phases = [" ", "░", "▒", "▓", "█"]; 110 } 111 }