dual
- #!/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