Pathmunge function in zsh
1. Use parameter expansion for great effect
You can replace most of the case construct with a two ${name:#pattern} expansions. If pattern matches the value of name, the empty string is substituted, otherwise the value of name. If name is an array, matching elements will be removed from the array. So instead of this:
local before

before=1
# [...]
case $1 in
    after)
        # Append to PATH
        before=
        ;&amp;
    before)
        shift
        ;;
esac
#[...]
if [[ -n $before ]]
then
#[...]
fi

it would look like this:
local before=${1:#after}
argv=(${argv:#[^/]*})
if [[ -n $before ]]
then
#[...]
fi

With before=${1:#after} before will be empty if the first parameter is &quot;after&quot;, non-zero otherwise. argv=(${argv:#[^/]*}) will remove any element from argv that does not start with an /, including &quot;before&quot; and &quot;after&quot;
One difference would be, that before contains the value of the first parameter instead of 1 unless said parameter was &quot;after&quot;. But this does not matter as long as you check only if before is non-zero.
The second difference would be, that in addition to removing &quot;before&quot; and &quot;after&quot; from argv, any relative paths (or anything that does not start with an /) will be removed, too.
2. Make use of path instead of PATH
There is no need to split PATH into an array on your own because zsh already makes the value of PATH available as an array with the array parameter path. Any change to PATH is automatically mirrored in path and vice versa. So you can manipulate path directly without the need for the local path_array parameter.
Instead of
path_array=(${(As.:.)PATH})
path_array=(${path_array:|argv})
if [[ -n $before ]]
then
    path_array=(${(Oa)argv} $path_array)
else
    path_array=($path_array $argv)
fi
PATH=&quot;${(j.:.)path_array}&quot;

You need only
path=(${path:|argv})
if [[ -n $before ]]
then
    path=(${(Oa)argv} $path)
else
    path=($path $argv)
fi