#!/bin/sh
##################################################################################
## Bashish, a console theme engine
## Copyright (C) 2010 Thomas Eriksson
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
##################################################################################
##
## THIS IS BASHISH2. YOU WILL BE ASSIMILATED
##
######################################################

## Cygwin (and others?) does not set COLUMNS and LINES by default
## in CygPuTTY COLUMNS and LINES get set to 0,0
if test "x$LINES$COLUMNS" = x -o "x$LINES$COLUMNS" = x00
then
	COLUMNS=$(stty size)
	LINES=${COLUMNS% *}
	COLUMNS=${COLUMNS#* }

	export COLUMNS LINES
fi

## cygwin reports errornous size 
test "x$TERM" = xcygwin && COLUMNS=`expr $COLUMNS - 1`

## if $SHELLNAME is set prior to loading this module
## bashish will not probe shell and use the preset value
test "$SHELLNAME" || {

	## generic sh
	SHELLNAME=sh
	
	## ksh
	test "$SECONDS"&&SHELLNAME=ksh

	## zsh
	test "$ZSH_VERSION"&&SHELLNAME=zsh
	
	## bash
	test "$BASH_VERSION"&&SHELLNAME=bash
}

_bashish_loadhelpers ()
{
	## most helpers are not ported to non-bash shells yet
	test "x$BASH" = x && return 0
	unset -f _bashish_loadhelpers
	case "$ZSH_VERSION" in
	4*) emulate -L ksh ;;
	"") :;;
	*) return 0;;
	esac
	test "x$RANDOM" != x && for LIB in "$BASHISHDIR"/lib/_bashish_prompt_*
	do
		BASHISH_FNLOAD=1 . "$BASHISHDIR/lib/${LIB##*/}"
	done
}
_bashish_loadhelpers

## write the shell PID so "bashishtheme" can force a theme update by
## sending a WINCH, which subsequently makes promptupdate to run
test "x${HOSTNAME}" = x && HOSTNAME=$(hostname)

test -d "$HOME/.bashish/tmp/${TTY##*/}" || mkdir -p "$HOME/.bashish/tmp/${TTY##*/}"

printf "$$" >"$HOME"/.bashish/tmp/"${TTY##*/}"/shpid$$
test -f "$HOME/.bashish/tmp/${TTY##*/}/sync" && rm "$HOME/.bashish/tmp/${TTY##*/}/sync"

## restore terminal on best effort
_bashish_restore()
{
	PS2='> '
	PS3='#? '
	PS4='+ '
	## load the fallback prompt to memory
	case "$SHELLNAME" in
	bash)
		PS1='\s-\v\$ '
		unset PROMPT_COMMAND
	;;
	zsh)
		PS1='%m%# '
		PS2='%_> '
		PS3='?# '
		PS4='+%N:%i> '
		unset RPS1 RPS2
		## zsh warns if functions does not exists
		unset -f precmd preexec 2>/dev/null
	;;
	*)
		case '$UID' in
		0) PS1='# ';;
		*) PS1='$ ';;
		esac
	esac
}

## load the fallback prompt to memory
_bashish_promptupdate ()
{
	## self destruct if no .bashish is found (otherwise bashish would install after an uninstall)
	if test -d "${HOME}/.bashish"
	then
		:
	else
		_bashish_restore
		unset -f cd
		unset -f _bashish_promptupdate _bashish_winch_promptupdate
		return 0
	fi
	
	## temporarily disable CTRL+C
	test "x$ZSH_NAME$BASH" != x && trap "" INT
	
	## zsh need this
	test x"$ZSH_NAME" != x && setopt prompt_subst
	
	## check if the theme is unsynced with the latest theme in 
	## bashishtheme, if so, force a theme update
	test -f "$HOME/.bashish/tmp/${TTY##*/}/sync" || {
		unset BASHISH_ASCIILOGO

		## dummy fallback prompt
		_bashish_defaults() { :;}
		_bashish_overrides() { :;}
		_bashish_prompt() { :;}

		## reset scrolling region
		printf "\033[H\033[2J\033[0;0r"
		bashish --init
		hash -r
	
		## load the fallback prompt to memory
		if test -f "$HOME/.bashish/defaults/prompt.$SHELLNAME"
		then
			. "$HOME/.bashish/defaults/prompt.$SHELLNAME"
		else
			if test -f "$HOME/.bashish/defaults/prompt.ksh"
			then
				. "$HOME/.bashish/defaults/prompt.ksh"
			else
				test -f "$HOME/.bashish/defaults/prompt.sh" && . "$HOME/.bashish/defaults/prompt.sh"
			fi
		fi
	
		test -f "$HOME/.bashish/defaults/prompt.$SHELLNAME" && . "$HOME/.bashish/defaults/prompt.$SHELLNAME"
		
		## continue loading if prompt is loaded cleanly
		## if not available, try to use 
		if test -f "$HOME/.bashish/prompt/prompt.$SHELLNAME"
		then
			. "$HOME/.bashish/prompt/prompt.$SHELLNAME"
		else
			if test -f "$HOME/.bashish/prompt/prompt.ksh"
			then
				. "$HOME/.bashish/prompt/prompt.ksh"
			else
				test -f "$HOME/.bashish/prompt/prompt.sh" && . "$HOME/.bashish/prompt/prompt.sh"
			fi
		fi
		
		## prompt overrides
		if test -f "$HOME/.bashish/overrides/prompt.$SHELLNAME"
		then
			. "$HOME/.bashish/overrides/prompt.$SHELLNAME"
		else
			if test -f "$HOME/.bashish/overrides/prompt.ksh"
			then
				. "$HOME/.bashish/overrides/prompt.ksh"
			else
				test -f "$HOME/.bashish/overrides/prompt.sh" && . "$HOME/.bashish/overrides/prompt.sh"
			fi
		fi
		
		## load argv.sh function
		_bashish_prompt_argv() { :;}
		test -f "$HOME/.bashish/prompt/argv.sh" && . "$HOME/.bashish/prompt/argv.sh"

		## a small delay makes the term settle down before reloading the prompt
		#sleep 0.5
		

	}
	
	## restore prompt
	_bashish_restore

	## load defaults
	_bashish_defaults

	## load the bashish prompt
	eval _bashish_prompt $(_bashish_prompt_argv)

	## load overrides
	_bashish_overrides
	
	## load _bashish_title() if available
	_bashish_title
	
	## re-enable CTRL+C
	test "x$ZSH_NAME$BASH" != x && trap INT
}
_bashish_title () { :;}
TEST_TERM="$TERM" _bashish_isxterm && _bashish_title () 
{
	test "x$TITLESTR" = x && TITLESTR="${TITLE}"
	eval $(_bashish_prompt_shellvars $SHELLNAME)
	printf "${ESC}]0;${TITLESTR}${BEL}"
	PS1="${EMBED}${ESC}]0;"'${TITLESTR}'"${BEL}${UNEMBED}"${PS1}
}


## load prompt
_bashish_promptupdate



## winch promptupdate
_bashish_winch_promptupdate()
{
	_bashish_promptupdate
	if test "x$BASH" != x
	then
		:
		$PROMPT_COMMAND
	else
		type precmd >/dev/null && precmd
	fi

}

## re-paint on winch signals
if test "x$BASH" != x
then
	trap "PROMPT_COMMAND=\"unset PROMPT_COMMAND;_bashish_promptupdate\"" WINCH
elif test "x$ZSH_NAME" != x
then
	trap "eval \"precmd () { unset -f precmd; _bashish_promptupdate;}\"" WINCH
fi

## re-paint whenever changing directory
case "$SHELLNAME" in
ksh)
cd ()
{
	unset -f cd
	cd "$@"
	_bashish_promptupdate
	cd ()
	{
		unset -f cd
		cd "$@"
		_bashish_promptupdate
	}
}
;;
bash|zsh)
cd ()
{
	builtin cd "$@"
	_bashish_promptupdate
}
;;
sh)
## sh does not support 'builtin'
cd ()
{
	chdir ${1+"$@"}
	_bashish_promptupdate
}

## posh does not support 'chdir'
type type 1>/dev/null 2>/dev/null || cd ()
{
	builtin cd "$@"
	_bashish_promptupdate
}

esac


## set default title
title ()
{
	## set non-permanent title
	case "$@" in
	-h*) printf "\
title() is part of Bashish by Thomas Eriksson.
title sets the terminal window title.
Usage: title [-n] [TITLE]
-n sets a non-permanent title, otherwise the title will be re-set each time the prompt is displayed
Without argument, a default title will be set.
"
	return 1
	;;
	-n*) shift; local TITLESTR;;
	esac
	if test "x$*" = x
	then
		TITLESTR="${TITLE}"		
	else
		TITLESTR="$*"
	fi
	
	printf "USER_TITLE=\"${TITLESTR}\"" >"$HOME/.bashish/tmp/${TTY##*/}/subproc"
}

## set default prompt string
prompt ()
{
	case "$@" in
	-h*) printf "\
prompt() is part of Bashish by Thomas Eriksson.
prompt sets the terminal prompt string

Usage: prompt [PROMPT]
Without argument, a default prompt will be set.
"
	return 1
	esac
	
	if test "x$*" = x
	then
		PROMPTSTR=""
	else
		PROMPTSTR="$*"
	fi	
	_bashish_promptupdate
}

## name, set prompt and title of current terminal [NAME]
name()
{
	case "$@" in
	-h*) printf "\
name() is part of Bashish by Thomas Eriksson.
name sets the terminal prompt and title string in bashish.

Usage: name [PROMPT]
Without argument, a default prompt and title will be set.
"
	return 1
	esac

	title "$@"
	prompt "$@"
}

## color 
color()
{
	local ARG 2>/dev/null
	case "$@" in
	-h*) printf "\
color() is part of Bashish by Thomas Eriksson.
color sets the color style for the prompt in bashish (if supported by the prompt).

Usage: color [PROMPT]
Without argument, a default prompt color will be set
"
	return 1
	esac
	if test "x$1" = x
	then
		. "$HOME/.bashish/prompt/argv.sh"
	else
		eval "_bashish_prompt_argv() { "$(for ARG in "$@"; do printf "printf \"$ARG\";";done)" }"
	fi
	_bashish_promptupdate
}
