################################################################################
# Stash/unstash support for per-directory variables
#
+# Adopted for zsh-autoenv.
+#
# Copyright (c) 2009,2012 Dave Olszewski <cxreg@pobox.com>
# http://github.com/cxreg/smartcd
#
# autostash PATH
# export PATH=/something/else
#
-# You may also do both operations on line line, leaving only the very succinct
+# You may also do both operations in one line, resulting in the very succinct
#
# autostash PATH=/something/else
#
-# If you run stash, unstash, or varstash interactively, they will instruct
-# you on how to create smartcd scripts for performing those actions
-# automatically. You can affect this behavior with several variables:
-#
-# VARSTASH_QUIET - Set if you'd rather not see these notices
-#
-# VARSTASH_AUTOCONFIG - Set if you want the suggested actions to be
-# performed automatically
-#
-# VARSTASH_AUTOEDIT - Set if you want it to set the values, but also
-# give you an opportunity to edit the file
-#
# If you attempt to stash the same value twice, a warning will be displayed
# and the second stash will not occur. To make it happen anyway, pass -f
# as the first argument to stash.
local force=1; shift
fi
- if [[ -n $1 ]] && [[ -z $run_from_smartcd ]] && [[ -z $run_from_autostash ]]; then
- local working_dir="${varstash_dir:-$(pwd)}"
- local smartcd_dir="$(_smartcd_base)/scripts$working_dir"
- local help_action="stashing a variable"
- local help_dir=$smartcd_dir
- local help_cmd="echo stash $@ >> \"$smartcd_dir/bash_enter\""
- local help_which="bash_enter"
- _manual_stash_help
- fi
-
-
while [[ -n $1 ]]; do
- if [[ $1 == "alias" && $2 =~ "=" ]]; then
+ if [[ $1 == "alias" && $2 == *=* ]]; then
shift
local _stashing_alias_assign=1
continue
# Handle any variable that may exist under this name
local vartype="$(declare -p $stash_which 2>/dev/null)"
if [[ -n $vartype ]]; then
- if [[ -n $ZSH_VERSION ]]; then
- local pattern="^typeset"
- else
- local pattern="^declare"
- fi
- if [[ $vartype =~ $pattern" -a" ]]; then
+ if [[ $vartype == 'typeset -a'* ]]; then
# varible is an array
if [[ -z $already_stashed ]]; then
eval "__varstash_array__$stash_name=(\"\${$stash_which""[@]}\")"
fi
- elif [[ $vartype =~ $pattern" -x" ]]; then
+ elif [[ $vartype == "export "* || $vartype == 'typeset -x'* ]]; then
# variable is exported
if [[ -z $already_stashed ]]; then
- eval "__varstash_export__$stash_name=\"\$$stash_which\""
+ eval "export __varstash_export__$stash_name=\"\$$stash_which\""
fi
if [[ $stash_which != $stash_expression && -z $_stashing_alias_assign ]]; then
eval "export $stash_which=\"$stash_value\""
# (eval):1: command not found: __varstash_nostash___tmp__home_dolszewski_src_smartcd_RANDOM_VARIABLE=1
# fixed in zsh commit 724fd07a67f, version 4.3.14
if [[ -z $already_stashed ]]; then
- eval "__varstash_nostash__$stash_name=1"
+ eval "export __varstash_nostash__$stash_name=1"
fi
# In the case of a previously unset variable that we're assigning too, export it
done
}
-function autostash() {
- if [[ -n $1 ]] && [[ -z $run_from_smartcd ]]; then
- local working_dir="${varstash_dir:-$(pwd)}"
- local smartcd_dir="$(_smartcd_base)/scripts$working_dir"
- local help_action="autostashing a variable"
- local help_dir=$smartcd_dir
- local help_cmd="echo autostash $@ >> \"$smartcd_dir/bash_enter\""
- local help_which="bash_enter"
- _manual_stash_help
+function get_autostash_array_name() {
+ local autostash_name=$(_mangle_var AUTOSTASH)
+ # Create a scalar variable linked to an array (for exporting).
+ local autostash_array_name=${(L)autostash_name}
+ if ! (( ${(P)+autostash_array_name} )); then
+ # Conditionally set it, to prevent error with Zsh 4.3:
+ # can't tie already tied scalar: ...
+ typeset -xT $autostash_name $autostash_array_name
fi
+ ret=$autostash_array_name
+}
+function autostash() {
local run_from_autostash=1
while [[ -n $1 ]]; do
- if [[ $1 == "alias" && $2 =~ "=" ]]; then
+ if [[ $1 == "alias" && $2 == *=* ]]; then
shift
local _stashing_alias_assign=1
fi
local already_stashed=
stash "$1"
if [[ -z $already_stashed ]]; then
- local autostash_name=$(_mangle_var AUTOSTASH)
- local varname=${1%%'='*}
- apush $autostash_name "$varname"
+ local ret varname=${1%%'='*}
+ get_autostash_array_name
+ eval "$ret=(\$$ret \$varname)"
fi
shift
unset -v _stashing_alias_assign
}
function unstash() {
- if [[ -n $1 ]] && [[ -z $run_from_smartcd ]] && [[ -z $run_from_autounstash ]]; then
- local working_dir=${varstash_dir:-$(pwd)}
- local smartcd_dir="$(_smartcd_base)/scripts$working_dir"
- local help_action="unstashing a variable"
- local help_dir=$smartcd_dir
- local help_cmd="echo unstash $@ >> \"$smartcd_dir/bash_leave\""
- local help_which="bash_leave"
- _manual_stash_help
- fi
-
while [[ -n $1 ]]; do
local unstash_which=$1
if [[ -z $unstash_which ]]; then
fi
if [[ ( -n "$nostash" && -z "$unstashed" ) || ( -n "$unstashed" && -z "$unstashed_variable" ) ]]; then
# Don't try to unset illegal variable names
- if ! [[ $unstash_which =~ [^a-zA-Z0-9_] || $unstash_which =~ ^[0-9] ]]; then
+ # Using substitution to avoid using regex, which might fail to load on Zsh (minimal system).
+ if [[ ${unstash_which//[^a-zA-Z0-9_]/} == $unstash_which && $unstash_which != [0-9]* ]]; then
unset -v $unstash_which
fi
fi
function autounstash() {
# If there is anything in (mangled) variable AUTOSTASH, then unstash it
- local autounstash_name=$(_mangle_var AUTOSTASH)
- if (( $(alen $autounstash_name) > 0 )); then
+ local ret
+ get_autostash_array_name
+ if (( ${#${(P)ret}} > 0 )); then
local run_from_autounstash=1
- while (( $(alen $autounstash_name) > 0 )); do
- local autounstash_var=$(afirst $autounstash_name)
- ashift $autounstash_name >/dev/null
+ for autounstash_var in ${(P)ret}; do
unstash $autounstash_var
done
- unset $autounstash_name
+ unset $ret
fi
}
function _mangle_var() {
- local mangle_var_where="${varstash_dir:-$(pwd)}"
+ local mangle_var_where="${varstash_dir:-$PWD}"
mangle_var_where=${mangle_var_where//[^A-Za-z0-9]/_}
local mangled_name=${1//[^A-Za-z0-9]/_}
echo "_tmp_${mangle_var_where}_${mangled_name}"
}
-function _manual_stash_help() {
- # instruct user how to create bash_enter or bash_leave
- if [[ -n $VARSTASH_AUTOEDIT || -n $VARSTASH_AUTOCONFIG ]]; then
- if [[ -z $VARSTASH_QUIET ]]; then
- echo "varstash: Automatically running $help_cmd"
- fi
-
- if [[ ! -d $help_dir ]]; then
- mkdir -p "$help_dir"
- fi
- eval $help_cmd
-
- if [[ -n $VARSTASH_AUTOEDIT ]]; then
- varstash_edit $help_which
- fi
- elif [[ -z $VARSTASH_QUIET ]]; then
- echo "############################################################################"
- echo "# You are manually $help_action. To automatically perform this"
- echo "# whenever you enter this directory, paste the following command(s):"
-
- if [[ ! -d $help_dir ]]; then
- echo "mkdir -p \"$help_dir\""
- fi
- echo "$help_cmd"
- echo "############################################################################"
- fi
-}
-
-# A couple convenient aliases for smartcd_edit
-function autostash_edit() {
- varstash_edit "$@"
-}
-
-function varstash_edit() {
- local file="$1"
- local dir="$2"
-
- if [[ -n $ZSH_VERSION ]]; then
- if [[ $(type smartcd_edit) == "smartcd_edit is a shell function" ]]; then
- local can_run=1
- fi
- else
- if [[ $(type -t smartcd_edit) == "function" ]]; then
- local can_run=1
- fi
- fi
-
- if [[ -n "$can_run" ]]; then
- # XXX - no support for "--host" or "--system" with this (yet?)
- _smartcd_file_check "$file" "global" "" edit "$dir"
- else
- echo "smartcd not loaded, cannot run smartcd_edit"
- fi
-}
-
-# Run deferred smartcd if we're waiting for it, and arrays is also loaded
-if [[ -n "$smartcd_initially_deferred" && -n "$(fn_exists apush)" && -z "$SMARTCD_NOINITIAL" ]]; then
- smartcd_skip_action=1
- smartcd_run_mainline=1
- smartcd cd
- unset smartcd_skip_action
- unset smartcd_initially_deferred
-fi
-
-# vim: filetype=sh autoindent expandtab shiftwidth=4 softtabstop=4
+# vim: filetype=zsh autoindent expandtab shiftwidth=4 softtabstop=4