Cleaning up dotfiles

This commit is contained in:
2016-03-17 14:16:58 -06:00
parent 386330f1a5
commit 47c4b01d5a
15 changed files with 206 additions and 1860 deletions

View File

@@ -1,371 +0,0 @@
#!/usr/bin/perl
use strict;
use utf8;
use Getopt::Long;
use Pod::Usage;
use Data::Dumper;
binmode(STDOUT, ":utf8");
#command line options
my ( $help, $period, $author, $filepath );
GetOptions(
'help|?' => \$help,
'period|p=n' => \$period,
'author=s' => \$author,
) or pod2usage(2);
pod2usage(1) if $help;
$filepath = shift @ARGV;
# also tried to use unicode chars instead of colors, the exp did not go well
#qw(⬚ ⬜ ▤ ▣ ⬛)
#qw(⬚ ▢ ▤ ▣ ⬛)
my @colors = ( 237, 157, 155, 47, 2 );
my @months = qw (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
process();
# 53 X 7 grid
# consists of 0 - 370 blocks
my ( @grid, @timeline, %pos_month, %month_pos, $jan1, $cur_year, $max_epoch, $min_epoch, $max_commits, $q1, $q2, $q3 );
my ( $first_block, $last_block, $start_block, $end_block, $row_start, $row_end );
my ( $total_commits, $max_streak, $cur_streak, $max_streak_weekdays, $cur_streak_weekdays );
my ( $cur_start, $max_start, $max_end, $cur_weekdays_start, $max_weekdays_start, $max_weekdays_end );
#loads of global variables
sub process {
#try to exit gracefully when the terminal doesn't support enough colors
no warnings; #dont warn if tput command fails
my $colors_supported = qx/tput colors/;
if ($colors_supported && $colors_supported < 256) {
chomp $colors_supported;
print "fatal: 'tput colors' returned < 256 (" . $colors_supported . ") , cannot plot the calendar as the terminal doesn't support enough colors\n"; #will try to hack around this soon
exit(1);
}
init_cal_stuff();
my $extra_args = "";
$extra_args = " --author=" . $author if $author;
if ($filepath) {
if ( -e $filepath ) {
$extra_args .= " -- " . $filepath;
}
else {
print "fatal: $filepath do not exists\n";
exit(2);
}
}
my $git_command = "git log --pretty=format:\"%at\" --since=\"13 months\"" . $extra_args; #commits might not be in strict time order, check some past too
my $epochs = qx/$git_command/;
if ($?) {
print "fatal: git-cal failed to get the git log\n";
exit(2);
}
my @epochs = split /\n/, $epochs;
if (! @epochs) {
print "git-cal: got empty log, nothing to do\n";
exit(1);
}
my $status;
foreach (@epochs) {
$status = add_epoch($_);
last if !$status;
}
compute_stats();
print_grid();
}
sub init_cal_stuff {
my ( $wday, $yday, $month, $year ) = ( localtime(time) )[ 6, 7, 4, 5 ];
$cur_year = $year;
$jan1 = 370 - ( $yday + 6 - $wday );
$last_block = $jan1 + $yday + 1;
$first_block = $last_block - 365;
$max_commits = 0;
push @timeline, $jan1;
$month_pos{0} = $jan1;
my $cur = $jan1;
foreach ( 0 .. $month - 1 ) {
$cur += number_of_days( $_, $year );
push @timeline, $cur;
$month_pos{ $_ + 1 } = $cur;
}
$cur = $jan1;
for ( my $m = 11; $m > $month; $m-- ) {
$cur -= number_of_days( $m, $year - 1 );
unshift @timeline, $cur;
$month_pos{$m} = $cur;
}
$pos_month{ $month_pos{$_} } = $months[$_] foreach keys %month_pos;
die "period can only be between -11 to -1 and 1 to 12" if ( defined $period && ( $period < -11 || $period > 12 || $period == 0 ) );
$period = 0 if !defined $period;
if ( $period == 0 ) {
$start_block = $first_block;
$end_block = $last_block;
}
elsif ( $period > 0 ) {
$start_block = $month_pos{ $period - 1 };
$end_block = $month_pos{ $period % 12 };
$end_block = $last_block if $start_block > $end_block;
}
else {
$start_block = $timeline[ 11 + $period ];
$start_block = $first_block if $period == -12;
$end_block = $last_block;
}
$row_start = int $start_block / 7;
$row_end = int $end_block / 7;
$max_epoch = time - 86400 * ( $last_block - $end_block );
$min_epoch = time - 86400 * ( $last_block - $start_block );
( $total_commits, $max_streak, $cur_streak, $max_streak_weekdays, $cur_streak_weekdays ) = (0) x 5;
( $cur_start, $max_start, $max_end, $cur_weekdays_start, $max_weekdays_start, $max_weekdays_end ) = (0) x 6;
}
sub add_epoch {
my $epoch = shift;
if ( $epoch > $max_epoch || $epoch < $min_epoch ) {
return 1;
}
my ( $month, $year, $wday, $yday ) = ( localtime($epoch) )[ 4, 5, 6, 7 ];
my $pos;
if ( $year == $cur_year ) {
$pos = ( $jan1 + $yday );
}
else {
my $total = ( $year % 4 ) ? 365 : 366;
$pos = ( $jan1 - ( $total - $yday ) );
}
return 0 if $pos < 0; #just in case
add_to_grid( $pos, $epoch );
return 1;
}
sub add_to_grid {
my ( $pos, $epoch ) = @_;
my $r = int $pos / 7;
my $c = $pos % 7;
$grid[$r][$c]->{commits}++;
$grid[$r][$c]->{epoch} = $epoch;
$max_commits = $grid[$r][$c]->{commits} if $grid[$r][$c]->{commits} > $max_commits;
}
sub compute_stats {
my %commit_counts;
foreach my $r ( $row_start .. $row_end ) {
foreach my $c ( 0 .. 6 ) {
my $cur_block = ( $r * 7 ) + $c;
if ( $cur_block >= $start_block && $cur_block < $end_block ) {
my $count = $grid[$r][$c]->{commits} || 0;
$total_commits += $count;
if ($count) {
$commit_counts{$count} = 1;
$cur_streak++;
$cur_start = $grid[$r][$c]->{epoch} if $cur_start == 0;
if ( $cur_streak > $max_streak ) {
$max_streak = $cur_streak;
$max_start = $cur_start;
$max_end = $grid[$r][$c]->{epoch};
}
#count++ if you work on weekends and streak will not be broken otherwise :)
$cur_streak_weekdays++;
$cur_weekdays_start = $grid[$r][$c]->{epoch} if $cur_weekdays_start == 0;
if ( $cur_streak_weekdays > $max_streak_weekdays ) {
$max_streak_weekdays = $cur_streak_weekdays;
$max_weekdays_start = $cur_weekdays_start;
$max_weekdays_end = $grid[$r][$c]->{epoch};
}
}
else {
$cur_streak = 0;
$cur_start = 0;
if ( $c > 0 && $c < 6 ) {
$cur_streak_weekdays = 0;
$cur_weekdays_start = 0;
}
}
}
}
}
#now compute quartiles
my @commit_counts = sort { $a <=> $b } ( keys %commit_counts );
$q1 = $commit_counts[ int( scalar @commit_counts ) / 4 ];
$q2 = $commit_counts[ int( scalar @commit_counts ) / 2 ];
$q3 = $commit_counts[ int( 3 * ( scalar @commit_counts ) / 4 ) ];
#print "commit counts: " . (scalar @commit_counts) . " - " . (join ",",@commit_counts) . "\n\n";
#print "quartiles: $q1 $q2 $q3\n";
}
sub print_grid {
my $space = 6;
print_month_names($space);
foreach my $c ( 0 .. 6 ) {
printf "\n%" . ( $space - 2 ) . "s", "";
if ( $c == 1 ) {
print "M ";
}
elsif ( $c == 3 ) {
print "W ";
}
elsif ( $c == 5 ) {
print "F ";
}
else {
print " ";
}
foreach my $r ( $row_start .. $row_end ) {
my $cur_block = ( $r * 7 ) + $c;
if ( $cur_block >= $start_block && $cur_block < $end_block ) {
my $val = $grid[$r][$c]->{commits} || 0;
my $index = 0;
#$index = ( int( ( $val - 4 ) / $divide ) ) + 1 if $val > 0; #too dumb and bad
if ($val) {
if ( $val <= $q1 ) {
$index = 1;
}
elsif ( $val <= $q2 ) {
$index = 2;
}
elsif ( $val <= $q3 ) {
$index = 3;
}
else {
$index = 4;
}
}
print_block($index);
}
else {
print " ";
}
}
}
print "\n\n";
printf "%" . ( 2 * ( $row_end - $row_start ) + $space - 10 ) . "s", "Less "; #such that the right borders align
print_block($_) foreach ( 0 .. 4 );
print " More\n";
printf "%4d: Total commits\n", $total_commits;
print_message( $max_streak_weekdays, $max_weekdays_start, $max_weekdays_end, "Longest streak excluding weekends" );
print_message( $max_streak, $max_start, $max_end, "Longest streak including weekends" );
print_message( $cur_streak_weekdays, $cur_weekdays_start, time, "Current streak" );
}
sub print_block {
my $index = shift;
$index = 4 if $index > 4;
my $c = $colors[$index];
#always show on a black background, else it looks different (sometimes really bad ) with different settings.
#print "\e[40;38;5;${c}m⬛ \e[0m";
print "\e[40;38;5;${c}m\x{25fc} \e[0m";
}
sub print_month_names {
#print month labels, printing current month in the right position is tricky
my $space = shift;
if ( defined $period && $period > 0 ) {
printf "%" . $space . "s %3s", "", $months[ $period - 1 ];
return;
}
my $label_printer = 0;
my $timeline_iter = 11 + ( $period || -11 );
if ( $start_block == $first_block && $timeline[0] != 0 ) {
my $first_pos = int $timeline[0] / 7;
if ( $first_pos == 0 ) {
printf "%" . ( $space - 2 ) . "s", "";
print $pos_month{ $timeline[-1] } . " ";
print $pos_month{ $timeline[0] } . " ";
$timeline_iter++;
}
elsif ( $first_pos == 1 ) {
printf "%" . ( $space - 2 ) . "s", "";
print $pos_month{ $timeline[-1] } . " ";
}
else {
printf "%" . $space . "s", "";
printf "%-" . ( 2 * $first_pos ) . "s", $pos_month{ $timeline[-1] };
}
$label_printer = $first_pos;
}
else {
printf "%" . $space . "s", "";
$label_printer += ( int $start_block / 7 );
}
while ( $label_printer < $end_block / 7 && $timeline_iter <= $#timeline ) {
while ( ( int $timeline[$timeline_iter] / 7 ) != $label_printer ) { print " "; $label_printer++; }
print " " . $pos_month{ $timeline[$timeline_iter] } . " ";
$label_printer += 3;
$timeline_iter++;
}
}
sub print_message {
my ( $days, $start_epoch, $end_epoch, $message ) = @_;
if ($days) {
my @range;
foreach my $epoch ( $start_epoch, $end_epoch ) {
my ( $mday, $mon, $year ) = ( localtime($epoch) )[ 3, 4, 5 ];
my $s = sprintf( "%3s %2d %4d", $months[$mon], $mday, ( 1900 + $year ) );
push @range, $s;
}
printf "%4d: Days ( %-25s ) - %-40s\n", $days, ( join " - ", @range ), $message;
}
else {
printf "%4d: Days - %-40s\n", $days, $message;
}
}
sub number_of_days {
my ( $month, $year ) = @_;
return 30 if $month == 3 || $month == 5 || $month == 8 || $month == 10;
return 31 if $month != 1;
return 28 if $year % 4;
return 29;
}
__END__
=head1 NAME
git-cal - A simple tool to view commits calendar (similar to github contributions calendar) on command line
=head1 SYNOPSIS
"git-cal" is a tool to visualize the git commit history in github's contribution calendar style.
The calendar shows how frequently the commits are made over the past year or some choosen period
git-cal
git-cal --author=<author> -- <filepath>
=head2 OPTIONS
--author view commits of a particular author (passed to git log --author= )
--period|p Do not show the entire year, p=1 to 12 shows only one month (1 = Jan .. 12 = Dec), p=-1 to -11 shows last p months and the current month
--help|? help me
=head2 ADDITIONAL OPTIONS
-- filename to view the logs of a particular file or directory
=head1 AUTHOR
Karthik katooru <karthikkatooru@gmail.com>
=head1 COPYRIGHT AND LICENSE
This program is free software; you can redistribute it and/or modify it under the MIT License

230
bin/peat
View File

@@ -1,230 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
##############################
# ____ ___ ____ ______ #
# | \ / _] / T| T #
# | o )/ [_ Y o || | #
# | _/Y _]| |l_j l_j #
# | | | [_ | _ | | | #
# | | | T| | | | | #
# l__j l_____jl__j__j l__j #
# #
##### #####
# Repeat commands! #
##################
import errno, os, subprocess, sys, time
from optparse import OptionParser
interval = 1.0
command = 'true'
clear = True
get_paths = lambda: set()
verbose = True
dynamic = False
paths_command = None
USAGE = """\
usage: %prog [options] COMMAND
COMMAND should be given as a single argument using a shell string.
A list of paths to watch should be piped in on standard input.
For example:
find . | peat './test.sh'
find . -name '*.py' | peat 'rm *.pyc'
find . -name '*.py' -print0 | peat -0 'rm *.pyc'
If --dynamic is given, a command to generate the list should be piped in
on standard input instead. It will be used to generate the list of files
to check before each run.
This command must be quoted properly, and this can be tricky. Make sure
you know what you're doing.
For example:
echo find . | peat --dynamic './test.sh'
echo find . -name '*.py' | peat --dynamic 'rm *.pyc'
"""
def log(s):
if verbose:
print s
def die(s):
sys.stderr.write('ERROR: ' + s + '\n')
sys.exit(1)
def check(paths):
cutoff = int(time.time() - interval)
for p in paths:
try:
if os.stat(p).st_mtime >= cutoff:
return True
except OSError, e:
# If the file has been deleted since we started watching, don't
# worry about it.
if e.errno == errno.ENOENT:
pass
else:
raise
return False
def run():
log("running: " + command)
subprocess.call(command, shell=True)
def build_option_parser():
p = OptionParser(USAGE)
# Main options
p.add_option('-i', '--interval', default=None,
help='interval between checks in milliseconds',
metavar='N')
p.add_option('-I', '--smart-interval', dest='interval',
action='store_const', const=None,
help='determine the interval based on number of files watched (default)')
p.add_option('-d', '--dynamic', default=False,
action='store_true',
help='take a command on standard input to generate the list of files to watch')
p.add_option('-D', '--no-dynamic', dest='dynamic',
action='store_false',
help='take a list of files to watch on standard in (default)')
p.add_option('-c', '--clear', default=True,
action='store_true', dest='clear',
help='clear screen before runs (default)')
p.add_option('-C', '--no-clear',
action='store_false', dest='clear',
help="don't clear screen before runs")
p.add_option('-v', '--verbose', default=True,
action='store_true', dest='verbose',
help='show extra logging output (default)')
p.add_option('-q', '--quiet',
action='store_false', dest='verbose',
help="don't show extra logging output")
p.add_option('-w', '--whitespace', default=None,
action='store_const', dest='sep', const=None,
help="assume paths on stdin are separated by whitespace (default)")
p.add_option('-n', '--newlines',
action='store_const', dest='sep', const='\n',
help="assume paths on stdin are separated by newlines")
p.add_option('-s', '--spaces',
action='store_const', dest='sep', const=' ',
help="assume paths on stdin are separated by spaces")
p.add_option('-0', '--zero',
action='store_const', dest='sep', const='\0',
help="assume paths on stdin are separated by null bytes")
return p
def _main():
if dynamic:
log("Running the following command to generate watch list:")
log(' ' + paths_command)
log('')
log("Watching the following paths:")
for p in get_paths():
log(' ' + p)
log('')
log('Checking for changes every %d milliseconds.' % int(interval * 1000))
log('')
run()
while True:
time.sleep(interval)
if check(get_paths()):
if clear:
subprocess.check_call('clear')
run()
def smart_interval(count):
"""Return the smart interval to use in milliseconds."""
if count >= 50:
return 1000
else:
sq = lambda n: n * n
return int(1000 * (1 - (sq(50.0 - count) / sq(50))))
def _parse_interval(options):
global get_paths
if options.interval:
i = int(options.interval)
elif options.dynamic:
i = 1000
else:
i = smart_interval(len(get_paths()))
return i / 1000.0
def _parse_paths(sep, data):
if not sep:
paths = data.split()
else:
paths = data.split(sep)
paths = [p.rstrip('\n') for p in paths if p]
paths = map(os.path.abspath, paths)
paths = set(paths)
return paths
def main():
global interval, command, clear, get_paths, verbose, dynamic, paths_command
(options, args) = build_option_parser().parse_args()
if len(args) != 1:
die("exactly one command must be given")
command = args[0]
clear = options.clear
verbose = options.verbose
sep = options.sep
dynamic = options.dynamic
if dynamic:
paths_command = sys.stdin.read().rstrip()
if not paths_command:
die("no command to generate watch list was given on standard input")
def _get_paths():
data = subprocess.check_output(paths_command, shell=True)
return _parse_paths(sep, data)
get_paths = _get_paths
else:
data = sys.stdin.read()
paths = _parse_paths(sep, data)
if not paths:
die("no paths to watch were given on standard input")
for path in paths:
if not os.path.exists(path):
die('path to watch does not exist: ' + repr(path))
get_paths = lambda: paths
interval = _parse_interval(options)
_main()
if __name__ == '__main__':
import signal
def sigint_handler(signal, frame):
sys.stdout.write('\n')
sys.exit(130)
signal.signal(signal.SIGINT, sigint_handler)
main()

View File

@@ -1,2 +0,0 @@
#!/bin/bash
offlineimap -q; notmuch new