/
StatusBar.pm6
97 lines (84 loc) · 2.71 KB
/
StatusBar.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
unit module Zef::CLI::StatusBar;
sub CLI-WAITING-BAR(&code, $status, Bool :$boring) is export {
say "===> $status" and return code() if $boring;
my $promise = Promise.new;
my $vow = $promise.vow;
my $await = start { show-await($status, $promise) };
my $retval = code();
$vow.keep(1);
await $await;
$retval;
}
# This works *much* better when using "\r" instead of some number of "\b"
# Unfortunately MoarVM on Windows has a bug where it prints "\r" as if it were "\n"
# (JVM is OK on windows, JVM/Moar are ok on linux)
sub show-await($message, *@promises) {
my $loading = Supply.interval(1);
my $out = $*OUT;
my $err = $*ERR;
my $in = $*IN;
my $last-line-len = 0;
$*ERR = $*OUT = class :: {
my $lock = Lock.new;
my ($e, $m, $n, $d);
$loading.tap(
{
$e = do given ++$m {
when 2 { '-==' }
when 3 { '=-=' }
when 4 { '==-' }
default { $m = 1; '===' }
}
$d = do given ++$n {
when 2 { '. ' }
when 3 { '.. ' }
when 4 { '...' }
when 5 { '.. ' }
when 6 { '. ' }
default { $n = 1; ' ' }
}
print r-print('');
},
done => { print r-print(''); },
closing => { print r-print(''); },
);
method print(*@_) {
if @_ {
my $lines = @_.join;
$lock.protect({
my $out2 = $*OUT;
$*ERR = $*OUT = $out;
if $lines.chars {
my $line = r-print($lines.trim-trailing, :$last-line-len);
$line ~= "\n";
print $line;
$last-line-len = 0;
}
my $msg = "$e> $message$d";
my $status-bar = r-print($msg, :$last-line-len);
print $status-bar;
$last-line-len = $msg.chars;
$*ERR = $*OUT = $out2;
});
}
}
method flush {}
}
await Promise.allof: @promises;
$loading.close;
$*ERR = $err;
$*OUT = $out;
print r-print("===> $message [done]\n", :$last-line-len);
}
sub fake-carriage($len) { my Str $str = ("\b" x $len) || ''; ~$str }
sub clear-line($len) { my Str $str = (" " x $len) || ''; ~$str }
sub r-print($str = '', :$last-line-len = 0) {
if $last-line-len {
my $fc = fake-carriage($last-line-len);
my $cl = clear-line($last-line-len);
my $ret = "$fc$cl$fc$str";
}
else {
return $str;
}
}