Commit | Line | Data |
---|---|---|
cce87900 TF |
1 | #!/usr/bin/perl |
2 | ||
3 | use warnings; | |
4 | use strict; | |
5 | ||
6 | use Getopt::Long qw{:config gnu_getopt posix_default}; | |
37fadc81 | 7 | use POSIX; |
cce87900 TF |
8 | use Term::ReadKey; |
9 | ||
10 | $0 =~ s{^.*/([^/]+)$}{$1}; | |
11 | ||
cce87900 TF |
12 | my %opt; |
13 | GetOptions(\%opt, qw{ | |
37fadc81 | 14 | cancel|c |
ebb589a0 | 15 | height|h=i |
37fadc81 TF |
16 | overlay|o |
17 | stack|s | |
dcf5f346 | 18 | width|w=i |
cb209060 TF |
19 | }) or do { |
20 | print STDERR <<END; | |
21 | usage: git-graph [options] | |
22 | -c | --cancel +/- counts cancel out | |
23 | -o | --overlay +/- counts are overlaid as # (default) | |
24 | -s | --cancel +/- counts are stacked | |
25 | --height [n] Set height of graph | |
26 | -h [n] (height of terminal is default) | |
27 | --width [n] Set horizontal scale | |
28 | -w [n] (fit to width of terminal by default) | |
29 | END | |
30 | exit 1; | |
31 | }; | |
cce87900 | 32 | |
22e04a63 | 33 | $opt{overlay} = 1 unless $opt{cancel} or $opt{stack}; |
cce87900 | 34 | |
37fadc81 | 35 | my @terminal = GetTerminalSize; |
c562dc48 | 36 | my $width = $terminal[0] - 11; |
ebb589a0 | 37 | my $height = $opt{height} // $terminal[1] - 2; |
37fadc81 | 38 | |
cce87900 TF |
39 | my %add; |
40 | my %del; | |
41 | ||
42 | my $addmax = 0; | |
43 | my $delmax = 0; | |
44 | my $canmax = 0; | |
45 | ||
c562dc48 TF |
46 | my $date; |
47 | ||
dc5e876a | 48 | for (qx{git log --find-renames --shortstat --pretty=format:%ct --since='$height days ago'}) { |
c562dc48 TF |
49 | next if m{^\s*$}; |
50 | if (m{^(\d{10})\n$}) { | |
51 | $date = int ($1 / 86400); | |
52 | next; | |
53 | } | |
54 | m{^\ \d+\ files?\ changed | |
55 | (?:,\ (\d+)\ insertion[s()+]+)? | |
56 | (?:,\ (\d+)\ deletion[s()-]+)?$}x | |
57 | or die "$0: bad stats $_"; | |
cce87900 TF |
58 | my ($add,$del) = ($1 || 0, $2 || 0); |
59 | $add{$date} += $add; | |
60 | $del{$date} += $del; | |
61 | $addmax = $add{$date} if $addmax < $add{$date}; | |
62 | $delmax = $del{$date} if $delmax < $del{$date}; | |
bceb4717 | 63 | my $can = abs $add{$date} - $del{$date}; |
cce87900 TF |
64 | $canmax = $can if $canmax < $can; |
65 | } | |
66 | ||
dcf5f346 TF |
67 | my $max = $opt{width} ? $opt{width} : |
68 | $opt{cancel} ? $canmax : | |
cce87900 TF |
69 | $opt{stack} ? $addmax + $delmax : |
70 | $addmax > $delmax ? $addmax : $delmax; | |
cce87900 TF |
71 | my $scale = $width / $max; |
72 | ||
37fadc81 TF |
73 | my $today = int (time / 86400); |
74 | ||
75 | for my $date ($today - $height .. $today) { | |
d419a729 TF |
76 | my $add = 0; |
77 | my $del = 0; | |
78 | my $mod = 0; | |
37fadc81 TF |
79 | $add{$date} //= 0; |
80 | $del{$date} //= 0; | |
d419a729 | 81 | if ($opt{cancel} or $opt{overlay}) { |
cce87900 TF |
82 | if ($add{$date} > $del{$date}) { |
83 | $add = $add{$date} - $del{$date}; | |
cce87900 TF |
84 | } else { |
85 | $del = $del{$date} - $add{$date}; | |
cce87900 TF |
86 | } |
87 | } | |
88 | if ($opt{overlay}) { | |
d419a729 TF |
89 | $mod = $add{$date} < $del{$date} ? |
90 | $add{$date} : $del{$date}; | |
cce87900 TF |
91 | } |
92 | if ($opt{stack}) { | |
93 | $add = $add{$date}; | |
94 | $del = $del{$date}; | |
cce87900 | 95 | } |
37fadc81 TF |
96 | my $greg = strftime "%b %d %w", localtime $date * 86400; |
97 | $greg =~ s{(\d)$}{substr "sMTWTFs", $1, 1}e; | |
dcf5f346 | 98 | my $line = sprintf "$greg \e[33m%s\e[32m%s\e[31m%s\e[0m\n", |
37fadc81 TF |
99 | "#" x ($mod && 1 + $mod * $scale), |
100 | "+" x ($add && 1 + $add * $scale), | |
101 | "-" x ($del && 1 + $del * $scale); | |
698ba7ee | 102 | if (length $line > $width + 30) { |
dcf5f346 TF |
103 | $line = sprintf "## %d ##\e[32m++ %d ++\e[31m-- %d --\e[0m\n", |
104 | $mod, $add, $del; | |
105 | $line = "$greg \e[33m" . "#"x($width + 16 - length $line) . $line; | |
106 | } | |
107 | print $line; | |
cce87900 | 108 | } |
cb4ff77a | 109 | printf " \e[33m#\e[0m <- %-8.1f %s %8d ->\n", |
bceb4717 | 110 | 1/$scale, " " x ($width - 25), $max; |