histogram: --format C implemented.
This commit is contained in:
parent
0ccf2cef20
commit
f5e838293c
|
@ -97,6 +97,9 @@ value. B<--values-before-headers> looks the header after the value.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
(echo 150 hundredfifty;echo 30 thirty;echo 3 three;echo 6 six)|./histogram --format Hbcp
|
||||||
|
(echo 0 zero; echo 50 fifty; echo 150 hundredfifty;echo 130 hundredthirty;echo 3 three;echo 6 six)|./histogram --format HbHCP
|
||||||
|
ls -l|tail -n +2| ./histogram --input iiiiviiih
|
||||||
|
|
||||||
=head1 EXAMPLE: git: number of commits in the last year, by author
|
=head1 EXAMPLE: git: number of commits in the last year, by author
|
||||||
|
|
||||||
|
@ -297,10 +300,6 @@ use Getopt::Long;
|
||||||
|
|
||||||
GetOptions
|
GetOptions
|
||||||
("delimiter|d=s" => \$opt::delimiter,
|
("delimiter|d=s" => \$opt::delimiter,
|
||||||
"values-as-headers|t" => \$opt::vash,
|
|
||||||
"values-before-headers|b" => \$opt::vbh,
|
|
||||||
"pre" => \$opt::pre,
|
|
||||||
"post" => \$opt::post,
|
|
||||||
"log" => \$opt::log,
|
"log" => \$opt::log,
|
||||||
"input|i=s" => \$opt::input,
|
"input|i=s" => \$opt::input,
|
||||||
"format|f=s" => \$opt::format,
|
"format|f=s" => \$opt::format,
|
||||||
|
@ -344,6 +343,7 @@ if(not defined $opt::input) {
|
||||||
parse_raw_given_opt_input($opt::input, @raw);
|
parse_raw_given_opt_input($opt::input, @raw);
|
||||||
}
|
}
|
||||||
my $max_value = max(@$value_ref);
|
my $max_value = max(@$value_ref);
|
||||||
|
my $total_value = sum(@$value_ref);
|
||||||
|
|
||||||
sub parse_raw_given_opt_input {
|
sub parse_raw_given_opt_input {
|
||||||
my ($input,@raw) = @_;
|
my ($input,@raw) = @_;
|
||||||
|
@ -381,7 +381,7 @@ sub parse_raw_given_opt_input {
|
||||||
}
|
}
|
||||||
my $regexp = join("",@regexp_part);
|
my $regexp = join("",@regexp_part);
|
||||||
for my $rawline (@raw) {
|
for my $rawline (@raw) {
|
||||||
$rawline =~ /$regexp/ || die;
|
$rawline =~ /$regexp/ || die("$regexp not matching $rawline");
|
||||||
if(defined $2) {
|
if(defined $2) {
|
||||||
if($first_meta_var eq "v") {
|
if($first_meta_var eq "v") {
|
||||||
# value,header
|
# value,header
|
||||||
|
@ -410,14 +410,9 @@ sub parse_raw_given_opt_input {
|
||||||
return ($max_value_length, $max_header_length, $max_value_header_length, \@header, \@value);
|
return ($max_value_length, $max_header_length, $max_value_header_length, \@header, \@value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#print "header ",@$header_ref,"\n";
|
|
||||||
#print "value ",@$value_ref,"\n";
|
|
||||||
|
|
||||||
my $term_width = terminal_width();
|
my $term_width = terminal_width();
|
||||||
|
|
||||||
# --format hVb%
|
my $format = ($opt::format || "Vbhp");
|
||||||
# --format Vhb%
|
|
||||||
my $format = ($opt::format || "vbhp");
|
|
||||||
my ($front, $end) = split /b/, $format;
|
my ($front, $end) = split /b/, $format;
|
||||||
my ($front_inside, $front_outside) = ($front,$front);
|
my ($front_inside, $front_outside) = ($front,$front);
|
||||||
$front_inside =~ s/[a-z]//g; # Remove outsides
|
$front_inside =~ s/[a-z]//g; # Remove outsides
|
||||||
|
@ -433,12 +428,14 @@ for(my $i = 0; $i <= $#$value_ref; $i++) {
|
||||||
my %end_repl = (
|
my %end_repl = (
|
||||||
'V' => sprintf(" %".$max_value_length."s",$value),
|
'V' => sprintf(" %".$max_value_length."s",$value),
|
||||||
'H' => sprintf(" %".$max_header_length."s",$header),
|
'H' => sprintf(" %".$max_header_length."s",$header),
|
||||||
'P' => sprintf(" %3d%%",int($value/$max_value*100)),
|
'P' => sprintf(" %3d%%",int($value/$max_value*100+0.5)),
|
||||||
|
'C' => sprintf(" %3d%%",int($value/$total_value*100+0.5)),
|
||||||
);
|
);
|
||||||
my %front_repl = (
|
my %front_repl = (
|
||||||
'V' => sprintf("%".$max_value_length."s ",$value),
|
'V' => sprintf("%".$max_value_length."s ",$value),
|
||||||
'H' => sprintf("%-".$max_header_length."s ",$header),
|
'H' => sprintf("%-".$max_header_length."s ",$header),
|
||||||
'P' => sprintf("%3d%% ",int($value/$max_value*100)),
|
'P' => sprintf("%3d%% ",int($value/$max_value*100+0.5)),
|
||||||
|
'C' => sprintf(" %3d%%",int($value/$total_value*100+0.5)),
|
||||||
);
|
);
|
||||||
my $front_outside_string = $front_outside;
|
my $front_outside_string = $front_outside;
|
||||||
$front_outside_string =~ s/(.)/$front_repl{uc($1)}/g;
|
$front_outside_string =~ s/(.)/$front_repl{uc($1)}/g;
|
||||||
|
@ -450,66 +447,16 @@ for(my $i = 0; $i <= $#$value_ref; $i++) {
|
||||||
$end_inside_string =~ s/(.)/$end_repl{uc($1)}/g;
|
$end_inside_string =~ s/(.)/$end_repl{uc($1)}/g;
|
||||||
|
|
||||||
my $bar_length = $term_width - length($front_outside_string) - length($end_outside_string);
|
my $bar_length = $term_width - length($front_outside_string) - length($end_outside_string);
|
||||||
|
my $factor;
|
||||||
my $bar = bar_string($bar_length-1, $value/$max_value,$front_inside_string,$end_inside_string);
|
|
||||||
print $front_outside_string,"$bar",$end_outside_string,"\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#term_width - (max_size_front + max_size_end);
|
|
||||||
|
|
||||||
|
|
||||||
my(@header) = @$header_ref;
|
|
||||||
my(@value) = @$value_ref;
|
|
||||||
my $has_header = 0;
|
|
||||||
my $i = 0;
|
|
||||||
for(@raw) {
|
|
||||||
if($opt::vbh) {
|
|
||||||
if(s/^\s*(\d+(\.\d+)?([eE][-+]?\d+)?)\s*//) {
|
|
||||||
push(@value, eval $1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(s/\s*(\d+(\.\d+)?([eE][-+]?\d+)?)\s*$//) {
|
|
||||||
push(@value, eval $1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(/\S/) {
|
|
||||||
$header[$i] = $_;
|
|
||||||
$i++;
|
|
||||||
if(not $opt::pre and not $opt::post) {
|
|
||||||
# There is a header, so you probably want it printed
|
|
||||||
$opt::pre = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($opt::vash or not @header) {
|
|
||||||
@header = @value;
|
|
||||||
} else {
|
|
||||||
$header[$#value+1]="";
|
|
||||||
@header = map { defined $_ ? $_ : "" } @header;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($opt::log) {
|
if($opt::log) {
|
||||||
@value = map { $_ > 0 ? log($_) : 0 } @value;
|
$factor = log($value)/log($max_value);
|
||||||
|
} else {
|
||||||
|
$factor = $value/$max_value;
|
||||||
|
}
|
||||||
|
my $bar = bar_string($bar_length-1, $factor, $front_inside_string, $end_inside_string);
|
||||||
|
print $front_outside_string, $bar, $end_outside_string, "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $max = max(@value);
|
|
||||||
my @header_len = map { length $_ } @header;
|
|
||||||
my $max_header_len = max(@header_len) || 0;
|
|
||||||
|
|
||||||
for(my $i = 0; $i <= $#value; $i++) {
|
|
||||||
if($opt::pre) {
|
|
||||||
if($opt::post) {
|
|
||||||
bar($header[$i]." ",$value[$i]," ".$header[$i],$max,$max_header_len);
|
|
||||||
} else {
|
|
||||||
bar($header[$i]." ",$value[$i],"",$max,$max_header_len);
|
|
||||||
}
|
|
||||||
} elsif($opt::post) {
|
|
||||||
bar("",$value[$i]," ".$header[$i],$max,$max_header_len);
|
|
||||||
} else {
|
|
||||||
bar("",$value[$i],"",$max,$max_header_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub max {
|
sub max {
|
||||||
# Returns:
|
# Returns:
|
||||||
|
@ -524,6 +471,19 @@ sub max {
|
||||||
return $max;
|
return $max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub sum {
|
||||||
|
# Returns:
|
||||||
|
# Sum of values of array
|
||||||
|
my @args = @_;
|
||||||
|
my $sum = 0;
|
||||||
|
for (@args) {
|
||||||
|
# Skip undefs
|
||||||
|
$_ and do { $sum += $_; }
|
||||||
|
}
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $columns;
|
my $columns;
|
||||||
|
|
||||||
|
@ -540,16 +500,18 @@ sub max {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub bar_string {
|
sub bar_string {
|
||||||
my ($width,$factor,$front,$end) = @_;
|
my ($width,$factor,$front,$end) = @_;
|
||||||
my @eight = (qw(█ ▉ ▊ ▋ ▌ ▍ ▎ ▏));
|
my @eight = (qw(█ ▉ ▊ ▋ ▌ ▍ ▎ ▏));
|
||||||
my $l = $width * $factor;
|
my $l = $width * $factor;
|
||||||
|
my $partial;
|
||||||
my $black = int($l);
|
my $black = int($l);
|
||||||
my $white = $width-int($l);
|
my $white = $width-int($l);
|
||||||
# $front="F".$front;
|
|
||||||
# $end=$end."E";
|
|
||||||
my $rev = '[7m';
|
my $rev = '[7m';
|
||||||
my $reset = '[0m';
|
my $reset = '[0m';
|
||||||
|
$front =~ s/ *$//;
|
||||||
|
$end =~ s/^ *//;
|
||||||
if(length $front < $black) {
|
if(length $front < $black) {
|
||||||
# Paint $front reverse
|
# Paint $front reverse
|
||||||
$black -= length $front;
|
$black -= length $front;
|
||||||
|
@ -557,11 +519,10 @@ sub bar_string {
|
||||||
$front = $rev . $front . $reset;
|
$front = $rev . $front . $reset;
|
||||||
} else {
|
} else {
|
||||||
# label overlaps white
|
# label overlaps white
|
||||||
# TODO reverse the first $black chars
|
|
||||||
$white = $width - length $front;
|
$white = $width - length $front;
|
||||||
$front = $rev . substr($front,0,$black). $reset.substr($front,$black);
|
$front = $rev . substr($front,0,$black). $reset.substr($front,$black);
|
||||||
$black = 0;
|
$black = 0;
|
||||||
$l = 0;
|
$partial = " ";
|
||||||
}
|
}
|
||||||
if(length $end < $white) {
|
if(length $end < $white) {
|
||||||
# Just append $end
|
# Just append $end
|
||||||
|
@ -569,36 +530,17 @@ sub bar_string {
|
||||||
$width -= length $end;
|
$width -= length $end;
|
||||||
} else {
|
} else {
|
||||||
# label overlaps black
|
# label overlaps black
|
||||||
# TODO reverse the first length($end)-$white chars
|
$black = $width - length($end);
|
||||||
$black = $width - (length($end)-$white);
|
|
||||||
$end = $rev . substr($end,0,length($end)-$white). $reset.substr($end,length($end)-$white);
|
$end = $rev . substr($end,0,length($end)-$white). $reset.substr($end,length($end)-$white);
|
||||||
$white = 0;
|
$white = 0;
|
||||||
$l = 0.9;
|
$partial = $eight[0];
|
||||||
}
|
}
|
||||||
my $middle = ($eight[0] x $black). ($eight[7-(int($l*8))%8]). (" "x$white);
|
$partial ||= ($eight[7-(int($l*8))%8]);
|
||||||
|
my $middle = ($eight[0] x $black). $partial . (" "x$white);
|
||||||
|
|
||||||
return $front . $middle . $end;
|
return $front . $middle . $end;
|
||||||
|
|
||||||
|
|
||||||
# return( ($eight[0] x int($l)). ($eight[7-(int($l*8))%8]). (" "x($width-int($l))) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bar {
|
|
||||||
my ($pre,$v,$post,$max,$max_header_len) = @_;
|
|
||||||
my @eight = qw(█ ▉ ▊ ▋ ▌ ▍ ▎ ▏);
|
|
||||||
push @eight,"";
|
|
||||||
my $header_len = ($pre ? $max_header_len+1 : 0) + ($post ? $max_header_len+1 : 0);
|
|
||||||
my $width = terminal_width()-$header_len;
|
|
||||||
my $factor = $width/$max;
|
|
||||||
my $l = $v*$factor;
|
|
||||||
my $pres = "";
|
|
||||||
|
|
||||||
if($pre) {
|
|
||||||
$pres = sprintf("%".($max_header_len+1)."s",$pre)
|
|
||||||
}
|
|
||||||
|
|
||||||
# print $pres,$eight[0] x $l, $eight[8-($l*8)%8],$post,"\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub guess_delimiter {
|
sub guess_delimiter {
|
||||||
my @raw = @_;
|
my @raw = @_;
|
||||||
|
|
Loading…
Reference in a new issue