#!/usr/bin/env bash
#
# Very simple file style checker.  Checks include:
#
# - No lines are over 80 characters.
# - No 2 or more consecutive newlines.
# - Consistent use of tabs and spaces.
#
# Author: Dave Eddy <dave@daveeddy.com>
# Date: May 21, 2021
# License: MIT

# colors
[[ -t 1 ]] || tput() { true; }
red=$(tput setaf 1)
bld=$(tput bold)
rst=$(tput sgr0)

# exit code
exitcode=0

# check for lines greater than 80 columns
exceeds-line-length() {
	local file=$1
	local columns=80

	expand "$file" | awk "-vcols=$columns" '
	BEGIN {
		code = 0;
	}
	length($0) > cols {
		printf("%4-d %s\n", NR, $0);
		code = 1;
	}
	END {
		exit(code);
	}
	'
}

# check for consecutive newlines
blank-lines() {
	local file=$1

	awk '
	BEGIN {
		code = 0;
		newlines = 0;
	}
	/^$/ {
		newlines++;
		if (newlines == 2) {
			printf("%-4d extra newline(s)\n", NR);
			code = 1;
		}
	}
	/^.+$/ {
		newlines = 0;
	}
	END {
		exit(code);
	}
	' "$file"
}

# check for bad tab/spacing
consistent-tabs() {
	local file=$1

	awk '
	BEGIN {
		code = 0;
	}
	/^( [^*]|\t+ {5})/ {
		printf("%4-d inconsistent tabs\n", NR);
		code = 1;
	}
	END {
		exit(code);
	}
	' "$file"
}

# run a test against a file
#
# usage: run-test <test-name> <file> <failure message>
#
# ex: run-test consistent-tabs src/sshp.c 'bad tab usage'
#
run-test() {
	local test=$1
	local file=$2
	local msg=$3
	local output

	if ! output=$("$test" "$file" 2>&1); then
		exitcode=1
		echo
		echo "${red}error:  $msg$rst"
		echo "$output"
		echo
	fi
}

# loop each argument and run tests
for f in "$@"; do
	ext=${f##*.}

	echo "${bld}checking:$rst  $f"

	run-test blank-lines         "$f" 'consective blank lines'
	run-test exceeds-line-length "$f" 'lines over 80 columns'

	# markdown files get a pass from tab/space checks - they are wild
	if [[ $ext != md ]]; then
		run-test consistent-tabs     "$f" 'bad tab usage'
	fi
done

exit "$exitcode"
