### vim:ft=zsh:foldmethod=marker
###
### This is the real setup file.
### All magic starts here.
###
### Frank Terbeck <ft@bewatermyfriend.org>
### Last-Modified: Tue Dec 25 17:24:26 2007
###
### URI: <http://ft.bewatermyfriend.org/comp/zsh.html>
###
### startup message
(( ZSHRC_VERBOSE > 0 )) && printf 'Starting zsh v%s\n' ${ZSH_VERSION}
### this array will contain the files we'll try to source
ZRCS=()
### helper functions {{{
### $ZRCS[] builder;
### + handles files that shouldn't give errors if they don't exist
function zrcsource() { #{{{
setopt local_options
### Note that zsh version 3.0.5 and earlier needs extendedglob
### to be switched on to make '~/...' expansions work in ZRCSOURCE_DIR.
### This does not hurt in newer versions, so I'll set this here.
setopt extended_glob
local file
file="${ZRC_SOURCE_DIR}/${1}"
if [[ -r ${~file} ]] ; then
ZRCS=( ${ZRCS} ${~file} )
elif [[ -z ${2} ]] ; then
ZRCS=( ${ZRCS} ${~file} )
else
(( ZSHRC_VERBOSE > 0 )) && printf 'zshrc: ignoring non-existant file: %s\n' ${~file}
fi
} #}}}
### Okay, this is overkill. But this config got too big a long time ago.
### So, who cares? :-)
### Anyway: Since this config is split into various files, some files
### depend on others to be sourced already. Because of that, I introduced
### the possibility of every file added to $ZRCS[] via zrcsource() to start
### with '#zdep ...' in the 1st line (where ... is a comma seperated list of
### files that file requires to be loaded already).
###
### To cut a long story short: zdepend() resorts $ZRCS[] to reflect the
### information found in the #zdep lines.
function zdepend() { #{{{
# be verbose if $ZSHRC_VERBOSE >= 5
local zdepdebug=0
(( zdepdebug == 1 )) && set -x
local added=1 untagged=0 satisfied subsat
local sortedRCS ; sortedRCS=()
local file buf tmp tag istag dep deplist sorted
local deps tags ; deps=() ; tags=( __all__ __begin__ __end__ )
### read the #zdep lines {{{
### yes, this is insane. :-) - But I want to know if it's doable.
for file in ${ZRCS} ; do
read buf < $file
if [[ ${buf} != '#zdep '* ]] ; then
### files names 'zshrc.local' are always tagged __end__, if the #zdep line is missing.
if [[ ${file} == *'/zshrc.local' ]] ; then
deps=(${deps} "${file}:__end__")
else
deps=(${deps} "${file}:")
fi
continue
fi
buf="${buf#\#zdep }"
tmp=(${(s:,:)buf})
if [[ -n ${tmp[1]} ]] ; then
istag=0
for tag in ${tags} ; do
if [[ ${tag} == ${tmp[1]} ]] ; then
istag=1
break
fi
done
if (( istag > 0 )) ; then
deps=(${deps} "${file}:${tmp[1]}")
continue
fi
buf="${ZRC_SOURCE_DIR}/${tmp[1]}"
shift tmp
else
buf=""
fi
for i in ${tmp} ; do
for tag in ${tags} ; do
if [[ ${tag} == ${i} ]] ; then
istag=1
break
fi
done
if (( istag > 0 )) ; then
deps=(${deps} "${file}:${i}")
break
fi
buf="${buf},${ZRC_SOURCE_DIR}/${i}"
done
tmp=""
deps=(${deps} "${file}:${buf#\#zdep }")
done
### }}}
for file in ${deps} ; do [[ ${file} != *:__*__ ]] && untagged=$((untagged + 1)) ; done
for file in ${deps} ; do [[ ${file} == *:__begin__ ]] && sortedRCS=(${sortedRCS} ${file%:*}) ; done
untagged=$((untagged + ${#sortedRCS}))
### resolve dependencies {{{
### okay, reading the '#zdep' lines wasn't too cheap. Yet, this
### loop is really expensive. But since it only handles a few strings,
### I'll do it. :-)
while true ; do
if (( added > 0 )) ; then
added=0
else
printf "zdepend(): Dependency problems. Giving up.\n"
print -l ${sortedRCS}
return 1
fi
for tmp in ${deps} ; do
file=${tmp%:*} ; deplist=${tmp#*:} ; satisfied=1
for sorted in ${sortedRCS} ; do [[ ${sorted} == ${file} ]] && continue 2 ; done
for dep in ${(s:,:)deplist} ; do
for sorted in ${sortedRCS} ; do
subsat=0
[[ ${sorted} == ${dep} ]] && subsat=1 && break
done
(( subsat == 0 )) && satisfied=0 && break
done
(( satisfied > 0 )) && sortedRCS=(${sortedRCS} ${file%:*}) && added=$((added + 1))
done
(( ${#sortedRCS} >= untagged )) && break
done
### }}}
for file in ${deps} ; do [[ ${file} == *:__all__ ]] && sortedRCS=(${sortedRCS} ${file%:*}) ; done
for file in ${deps} ; do [[ ${file} == *:__end__ ]] && sortedRCS=(${sortedRCS} ${file%:*}) ; done
(( zdepdebug == 1 )) && set +x
(( ZSHRC_VERBOSE >= 5 )) && printf 'zshrc source order:\n' && for tmp in ${sortedRCS} ; do printf ' + %s\n' "${tmp}" ; done
ZRCS=(${sortedRCS})
return 0
} #}}}
### this VERSION_* array solution could be more elegant,
### but zsh versions prior to 3.1.6 do not support associative arrays.
### so, to stay backwards compatible we do not use them here.
VERSION_TABLE=( #{{{
"3.0.6" "3.1.4" "3.1.6" "3.1.7"
"4.0.2" "4.2.1" "4.2.2"
"3.0" "3.1" "4.0" "4.1"
"4.2" "4.3"
) #}}}
VERSION_SHORT=( #{{{
"306" "314" "316" "317"
"402" "421" "422"
"30" "31" "40" "41"
"42" "43"
) #}}}
VERSION_CHECKS_ATLEAST=( #{{{
'${ZSH_VERSION} == 3.0.<6->* || ${ZSH_VERSION} == 3.<1->.<->* || ${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == 3.1.<4->* || ${ZSH_VERSION} == 3.<2->.<->* || ${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == 3.1.<6->* || ${ZSH_VERSION} == 3.<2->.<->* || ${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == 3.1.<7->* || ${ZSH_VERSION} == 3.<2->.<->* || ${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == 4.0.<2->* || ${ZSH_VERSION} == 4.<1->.<->* || ${ZSH_VERSION} == <5->.<->*'
'${ZSH_VERSION} == 4.2.<1->* || ${ZSH_VERSION} == 4.<3->.<->* || ${ZSH_VERSION} == <5->.<->*'
'${ZSH_VERSION} == 4.2.<2->* || ${ZSH_VERSION} == 4.<3->.<->* || ${ZSH_VERSION} == <5->.<->*'
'${ZSH_VERSION} == <3->.<->*'
'${ZSH_VERSION} == 3.<1->.<->* || ${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == <4->.<->*'
'${ZSH_VERSION} == 4.<1->.<->* || ${ZSH_VERSION} == <5->.<->*'
'${ZSH_VERSION} == 4.<2->.<->* || ${ZSH_VERSION} == <5->.<->*'
'${ZSH_VERSION} == 4.<3->.<->* || ${ZSH_VERSION} == <5->.<->*'
) #}}}
VERSION_CHECKS=( #{{{
'${ZSH_VERSION} == 3.0.6' '${ZSH_VERSION} == 3.1.4' '${ZSH_VERSION} == 3.1.6'
'${ZSH_VERSION} == 3.1.7' '${ZSH_VERSION} == 4.0.2' '${ZSH_VERSION} == 4.2.1'
'${ZSH_VERSION} == 4.2.2'
'${ZSH_VERSION} == 3.0.*' '${ZSH_VERSION} == 3.1.*' '${ZSH_VERSION} == 4.0.*'
'${ZSH_VERSION} == 4.1.*' '${ZSH_VERSION} == 4.2.*' '${ZSH_VERSION} == 4.3.*'
) #}}}
### generating zis_*() {{{
if [[ ${#VERSION_TABLE} != ${#VERSION_CHECKS_ATLEAST}
|| ${#VERSION_TABLE} != ${#VERSION_SHORT}
|| ${#VERSION_TABLE} != ${#VERSION_CHECKS} ]] ; then
printf 'Automatic zis_*() generation failed! Using fallback. Please check.\n'
for i in {1..${#VERSION_TABLE}} ;do
eval "function zis_${VERSION_SHORT[$i]}() { return 0 }"
done
else
for i in {1..${#VERSION_TABLE}} ; do
eval "function zis_${VERSION_SHORT[$i]}() { \
if [[ \${1} == \"atleast\" ]] ; then [[ ${VERSION_CHECKS_ATLEAST[$i]} ]] && return 0 ; \
else [[ ${VERSION_CHECKS[$i]} ]] && return 0 ; fi ; \
(( ZSHRC_VERBOSE > 3 )) && printf \" + zis_${VERSION_SHORT[$i]}: this is not %s (%s)\\n\" ${VERSION_TABLE[$i]}; return 1 }"
done
fi
### }}}
### wrapper for autoload
function zrcautoload() { #{{{
setopt local_options
setopt extended_glob
local fdir ffile
local -i ffound
ffile=${1}
(( found = 0 ))
for fdir in ${fpath} ; do
[[ -e ${fdir}/${ffile} ]] && (( ffound = 1 ))
done
if (( ffound == 0 )) ; then
(( ZSHRC_VERBOSE > 1 )) && printf " zrcautoload: cannot find %s\n" ${ffile}
return 1
fi
(( ZSHRC_VERBOSE > 2 )) && printf " zrcautoload: loading %s\n" ${ffile}
if zis_316 "atleast" ; then
autoload -U ${ffile} || return 1
else
autoload ${ffile} || return 1
fi
return 0
} #}}}
### check if rc needs recompilation
function zrcneedcomp() { #{{{
local recomp
local rc=${1:t}
if [[ -z ${1} ]] ; then
printf "usage: ${0} <rcfile>\n"
return 0
fi
if ! zis_317 "atleast" ; then
(( ZSHRC_VERBOSE > 3 )) && printf " zrcneedcomp(): rccompilation needs at least zsh v3.1.7\n"
return 0
fi
if [[ ! -e ${1}.zwc ]] ; then
(( ZSHRC_VERBOSE > 2 )) && printf " zrcneedcomp(): ${rc}.zwc does not exist,\n - marking for compilation.\n"
return 1
fi
if [[ ${1} -nt ${1}.zwc ]] ; then
(( ZSHRC_VERBOSE > 2 )) && printf " zrcneedcomp(): ${rc} is newer than ${rc}.zwc,\n"
recomp=1
elif ! zcompile -t ${1}.zwc >/dev/null 2>&1 ; then
(( ZSHRC_VERBOSE > 2 )) && printf " zrcneedcomp(): ${rc}.zwc is compiled for different zsh version,\n"
recomp=1
fi
if (( recomp > 0 )) ; then
(( ZSHRC_VERBOSE > 2 )) && printf " - marking for recompilation.\n"
return 2
fi
return 0
} #}}}
### }}}
### warm greeting to those living in stone age ;) {{{
if ! zis_40 "atleast" ; then
printf "\n"
printf " +----------------------------------------------------------------------\n"
printf " |\n"
printf " | Howdy stone-ager!\n"
printf " |\n"
printf " | You are running version %s of zsh.\n" ${ZSH_VERSION}
printf " | That is quite old.\n"
printf " |\n"
printf " | You should consider updating to at least v4.0\n"
printf " | If that is not up to you, bug your admin until he does. ;)\n"
printf " | The newer versions do really have nice features\n"
printf " | that these fossils do not.\n"
printf " |\n"
printf " | The completion system improves with every release. Believe me.\n"
printf " |\n"
printf " | Versions v4.3+ have multibyte support built in.\n"
printf " | So, if you are in a UTF-8 locale, that is for you.\n"
printf " |\n"
printf " | Anyway, have fun using zsh. :-)\n"
printf " |\n\n"
fi #}}}
### build $ZRCS[]
zrcsource "aliases" ### setup aliases
### setup proper completion system for current zsh version
if zis_317 "atleast" ; then
zrcsource "compsys"
else
zrcsource "compctl"
fi
zrcsource "misc" ### other configuration
zrcsource "modules" ### load modules
zrcsource "options" ### setup zsh's options
zrcsource "path" ### set *path
zrcsource "vars" ### setup variables
zrcsource "zcleanup" ### cleanups
zrcsource "zfunct" ### functions file
zrcsource "zle" ### setup zsh's line editor
zrcsource "zshrc.local" '__local_settings;_do_not_care_if_it_is_missing__'
### re-sort $ZRCS[] based on #zdep lines.
zdepend
### compile 'zshrc' and 'zshrc.real' if needed.
if (( ZSHRC_COMPILE > 0 )) && zis_317 "atleast" ; then #{{{
for rc in 'zshrc' 'zshrc.real' ; do
if [[ -r "${ZRC_SOURCE_DIR}/${rc}" ]] ; then
zrcneedcomp "${ZRC_SOURCE_DIR}/${rc}"
needc=${?}
if (( needc > 0)) ; then
if (( needc == 1 )) ; then
(( ZSHRC_VERBOSE > 0 )) && printf "zshrc: compiling ${rc}.zwc\n"
elif (( needc == 2 )) ; then
(( ZSHRC_VERBOSE > 0 )) && printf "zshrc: recompiling ${rc}.zwc\n"
rm -f "${ZRC_SOURCE_DIR}/${rc}.zwc"
fi
zcompile -URz "${ZRC_SOURCE_DIR}/${rc}"
fi
fi
done
fi #}}}
### and finally try to source the files in $ZRCS[]
for rc in ${ZRCS} ; do #{{{
if [[ -r ${rc} ]] ; then
(( ZSHRC_VERBOSE > 0 )) && printf "zshrc: loading %s\n" ${rc}
### zcompile support
if (( ZSHRC_COMPILE > 0 )) ; then
zrcneedcomp ${rc}
needc=${?}
if (( needc > 0)) ; then
if (( needc == 1 )) ; then
(( ZSHRC_VERBOSE > 0 )) && printf "zshrc: compiling ${rc}.zwc\n"
elif (( needc == 2 )) ; then
(( ZSHRC_VERBOSE > 0 )) && printf "zshrc: recompiling ${rc}.zwc\n"
rm -f ${rc}.zwc
fi
zcompile -URz ${rc}
fi
fi
### End of zcompile support
source ${rc}
else
printf "zshrc: could not load %s\n" ${rc}
fi
done #}}}