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 }