#!/usr/local/bin/zsh
#
# $Id: reporter,v 1.1 1994/07/17 21:53:33 vogelke Exp $
#
# $Source: /d/cdc/vogelke/work/zsh/RCS/reporter,v $
#
# NAME:
#	reporter
#
# SYNOPSIS:
#	reporter [all | aliases | bindings | completion | functions |
#			limits | options | variables]
#
# DESCRIPTION:
#	"reporter" prints your current environment variables, shell
#	variables, limits, completion settings, and option settings to
#	stdout in the form of a script.
#
#	If you run into a zsh bug, someone can source the output script to
#	recreate most of the environment under which you were working.
#
#	IMPORTANT:	"source" this script, don't try to run it directly.
#			Otherwise it won't report the settings for your
#			current shell session.
#
# OPTIONS:
#	All command-line options can be abbreviated.
#
#	"aliases"	prints only aliases.
#	"bindings"	prints only "bindkey" commands.
#	"completion"	prints only "compctl" commands.
#	"functions"	prints "autoload" commands or actual functions.
#	"limits"	prints "limit" commands for things like cputime, etc.
#	"options"	prints "setopt" commands.
#	"variables"	prints both shell and environment variables.
#
#	"all"		tries to find every useful setting under your shell.
#			This is the default, and it's the same as typing all
#			of the above options on the command line.
#
# AUTHOR:
#	Karl E. Vogel <vogelke@c-17igp.wpafb.af.mil>
#	Control Data Systems, Inc.
# 
# CAVEATS:
#	Assumes that you have the following programs in your search path:
#		awk, cut, echo, grep, sed, sort
#	Assumes that your C preprocessor lives in /lib/cpp.
#	Uses (and unsets) variables beginning with "reporter_".
#
# RESTRICTIONS:
#	DON'T:	pretend you wrote it, sell it, or blame me if it breaks.
#	DO:	as ye will an' ye harm none.
#					--Wiccan saying, I think
#
# BUGS:
#	I'm sure there are more than a few.  To be safe, run "zsh -f" before
#	sourcing the output from this script.  If you have "screen", you may
#	want to use that, too; I hammered my terminal settings beyond repair
#	when using an early version, and "screen" saved me from having to
#	login on another terminal.
#
# HISTORY:
#	The name was ripped off from the Emacs "reporter.el" function.
#	The idea came from a mail message to the ZSH mailing list:
#
#		From: michael lamoureux <lamour@engin.umich.edu>
#		Date: Fri, 15 Jul 1994 12:42:22 -0400
#		Message-Id: <199407151642.MAA14472@erpland.engin.umich.edu>
#		Resent-Message-Id: <199407151653.AA26588@sparky.sterling.com>
#
#	$Log: reporter,v $
# Revision 1.1  1994/07/17  21:53:33  vogelke
# Initial revision
#
#

reporter_do_all=yes

for each in $*
do
	case "$each"
	in
		ali*)	reporter_do_aliases=yes; reporter_do_all=no ;;
		b*)	reporter_do_bindings=yes; reporter_do_all=no ;;
		c*)	reporter_do_compctl=yes; reporter_do_all=no ;;
		f*)	reporter_do_fun=yes; reporter_do_all=no ;;
		l*)	reporter_do_lim=yes; reporter_do_all=no ;;
		o*)	reporter_do_setopt=yes; reporter_do_all=no ;;
		v*)	reporter_do_vars=yes; reporter_do_all=no ;;
		*)	;;
	esac
done

#
#	UNAME
#
#	This shows your system name.  It's extremely system-dependent, so
#	we need a way to find out what system you're on.  The only thing
#	I can think of is to check what's defined in your C compiler.
#	Pyramid has "uname" only in the ATT universe.
#
#	This section of code sees what is defined by "cpp".  It was
#	originally written by brandy@tramp.Colorado.EDU (Carl Brandauer).
#	Additional error checking and sed hacking added by Ken Phelps.
#

reporter_cppdef=`strings -3 /lib/cpp |
	sed -n '
	/^[a-zA-Z_][a-zA-Z0-9_]*$/{
	s/.*/#ifdef &/p
	s/.* \(.*\)/"\1";/p
	s/.*/#endif/p
	}
	' |/lib/cpp |sed '
	/^[	 ]*$/d
	/^#/d
	s/.*"\(.*\)".*/\1/'`

reporter_uname="uname"

for each in $reporter_cppdef
do
	case "$each"
	in
		unix)		;;
		__LINE__)	;;
		__FILE__)	;;
		pyr)		reporter_uname="att uname" ;;
	esac
done

str=`eval $reporter_uname -a`

echo '# START zsh saveset'
echo '# uname: ' $str
echo

unset reporter_cppdef
unset reporter_uname

#
#	ALIASES
#
#	The sed nonsense is to make sure that any single-quote found
#	inside an alias is escaped properly.  The alias commands
#	are written using single-quotes in the form
#
#		alias something='something else'
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_aliases" = "yes"
then
	echo '# Aliases.'
	echo

	alias | sed -e "s/'/\\\'/g" | sed -e "s/=/=\'/" -e "s/\$/'/" |
		awk '{print "alias " $0}'
fi

#
#	KEY BINDINGS
#
#	You may get an occasional message stating that a key is not bound,
#	but I don't think this will cause any problems.
#	It hasn't for me. :)
#
#	The sed nonsense is to make sure that a key-binding like \e" is
#	handled correctly.  I don't know how to handle ranges of keys
#	(like "something to something is bound to self-insert") so I ignore
#	them.
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_bindings" = "yes"
then
	echo
	echo "# Key bindings."
	echo

	bindkey | grep -v '" to "' | cut -f1 |
		sed -e 's/\^\[/\\e/' -e 's/""/\\""/' |
		awk '{print "bindkey -r " $0}'
	echo
	bindkey | grep -v '" to "' |
		sed -e 's/\^\[/\\e/' -e 's/""/\\""/' |
		awk 'NF > 1 {print "bindkey " $0}'
fi

#
#	COMPLETION COMMANDS
#
#	I don't know how to handle the COMMAND and DEFAULT output lines
#	from compctl, so I just ignored them.  The last grep command is
#	for handling the following output lines from compctl:
#
#		 -f
#		+ -f
#		-H -f
#		0 -f
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_compctl" = "yes"
then
	echo
	echo "# Completions."
	echo

	compctl | grep -v 'COMMAND' | grep -v 'DEFAULT' | grep -v '^[ +0-]' |
		awk '{printf "compctl %s %s %s\n", $2, $3, $1}'
fi

#
#	FUNCTIONS
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_fun" = "yes"
then
	echo 
	echo "# Undefined functions."
	echo

	functions | grep "undefined" | awk '{print "autoload " $2}'

	echo 
	echo "# Defined functions."
	echo

	functions | grep -v "undefined"
fi

#
#	LIMITS
#
#	"cputime" has to be handled specially, because you can specify
#	the time as just hours, or "minutes:seconds".
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_lim" = "yes"
then
	echo
	echo '# Limits.'
	echo

	(
		set X `limit | grep "cputime" | grep -v "unlimited" |
			sed -e 's/:/ /g'`

		if test "$#" -gt 1
		then
			hr=$3
			min=$4
			sec=$5

			if test "$hr" -gt 0
			then
				echo "limit cputime ${hr}h"
			else
				echo "limit cputime $min:$sec"
			fi
		fi
	)

	limit | grep -v "cputime" | grep -v "unlimited" |
		sed -e 's/Mb/m/' -e 's/Kb/k/' |
		awk 'NF > 1 {print "limit " $0}'
fi

#
#	NON-ARRAY VARIABLES
#
#	We run this in a subshell to preserve the TERMCAP and TERM settings
#	in the current shell.  Also, reset the prompt to show you're now
#	in a test shell.  I can't find an easy way to do IFS, so I ignore it.
#
#	Most of the sed nonsense is to make sure that variables are quoted
#	when being set.  We also have to make sure that single-quotes and
#	back-quotes are escaped.  This is why variable settings are
#	surrounded by double quotes; some variables like SPROMPT have single
#	quotes and back-quotes, and it's just too hard to escape those
#	properly when setting them.
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_vars" = "yes"
then
	echo
	echo "# Non-array variables."
	echo

	(
		echo "TERMCAP='$TERMCAP'"
		echo "TERM='$TERM'"
		unset TERMCAP

		set | grep '=' | grep -v 'prompt=' |
			grep -v 'reporter_do' |
			grep -v '^[!#$*0?@_-]=' |
			grep -v '=(' | sed -e "s/'/\\\'/g" |
                        sed -e 's/`/\\`/g' |
			sed -e 's/=/="/' -e 's/$/"/' |
			grep -v '^IFS=' |
			grep -v '^TERMCAP=' |
			grep -v '^TERM='

		echo "prompt='test%'"
	)

#
#	ARRAY VARIABLES
#
#	The "grep -v" nonsense is to keep from setting shell variables
#	that caused me some trouble from a script.
#

	echo
	echo "# Array variables."
	echo

	echo "argv=()"
	set | grep '=' | grep -v 'argv=' |
		grep -v 'reporter_do' | grep -v '^[!#$*0?@_-]=' |
		grep '=('

#
#	EXPORTED VARIABLES
#
#	Run this in a subshell to preserve the TERM and TERMCAP setting in
#	the current shell.
#

	echo
	echo "# Exported variables."
	echo

	(
		echo "export TERMCAP"
		echo "export TERM"
		unset TERMCAP

		export | grep -v '^[!#$*0?@_-]=' |
			awk -F='=' '{print "export " $1}' |
			grep -v '^TERM=' | grep -v '^TERMCAP='
	)
fi

#
#	SETOPT
#
#	We exclude interactive because "setopt interactive" has no effect.
#

if test "$reporter_do_all" = "yes" -o "$reporter_do_setopt" = "yes"
then
	echo
	echo '# Setopt.'
	echo

	setopt | sort | grep -v 'interactive' | awk '{print "setopt " $0}'
fi

echo
echo '# END zsh saveset'

#
#	Don't put an exit here, or you'll get a nasty surprise when you
#	source this thing.  Get rid of variables created when processing
#	command line.
#

unset reporter_do_all
unset reporter_do_aliases
unset reporter_do_bindings
unset reporter_do_compctl
unset reporter_do_fun
unset reporter_do_lim
unset reporter_do_setopt
unset reporter_do_vars
