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 }