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; 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 string line = [this.bar_prefix, bar, empty, this.bar_suffix, suffix].join(""); 42 this.write(line); 43 } 44 } 45 46 class ChargingBar : Bar 47 { 48 this() 49 { 50 super(); 51 bar_prefix = " "; 52 bar_suffix = " "; 53 empty_fill = "∙"; 54 fill = "█"; 55 suffix = { return this.percent.to!string() ~ "%"; }; 56 } 57 } 58 59 class FillingSquaresBar : ChargingBar 60 { 61 this() 62 { 63 super(); 64 empty_fill = "▢"; 65 fill = "▣"; 66 } 67 } 68 69 class FillingCirclesBar : ChargingBar 70 { 71 this() 72 { 73 super(); 74 empty_fill = "◯"; 75 fill = "◉"; 76 } 77 } 78 79 class IncrementalBar : Bar 80 { 81 string[] phases; 82 this() 83 { 84 super(); 85 phases = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"]; 86 } 87 88 override void force_update() 89 { 90 immutable size_t nphases = this.phases.length; 91 size_t expanded_length = cast(size_t)(nphases * this.width * this.progress); 92 size_t filled_length = cast(size_t)(this.width * this.progress); 93 size_t empty_length = this.width - filled_length; 94 size_t phase = expanded_length - (filled_length * nphases); 95 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 string line = [this.bar_prefix, bar, current, empty, this.bar_suffix, suffix].join(""); 101 this.write(line); 102 } 103 } 104 105 class ShadyBar : IncrementalBar 106 { 107 this() 108 { 109 super(); 110 phases = [" ", "░", "▒", "▓", "█"]; 111 } 112 }