#!/usr/local/bin/zsh # # 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. # "modules" prints "zmodload" commands. # "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. # # 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 or /usr/ccs/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: # # Begin Configuration Section # reporter_OSVersion="`uname -s`_`uname -r`" # # Solaris 2.x # case ${reporter_OSVersion} in SunOS_5.*) CPP=${CPP:-/usr/ccs/lib/cpp} AWK=${AWK:-nawk} # GNU AWK doesn't come standard :-( ;; esac # # Default Values # CPP=${CPP:-/lib/cpp} AWK=${AWK:-awk} # # End Configuration Section # 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 ;; m*) reporter_do_mod=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 # # The "cshjunkiequotes" option can break some of the commands # used in the remainder of this script, so we check for that first # and disable it. We'll re-enable it later. # reporter_junkiequotes="no" if setopt | grep "cshjunkiequotes" > /dev/null then reporter_junkiequotes="yes" unsetopt cshjunkiequotes fi # # 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 easiest # way to do this is by using "uname", but not everyone has that, # so first we go through the search path. # # If we don't find it, then the only thing I can think of is to # check what's defined in your C compiler, and code in some exceptions # for the location of "uname" or an equivalent. For example, Pyramid # has "uname" only in the ATT universe. This code assumes that # the "-a" switch is valid for "uname". # # 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 ${CPP} | sed -n ' /^[a-zA-Z_][a-zA-Z0-9_]*$/{ s/.*/#ifdef &/p s/.* \(.*\)/"\1";/p s/.*/#endif/p } ' | ${CPP} |sed ' /^[ ]*$/d /^#/d s/.*"\(.*\)".*/\1/'` reporter_uname="" for each in `echo $PATH | sed -e 's/:/ /g'` do if [ -x $each/uname ] then reporter_uname="$each/uname" break fi done case "$reporter_uname" in "") reporter_uname="echo not found on this system" ;; *) ;; esac for each in $reporter_cppdef do case "$each" in pyr) reporter_uname="/bin/att uname" ;; *) ;; esac done str=`eval $reporter_uname -a` echo '# START zsh saveset' echo '# uname: ' $str echo unset reporter_cppdef unset reporter_uname # # ALIASES # # Use "alias -L" to get a listing of the aliases in the form we want. # if test "$reporter_do_all" = "yes" -o "$reporter_do_aliases" = "yes" then echo '# Aliases.' echo alias -L fi # # KEY BINDINGS # # The -L option does most of the work. The subshell is used to # avoid modifying things that will be recorded later. # if test "$reporter_do_all" = "yes" -o "$reporter_do_bindings" = "yes" then echo echo "# Key bindings." echo bindkey -lL ( alias bindkey=bindkey bindkey () { [[ "$1" == "-N" ]] || return [[ "$2" == "--" ]] && shift echo builtin bindkey -L -M -- "$2" } eval "`builtin bindkey -lL`" ) fi # # COMPLETION COMMANDS # Warning: this won't work for zsh-2.5.03. # if test "$reporter_do_all" = "yes" -o "$reporter_do_compctl" = "yes" then echo echo "# Completions." echo compctl -L 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 # # MODULE LOADING COMMANDS # if test "$reporter_do_all" = "yes" -o "$reporter_do_mod" = "yes" then echo if ( zmodload ) >& /dev/null; then echo "# Modules." echo zmodload -d -L echo zmodload -ab -L echo zmodload -ac -L echo zmodload -ap -L echo zmodload -L else echo "# Modules: zmodload not available." fi 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. # The cshjunkiequotes option is dealt with separately; see the # comments near the start of the script. # if test "$reporter_do_all" = "yes" -o "$reporter_do_setopt" = "yes" then echo echo '# Setopt.' echo ( setopt | grep -v 'interactive' | ${AWK} '{print "setopt " $0}' case "$reporter_junkiequotes" in yes) echo "setopt cshjunkiequotes" ;; *) ;; esac ) | sort 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 # # Turn cshjunkiequotes back on if necessary. # case "$reporter_junkiequotes" in yes) setopt cshjunkiequotes ;; *) ;; esac unset reporter_junkiequotes