#!/bin/bash -p
# Author: 2009-2011 Gert-jan Los <los@hacke.rs>
# License: GPL v3 or later (http://www.gnu.org/licenses/gpl-3.0.txt)

shopt -s extglob

usage() {
	fold -s <<-EOT 1>&2
		usage: ${0##*/} [-s] [-g SEP] [-t SEP] [-k POS[OPTS] [-p PREFIX]]... [-K POS[OPTS]] [-P PREFIX] [FILE]...
		    h: print this help
		    s: sort on given keys before grouping
		    g: use SEP as group seperator instead of a single NL
		    t: use SEP as field seperator instead of TAB
		    k: use field POS as key.  OPTS will be passed to sort(1) if -s is enabled
		    K: use field POS as sort-only key (implies -s)
		    p: use PREFIX as output prefix for the last specified key.
		    P: use PREFIX as data prefix
	EOT
	exit 1
}


sort=false
IFS=$'\t'
key=()
prefix=()
grpsep=$'\n'
sortopts=()
dataprefix='  '

maxkey=0
idx=0
while getopts "hsk:K:g:t:p:P:" opt ; do
	case "$opt" in
		h) usage ;;
		s) sort=true ;;
		g) grpsep="$OPTARG" ;;
		t) IFS="$OPTARG" ;;
		k|K)
			if [[ "$OPTARG" != [1-9]*([0-9])*([bdfgiMnr]) ]] ; then
				echo "${0##*/}: invalid key specification '$OPTARG'" 1>&2
				exit 2
			fi
			if [ "$opt" = 'k' ] ;then
				idx=${#key[*]}
				key[$idx]="${OPTARG%%*([^0-9])}"
				[ ${key[$idx]} -gt $maxkey ] && maxkey=${key[$idx]}
				if [ $idx -gt 0 ] ; then
					prefix[$idx]="$(
						for((i=1; i<=$idx; ++i)) ; do 
							echo -n $'\n== '
						done
					)"
				fi
			else
				sort=true
			fi
			sortopts+=(-k "${OPTARG},${OPTARG}")
		;;
		p) prefix[$idx]="$(echo -e "$OPTARG")" ;;
		P) dataprefix="$(echo -e "$OPTARG")" ;;
		*) usage ;;
	esac
done
shift $((OPTIND-1))
[ ${#key[*]} -gt 0 ] || key=( 1 )
[ -z "$IFS" ] || sortopts=( "${sortopts[@]}" -t "$IFS" )


# main
if $sort ; then
	sort "${sortopts[@]}" "$@"
else
	cat "$@"
fi | {
	while read -ra data ; do
		for ((idx=0; idx<${#key[*]}; ++idx)) ; do
			k=$((${key[$idx]}-1))
			if [ "${keyval[$idx]-$IFS}" != "${data[$k]}" ] ; then
				echo -n "${prefix[$idx]}${data[$k]}"
				keyval[$idx]="${data[$k]}"
				unset keyval[$((idx+1))]
			fi
			unset data[$k]
		done
		echo
		echo -n "${dataprefix}${data[*]}"
		prefix[0]="$grpsep"
	done
	echo
}

