dotfiles

My collection of dotfiles
git clone git://git.noxz.tech/dotfiles
Log | Files | Refs

repo-graph (9784B)


      1 #!/bin/sh
      2 
      3 _MNAMES="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
      4 _WNAMES="Mon Tue Wed Thu Fri Sat Sun"
      5 _NMORE="More"
      6 _NLESS="Less"
      7 _HCOLORS="ebedf0 efa6cf e667af e6399b 85004b"
      8 _8COLORS="2 12 10 3 1"
      9 _COLORS="240 28 34 40 46"
     10 _DSYMB="■"
     11 _WSWM=1
     12 _OUTPUT=""
     13 _AUTHOR=""
     14 _PATH=""
     15 _ALL=""
     16 _LOG=""
     17 
     18 git_log() {
     19 	cmd='git log --no-merges --pretty=format:"%at" --since="13 months"'
     20 	[ "$_AUTHOR" != "" ] && cmd="$cmd --author=\"$_AUTHOR\""
     21 	[ "$_ALL" != "" ] && cmd="$cmd --all"
     22 	if [ "$1" != "" ]
     23 	then
     24 		if [ -d "$1" ]
     25 		then
     26 			cmd="cd \"$1\" && $cmd"
     27 		else
     28 			printf 'error: %s: no such file or directory\n' "$1" 1>&2 && exit 1
     29 		fi
     30 	fi
     31 	echo $(eval "$cmd")
     32 }
     33 
     34 get_days() {
     35 	set -- $(echo $_LOG)
     36 	for epoch
     37 	do
     38 		date -d "@$epoch" +%Y:%j
     39 	done
     40 }
     41 
     42 get_day_count() {
     43 	get_days | sort | uniq -c | sed -e 's/^\ *//g' -e 's/\ /:/g'
     44 }
     45 
     46 main() {
     47 	_TODAY=$(date +%j)
     48 	_DOW=$(date +%u)
     49 	_YEAR=$(date +%Y)
     50 	_LENGTH=$([ $(((_YEAR - 1) % 4)) -eq 0 ] && echo 366 || echo 365)
     51 	_FIRST=$((_TODAY - (53 * 7) - (_DOW % 7) - _WSWM))
     52 	_FMONTH=$(date -d "$_YEAR-01-01 $_FIRST day" +%m)
     53 	_FDOY=$(date -d "$_YEAR-01-01 $_FIRST day" +%j)
     54 	_MNAMES="$(echo $_MNAMES | cut -d ' ' -f $_FMONTH-) $_MNAMES"
     55 	[ $(tput colors) != 256 ] && _COLORS=$_8COLORS
     56 
     57 	[ "$_PATH" = "" ] && _PATH=$(pwd)
     58 	for d in $_PATH
     59 	do
     60 		d="$(realpath $d)"
     61 		_LOG=$(printf '%s\n%s' "$_LOG" "$(git_log $d | tr ' ' '\n')")
     62 		[ $? -ne 0 ] && printf 'error: %s failed to get log: %s\n'          \
     63 			"$0" "$d" && return
     64 	done
     65 
     66 	[ "$_LOG" = "" ] && printf '%s: got empty log, exiting...\n' "$0" && return
     67 
     68 	_DATA=$(get_day_count)
     69 	_COUNTS=$(echo "$_DATA" | sed -e 's/:.*$//g' | sort -n)
     70 	_CCOUNTS=$(echo "$_COUNTS" | wc -l)
     71 	_Q1=$(echo $_COUNTS | cut -d ' ' -f $(((_CCOUNTS + 4 - 1) / 4)))
     72 	_Q2=$(echo $_COUNTS | cut -d ' ' -f $(((_CCOUNTS + 2 - 1) / 2)))
     73 	_Q3=$(echo $_COUNTS | cut -d ' ' -f $(((3 * _CCOUNTS + 2 - 1) / 4)))
     74 
     75 	_HMONTH=$_FMONTH
     76 	mi=1
     77 	ci=1
     78 
     79 	case "$_OUTPUT" in
     80 	""|t) print_tui;;
     81 	s) print_svg;;
     82 	esac
     83 }
     84 
     85 print_tui() {
     86 	printf '%s' "      "
     87 	for w in $(seq 1 53)
     88 	do
     89 		_CINDEX=$((_FDOY + 7 * w - 1))
     90 		_CYEAR=$((_YEAR - 1))
     91 		[ $_CINDEX -ge $_LENGTH ] && _CYEAR=$_YEAR
     92 		_CMONTH=$(date -d "$_CYEAR-01-01 $((_CINDEX % _LENGTH)) day" +%m)
     93 
     94 		if [ $_CMONTH -ne $_HMONTH ]
     95 		then
     96 			mi=$((mi + 1))
     97 			ci=1
     98 		fi
     99 
    100 		# make sure first 2 weeks are of the same month
    101 		if [ $mi -eq 1 ]                                                    \
    102 			&& [ $(date -d "$_YEAR-01-15 $_FIRST day" +%m) -ne $_FMONTH ]
    103 		then
    104 			printf '  '
    105 		else
    106 			[ $ci -le 3 ] && printf '%-2s' \
    107 			"$(echo $_MNAMES | cut -d ' ' -f $mi | cut -c $ci-$((ci + 1)))" \
    108 				|| printf '  '
    109 		fi
    110 
    111 		ci=$((ci + 2))
    112 		_HMONTH=$_CMONTH
    113 	done
    114 	printf '\n'
    115 
    116 	for wd in $(seq 1 7)
    117 	do
    118 		if [ $((wd % 2)) -eq 0 ]
    119 		then
    120 			printf '%5s ' "$(echo $_WNAMES | cut -d ' ' -f $((wd - _WSWM)))"
    121 		else
    122 			printf '      '
    123 		fi
    124 		for w in $(seq 1 53)
    125 		do
    126 			_CINDEX=$((_FDOY + 7 * w - 1 + (wd - 1)))
    127 			_CYEAR=$((_YEAR - 1))
    128 			[ $_CINDEX -ge $_LENGTH ] && _CYEAR=$_YEAR
    129 			_CDOY=$(date -d "$_CYEAR-01-01 $((_CINDEX % _LENGTH)) day" +%j)
    130 			_DC=$(echo "$_DATA" | grep -o ".*$_CYEAR:$_CDOY$")
    131 			_C=${_DC%%:*}
    132 			[ "$_C" = "" ] && _C=0
    133 
    134 			[ $_CYEAR -eq $_YEAR ] && [ $((_CINDEX % _LENGTH)) -ge $_TODAY ] && break
    135 
    136 			_CC="$((
    137 				( $_C == 0 )                    * 1 +
    138 				( $_C > 0 && $_C <= $_Q1 )      * 2 +
    139 				( $_C > $_Q1 && $_C <= $_Q2 )   * 3 +
    140 				( $_C > $_Q2 && $_C <= $_Q3 )   * 4 +
    141 				( $_C > $_Q3 )                  * 5 ))"
    142 
    143 			printf "$(tput setaf $(echo "$_COLORS" | cut -d ' ' -f $_CC))"
    144 			printf '%s%s' "$_DSYMB" "$(tput sgr0) "
    145 		done
    146 		printf "\n"
    147 	done
    148 	printf '\n%92s%s ' " " "$_NLESS"
    149 	for i in $(seq 1 5)
    150 	do
    151 		printf "$(tput setaf $(echo "$_COLORS" | cut -d ' ' -f $i))$_DSYMB$(tput sgr0) "
    152 	done
    153 	printf '%s\n' "$_NMORE"
    154 }
    155 
    156 print_svg() {
    157 	printf '<svg width="650" height="120">\n'
    158 	printf '  <style>\n'
    159 	printf '  .m  { font: normal 10px monospace, sans-serif; fill: #767676;}\n'
    160 	printf '  .wd { font: normal 10px monospace, sans-serif; fill: #767676;}\n'
    161 	printf '  .l  { font: normal 10px monospace, sans-serif; fill: #767676;}\n'
    162 	printf '  </style>\n'
    163 	printf '  <g transform="translate(20, 20)">\n'
    164 	for w in $(seq 1 53)
    165 	do
    166 		printf '    <g transform="translate(%d, 0)">\n' $(((w - 1) * 12))
    167 		for wd in $(seq 1 7)
    168 		do
    169 			_CINDEX=$((_FDOY + 7 * w - 1 + (wd - 1)))
    170 			_CYEAR=$((_YEAR - 1))
    171 			[ $_CINDEX -ge $_LENGTH ] && _CYEAR=$_YEAR
    172 			_CDOY=$(date -d "$_CYEAR-01-01 $((_CINDEX % _LENGTH)) day" +%j)
    173 			_DC=$(echo "$_DATA" | grep -o ".*$_CYEAR:$_CDOY$")
    174 			_C=${_DC%%:*}
    175 			[ "$_C" = "" ] && _C=0
    176 
    177 			[ $_CYEAR -eq $_YEAR ] && [ $((_CINDEX % _LENGTH)) -ge $_TODAY ]\
    178 				&& break
    179 
    180 			_CC="$((
    181 				( $_C == 0 )                    * 1 +
    182 				( $_C > 0 && $_C <= $_Q1 )      * 2 +
    183 				( $_C > $_Q1 && $_C <= $_Q2 )   * 3 +
    184 				( $_C > $_Q2 && $_C <= $_Q3 )   * 4 +
    185 				( $_C > $_Q3 )                  * 5 ))"
    186 
    187 			printf '      <rect %s %s %s %s %s><title>%s</title></rect>\n'  \
    188 				'width="8"'                                                 \
    189 				'height="8"'                                                \
    190 				"x=\"$((16 - (w - 1)))\""                                   \
    191 				"y=\"$(((wd - 1) * 11))\""                                  \
    192 				"fill=\"#$(echo "$_HCOLORS" | cut -d ' ' -f $_CC)\""        \
    193 				"$_C commits"
    194 		done
    195 		printf '    </g>\n'
    196 	done
    197 
    198 	for w in $(seq 1 53)
    199 	do
    200 		_CINDEX=$((_FDOY + 7 * w - 1))
    201 		_CYEAR=$((_YEAR - 1))
    202 		[ $_CINDEX -ge $_LENGTH ] && _CYEAR=$_YEAR
    203 		_CMONTH=$(date -d "$_CYEAR-01-01 $((_CINDEX % _LENGTH)) day" +%m)
    204 
    205 		if [ $mi -eq 1 ]                                                    \
    206 			&& [ $(date -d "$_YEAR-01-30 $_FIRST day" +%m) -ne $_FMONTH ]
    207 		then
    208 			mi=$((mi + 1))
    209 		fi
    210 
    211 		if [ $_CMONTH -ne $_HMONTH ]
    212 		then
    213 			printf '    <text %s %s %s %s>%s</text>\n'                      \
    214 				'dominant-baseline="middle"'                                \
    215 				'class="m"'                                                 \
    216 				"dx=\"$((16 + 11 * (w - 1)))\""                             \
    217 				'dy="-10"'                                                  \
    218 				"$(echo $_MNAMES | cut -d ' ' -f $mi)"
    219 			mi=$((mi + 1))
    220 		fi
    221 		_HMONTH=$_CMONTH
    222 	done
    223 
    224 	for wd in $(seq 1 7)
    225 	do
    226 		[ $((wd % 2)) -ne 0 ] && continue
    227 		printf '    <text %s %s %s %s %s %s>%s</text>\n'                    \
    228 			'transform="translate(5)"'                                      \
    229 			'text-anchor="end"'                                             \
    230 			'dominant-baseline="middle"'                                    \
    231 			'class="wd"'                                                    \
    232 			'dx="0"'                                                        \
    233 			"dy=\"$((6 + 11 * (wd - 1)))\""                                 \
    234 			"$(echo $_WNAMES | cut -d ' ' -f $((wd - _WSWM)))"
    235 	done
    236 
    237 	printf '    <text %s %s %s %s %s %s>%s</text>\n'                        \
    238 		'transform="translate(476)"'                                        \
    239 		'dominant-baseline="middle"'                                        \
    240 		'text-anchor="end"'                                                 \
    241 		'class="l"'                                                         \
    242 		'dx="0"'                                                            \
    243 		'dy="90"'                                                           \
    244 		"$_NLESS"
    245 	for x in $(seq 1 5)
    246 	do
    247 		printf '    <rect %s %s %s %s %s/>\n'                               \
    248 			'width="8"'                                                     \
    249 			'height="8"'                                                    \
    250 			"x=\"$((489 + 11 * (x - 1)))\""                                 \
    251 			"y=\"85\""                                                      \
    252 			"fill=\"#$(echo "$_HCOLORS" | cut -d ' ' -f $x)\""
    253 	done
    254 	printf '    <text %s %s %s %s %s %s>%s</text>\n'                        \
    255 		'transform="translate(556)"'                                        \
    256 		'dominant-baseline="middle"'                                        \
    257 		'text-anchor="start"'                                               \
    258 		'class="l"'                                                         \
    259 		'dx="0"'                                                            \
    260 		'dy="90"'                                                           \
    261 		"$_NMORE"
    262 
    263 	printf '  </g>\n'
    264 	printf '</svg>\n'
    265 }
    266 
    267 show_help() {
    268 	printf 1>&2 '%s\n' "$0"
    269 	printf 1>&2 'usage: %s ' "$0"
    270 	printf 1>&2 '%s '                                                       \
    271 		"[-A|--all]"                                                        \
    272 		"[-a|--author <name>]"                                              \
    273 		"[-t|--tui]"                                                        \
    274 		"[-s|--svg]"                                                        \
    275 		"[-h|--help]"
    276 	printf 1>&2 '\n'
    277 	printf 1>&2 '%s\n'                                                      \
    278 		"   -A, --all               include all branches"                   \
    279 		"   -a, --author <name>     specify a user"                         \
    280 		"   -h, --help              show this help text and exit"           \
    281 		""                                                                  \
    282 		"  OUTPUT TYPES"                                                    \
    283 		"   -t, --tui               output for terminal (default)"          \
    284 		"   -s, --svg               output as svg"
    285 }
    286 
    287 while :; do
    288 	case "$1" in
    289 	-h|--help)
    290 		show_help; exit 0;;
    291 	-A|--all)
    292 		_ALL=1;;
    293 	-a|--author)
    294 		shift; _AUTHOR=$1;;
    295 	-t|--tui)
    296 		if [ "$_OUTPUT" = "" ]
    297 		then _OUTPUT='t'
    298 		else printf 1>&2 'error: only one output type allowed\n'; exit 1
    299 		fi;;
    300 	-s|--svg)
    301 		if [ "$_OUTPUT" = "" ]
    302 		then _OUTPUT='s'
    303 		else printf 1>&2 'error: only one output type allowed\n'; exit 1
    304 		fi;;
    305 	--)
    306 		shift; break;;
    307 	-*)
    308 		echo "invalid option: $1" 1>&2; return 1;;
    309 	"")
    310 		break;;
    311 	*)
    312 		_PATH=$@
    313 		break;;
    314 	esac
    315 	shift
    316 done
    317 
    318 main