#!/bin/bash # Generate code count plots by iterating over tagged revisions and running cloc. # Requires cloc and gnuplot. # Output images. loc="`hg root`/docs/images/loc.png" languages="`hg root`/docs/images/languages.png" # Clone a temporary repository and generate code count data for gnuplot to plot. tmp=/tmp/count hg clone `hg root` $tmp && pushd $tmp plotfile=gnuplot.dat for rev in `hg tags | awk '{print $2}' | cut -d: -f1 | tac`; do date=`hg log -r $rev | grep ^date | cut -d: -f2- | tr + - | cut -d- -f1` hg update -r $rev -q timestamp=`date -d "$date" "+%s"` counts=`cloc --force-lang=C,h --include-lang=C,Lua,make --quiet --csv \ --exclude-dir=doc,docs,scripts,themes,test,.github --not-match-f=adeptsensedoc\\|tadoc . | \ tail -n +3 | head -n -1 | cut -d, -f2- | sort | tr '\n' ,` echo $timestamp,$counts done | lua -e " -- Filter counts from cloc into a data format readable by gnuplot. -- Input is of the form: -- timestamp1,lang1,blanks1,comments1,code2,lang2,blanks2,comments2,code2,... -- timestamp2,lang1,blanks1,comments1,code2,lang2,blanks2,comments2,code2,... -- Output is of the form: -- Lang1 -- Time Blanks Comments Code -- ts1 bl1 cm1 co1 -- ts2 bl2 cm2 co2 -- ... -- -- -- Lang2 -- Time Blanks Comments Code -- ts1 bl1 cm1 co1 -- ts2 bl2 cm2 co2 -- ... -- Read in counts. local counts, langs = {}, {} for line in io.lines() do local time, data = line:match('^(%d+),(.+)$') counts[#counts + 1], counts[time] = time, {} for lang, data in data:gmatch('([^,]+),([^,]+,[^,]+,[^,]+)') do lang = lang:match('%S+$') if not langs[lang] then langs[#langs + 1], langs[lang] = lang, true end counts[time][lang] = data end end table.sort(langs) -- Output a data series for each language counted. for i = 1, #langs do print(langs[i]) print('Time', 'Blanks', 'Comments', 'Code') for j = 1, #counts do local data = (counts[counts[j]][langs[i]] or '0,0,0'):gsub(',', '\t') print(counts[j], data) end print('\n') -- double-newline needed to delimit gnuplot data series end -- Output a data series for code, comments, and blanks counted. for i = 1, #counts do local sum_code, sum_comments, sum_blanks = 0, 0, 0 for j = 1, #langs do local data = counts[counts[i]][langs[j]] or '0,0,0' local blanks, comments, code = data:match('([^,]+),([^,]+),([^,]+)') sum_code = sum_code + tonumber(code) sum_comments = sum_comments + tonumber(comments) sum_blanks = sum_blanks + tonumber(blanks) end counts[counts[i]] = {sum_code, sum_comments, sum_blanks} end for i, measure in ipairs{'Code', 'Comments', 'Blanks'} do print(measure) print('Time', measure) for j = 1, #counts do print(counts[j], counts[counts[j]][i]) end print('\n') -- double-newline needed to delimit gnuplot data series end " > $plotfile nlangs=$((`grep ^Time $plotfile | wc -l` - 3)) # ignore blanks, comments, code # Define gnuplot plot settings and plot commands. plotcmd=gnuplot.plt echo " set term png transparent font 'DejaVu Sans,10' size 450,275; set border linewidth 1.5; set style line 1 linecolor rgb '#99994d' linewidth 2; set style line 2 linecolor rgb '#4d99e6' linewidth 2; set style line 3 linecolor rgb '#994d4d' linewidth 2; set style line 4 linecolor rgb '#4d994d' linewidth 2; set style line 5 linecolor rgb '#994d99' linewidth 2; set grid linecolor rgb '#cccccc' linetype 1; set tics scale 0; set key left top horizontal Left reverse samplen 1; set xdata time; set timefmt '%s'; set format x \"%Y\n%b\"; set autoscale xfix; set title 'Code Summary' set output '$loc' plot for [i=0:2] '$plotfile' index $nlangs+i using 1:2 with lines title columnhead(1) linestyle i+1 set title 'Code Line Counts' set output '$languages' plot for [i=0:$nlangs-1] '$plotfile' index i using 1:4 with lines title columnhead(1) linestyle i+1 " > $plotcmd # Invoke gnuplot. gnuplot $plotcmd # Cleanup. popd && rm -r $tmp