#!/bin/bash
#
# --------------------------------------------------------------------
# A simple script to read text from stdin, technicolourise it prettily
# and pass it to stdout. Example usage: 
#
#	echo "LIMIT" | neonize -m3 -p6
#
#	fortune | cowsay | neonize -m1
#
#	rain | neonize -m2	     	(Works with PerlPowerTools
#					style rain, not with Debian
#					bsdgames style rain.)
#
# For usage details: `neonize -h`
# -------------------------------
#
# Author: Robert F.J. Seddon ( http://rfjseddon.net/ )
# --------------------------------------------------------------------

red=(52 88 124 160 196 160 124 88 52)
blue=(17 18 19 20 21 20 19 18 17)
green=(22 28 34 40 46 40 34 28 22)
yellow=(172 178 214 220 226 220 214 178 172)
purple=(53 90 127 164 201 164 127 90)
rainbow=(196 9 11 10 6 5 13)
# I'm a bit concerned that 9 on this person's screenshot - 
# http://misc.flogisoft.com/bash/tip_colors_and_formatting -
# looks more red than orange to me.

# Defaults
bg=0
dreamcoat=2
invert=0
index=0
palette=("${rainbow[@]}")

for arg
do
	case $arg in
	-h | --help)
		echo -e "A simple script to read text from stdin, technicolourise it prettily and
pass it to stdout. Requires 256-colour capability.

Usage:	neonize [-b|w] [-m\e[04mn\e[0m] [-p\e[04mn\e[0m]

	-b	Ensure black background (or foreground in modes 4 - 6)
	-m\e[04mn\e[0m	Choose mode:

	1:	Long loop
	2:	Random
	3:	Short loop of palette -p\e[04mn\e[0m
	4:	Background version of 1
	5:	Background version of 2
	6:	Background version of 3

	-p\e[04mn\e[0m	Choose palette for Mode 3 or 6:

	1:	Red
	2:	Blue
	3:	Green
	4:	Yellow
	5:	Purple
	6:	Rainbow

	-w	Ensure white background (or foreground in modes 4 - 6)"
		exit 0
		;;
	-b) # Ensure black background in modes 1-3 (and black text in 4-6)
		bg=16 # (May cause unsightly black bars; see under -w.)
		;;
	-w) # Ensure white background in modes 1-3 (and white text in 4-6)
		bg=255 # (May cause unsightly white bars depending on
		# terminal settings; in PuTTY, disable this by turning off
		# 'Terminal > Use background colour to erase screen'.)
		;;
       -m1) # Mode 1: Looping mode--better for longer text
		dreamcoat=1
		;;
       -m2) # Mode 2: Random mode--better for shorter text (default)
		dreamcoat=2
		;;
       -m3) # Mode 3: Rainbow mode, or a palette chosen with -p
		dreamcoat=3
		;;
       -m4) # Mode 4: Background version of 1
		dreamcoat=1
		invert=07
		;;
       -m5) # Mode 5: Background version of 2
		dreamcoat=2
		invert=07
		;;
       -m6) # Mode 6: Background version of 3
		dreamcoat=3
		invert=07
		;;
       -p1) # Palette 1 - red
		palette=("${red[@]}")
		;;
       -p2) # Palette 2 - blue
		palette=("${blue[@]}")
		;;
       -p3) # Palette 3 - green
		palette=("${green[@]}")
		;;
       -p4) # Palette 4 - yellow
		palette=("${yellow[@]}")
		;;
       -p5) # Palette 5 - purple
		palette=("${purple[@]}")
		;;
       -p6) # Palette 6 - rainbow (default)
		palette=("${rainbow[@]}")
		;;
	-bw | -wb)
		echo "Error: impossible combination: $arg" >&2
		exit 1
		;;
	--)	break
		;;
	-*)	echo "Error: unknown option: $arg" >&2
		exit 1
		;;
	 *)	echo "Error: unknown argument: $arg" >&2
		exit 2
		;;
	esac
done

if [ $dreamcoat = 1 ]
	then fg=18
fi

while IFS='' read -r -d '' -n1 char
do
	if [ $dreamcoat = 2 ]
	then
		fg=$(($RANDOM % 222))
		if [ $fg = 16 ] || [ $fg = 0 ]
			then let fg++
		fi
	fi
	if [ $dreamcoat = 3 ]
		then let fg=palette[index]
		if [ $index -gt $((${#palette[@]} - 2)) ]
		then
			index=0
		else let index++
		fi
	fi
	
	echo -ne "\e[${invert};38;05;${fg};48;05;${bg}m$char"
	
	if [ $dreamcoat = 1 ]
	then
		let fg++
		if [ $fg = 222 ]
			then fg=18
		fi
	fi
done
echo -ne "\e[0m"
