#!/bin/zsh # # dual - automatically updates path-array combinations. # i.e. setting BLAH=a:b:c also sets blah=(a b c) and # vice versa. # # This behaviour is planned for release in version 2.6 of zsh, where # it will presumably be as transparent as every other variable # type. In the mean time, this will accomplish the same thing. # # [2000-09-29] # Version 3.1.6 of zsh automates this functionality with # typeset -T. I'll leave this function here for historical purposes. # # Usage: # dual [var[=val]] . . . # # where # var is a variable to mark as being dual, that is, when dual # sets foo, it also sets FOO. # val is the value to assign to var. Because it is interpreted # by the shell twice, replace every \ by \\\ to receive the # same behaviour. # # Note that because this is not really a part of zsh, but just an # add-on, doing # foo=(a b c d) # will not set FOO to A:B:C:D. You must explicitly say # dual foo=(a b c d) # Likewise, FOO=a:b:c:d will not work on its own. Prefix it with dual. # # To do: # This is a little over-large. There's no real need to keep a list of # variables that are dual, at least not with this small implementation. # As a result undual isn't necessary either, though one does exist. # I did it mainly for interest's sake. # Currently this function assumes unsetopt shwordsplit # scan each variable given for var do # get name name=${var%%\=*} # This next bit needed because for some reason ${foo%%\=*} doesn't strip # the = if it's all there is. Use ${foo%\=*} and it does. This # doesn't happen with the equivalent # or ## format. Bizarre. if [[ $name[-1] = "=" ]] then name=$name[1,-2] fi # value to assign. if [[ "$var" = *\=* ]] then eval "val=${var#$name\=}" else val= fi # get lower- and upper-case versions. lower=${(L)name} upper=${(U)name} # check for obvious errors - no letters, mixed case if [[ $upper = $lower ]] then echo "dual: $name has no letters" elif [[ $name != $upper && $name != $lower ]] then echo "dual: $name has both cases" else # Update DUAL and dual environment variables if [[ -z "$dual" || -z "$DUAL" ]] then dual=(dual) DUAL=DUAL fi if [[ $DUAL != (*:|)$upper(|:*) ]] then dual=($dual "$lower") DUAL="$DUAL:$upper" fi if [[ $name = $upper ]] then # upper-case given - split into tokens at : upperval=$val lowerval=${(s,:,)=upperval} else # lower-case. Join with : lowerval=$val upperval=${(j,:,)=lowerval} fi # assign. $upper=$upperval $lower=$lowerval fi done return 0