IN: diffstat USING: assocs combinators io kernel math namespaces sequences splitting ; SYMBOL: stats SYMBOL: fname SYMBOL: curstats : isstart ( seq subseq -- bool ) swap start 0 = ; : is-diffstart-line ( line -- bool ) "diff" isstart ; : is-plus-line ( line -- bool ) [ "+++" isstart not ] [ "+" isstart ] bi and ; : is-minus-line ( line -- bool ) [ "---" isstart not ] [ "-" isstart ] bi and ; : fname-git ( line -- fname ) ! fucking regular expressions! ! R"diff --git a/(.*) b/(.*)" ! (match) captured-groups>> 1 swap at " " split third 2 swap dup length swap subseq ; : fname-uni ( line -- fname ) " " split 5 tail " " join ; : determine-fname ( line -- fname ) [ dup "--git" start ] [ fname-git ] [ fname-uni ] if ; : inc-curstats ( n -- ) curstats get 2dup nth 1 + -rot set-nth ; : finish-count ( -- ) curstats get fname get stats get set-at { 0 0 } clone curstats set f fname set ; : diffstat* ( line -- ) { { [ dup is-diffstart-line ] [ fname get [ finish-count ] when ! update stats determine-fname fname set ] } { [ dup is-plus-line ] [ 0 inc-curstats drop ] } { [ dup is-minus-line ] [ 1 inc-curstats drop ] } [ drop ] } cond ; : diffstat ( stream -- stream diffstat ) H{ } clone stats set ! initialize statistics hashtable { 0 0 } clone curstats set ! adds, removes [ readln dup ] [ diffstat* ] [ drop ] while finish-count stats get ; ! "diff" utf8 [ diffstat ] with-file-reader