#!/usr/bin/bash

# archive_color (by Wolfgang Friebel), a modified tarcolor, works also for
# other (archive) listings, such as rpm, debian, ar, isoinfo archives and ls -l
#
# Colors can be customized using an environment variable:
#
# TAR_COLORS='di=01;34:ln=01;36:ex=01;32:so=01;40:pi=01;40:bd=40;33:cd=40;33:su=0;41:sg=0;46'
#
# The format for TAR_COLORS is similar to the format used by LS_COLORS
# Check out the online LSCOLORS generator at https://geoff.greer.fm/lscolors/
#
# License: GPL-2.0-or-later

get_file_code() {
	local line=$1
	local len=${#line}
	(( len < 20 )) && return 1
	local c0=${line:0:1}
	local perm10=${line:0:10}
	local c3=${line:3:1}
	local c6=${line:6:1}
	local last3=${line: -3}
	local l2=${last3:0:2}

	[[ $c0 == "l" ]] && echo "ln" && return
	[[ $perm10 == "drwxrwxrwx" ]] && echo "ow"
	[[ $perm10 == "drwxrwxrwt" ]] && echo "tw"
	[[ $c0 == "d" ]] && echo "di" && return
	[[ $c0 == "s" ]] && echo "so" && return
	[[ $c3 == "S" ]] && echo "su" && return
	[[ $c6 == "S" ]] && echo "sg" && return
	[[ $c0 == "p" ]] && echo "pi" && return
	[[ $c0 == "c" ]] && echo "cd" && return
	[[ $c0 == "b" ]] && echo "bd" && return
	[[ $c0 == "D" ]] && echo "do" && return
	[[ $c3 == "x" ]] && echo "ex" && return
	[[ $l2 == ./* ]] && echo "di" && return
	[[ $line != *.* ]] && return 1
	echo "*.${line##*.}"
}

if [[ -t 0 ]]; then
	echo "Example: tar tvzf some_tarball.tar.gz | archive_color"
	exit 0
fi

declare -A FILE_TYPE_TO_COLOR
default_colors='di=01;34:ln=01;36:ex=01;32:so=01;35:pi=40;33:bd=40;33;01:cd=40;33;01:su=37;41:sg=30;43:do=01;35:tw=30;42:ow=34;42'
tar_colors=${TAR_COLORS:-${LS_COLORS:-}}
# shellcheck disable=SC2207
color_specs=($(echo "$default_colors:$tar_colors"| tr ":" "\n"))

for spec in "${color_specs[@]}"; do
	[[ -z $spec ]] && continue
	type=${spec%=*}
	codes=${spec#*=}
	[[ -z $type || -z $codes ]] && continue
	FILE_TYPE_TO_COLOR[$type]="\033[${codes}m"
done

while IFS= read -r line; do
	type=$(get_file_code "$line") || true
	if [[ -n $type && -n ${FILE_TYPE_TO_COLOR[$type]+set} ]]; then
		[[ $(echo "$line"|awk '{print $4}') == *-*-* ]] && fld=6 || fld=9
		filename=$(echo "$line"|awk '{print $'"$fld"'}')
		filename="$filename${line##*"$filename"}"
		if [[ -n $filename ]]; then
			printf '%s%b%s%b\n' "${line%"$filename"}" "${FILE_TYPE_TO_COLOR[$type]}" "$filename" "\033[0m"
		else
			printf '%s\n' "$line"
		fi
	else
		printf '%s\n' "$line"
	fi
done
