Reverse the candidates array (the list of positional arguments after options) with the --prepend (or -p) option so that directories are prepended to the path variable in the correct precedence. Add a "force" option as -f or --force that will skip checking if a directory exists and add the path even if it doesn't. As part of this change, add the check that the directory exists.
146 lines
4.2 KiB
Bash
146 lines
4.2 KiB
Bash
# Eryn Wells <eryn@erynwells.me>
|
|
# vim: set ft=zsh:
|
|
|
|
function _update-path-usage
|
|
{
|
|
local -r function_name=$1
|
|
|
|
local usage_string=$(cat <<EOF
|
|
Usage: $function_name <arguments> [<path>...]
|
|
|
|
Modify the target path-like variable by adding or removing paths provided as
|
|
positional arguments. Before adding, check that the target path variable doesn't
|
|
already contain the path and that the directory exists.
|
|
|
|
This function returns the number of paths that were skipped in the input. If all
|
|
paths were processed, it returns 0. It returns 255 if an error occurred while
|
|
processing arguments.
|
|
|
|
Arguments
|
|
---------
|
|
|
|
%B-e%b | %B--export%b | %B--no-export%b
|
|
Export the variable after modification.
|
|
|
|
%B-f%b | %B--force%b
|
|
Unconditionally add the path, even if it doesn't exist.
|
|
|
|
%B-h%b | %B--help%b
|
|
Print this message.
|
|
|
|
%B-p%b | %B--prepend%b
|
|
Prepend paths to the target path variable, instead of appending. When
|
|
prepending, directories will be added in reverse order so their precedence
|
|
is preserved. That is, the first directory in the list will be at the start
|
|
of the path.
|
|
|
|
%B-P%b | %B--path%b <path_variable_name>
|
|
The name of a path-like variable to modify. The default is 'path'.
|
|
|
|
%B-r%b | %B--remove%b
|
|
Remove paths instead of adding. -p and -f are ignored when removing
|
|
directories from the path.
|
|
|
|
%B-v%b | %B--verbose%b
|
|
Print extra information while processing directories.
|
|
EOF
|
|
)
|
|
|
|
print -P $usage_string
|
|
}
|
|
|
|
function update-path
|
|
{
|
|
zmodload zsh/zutil
|
|
|
|
local -a o_args o_export o_force o_help o_prepend o_remove o_verbose o_pathvar
|
|
zparseopts -a o_args -D -E -F - \
|
|
{e,-export,-no-export}=o_export \
|
|
{f,-force}=o_force \
|
|
{h,-help}=o_help \
|
|
{p,-prepend}=o_prepend \
|
|
{P,-path}:=o_pathvar \
|
|
{r,-remove}=o_remove \
|
|
{v,-verbose}=o_verbose
|
|
|
|
local -ri parse_status=$?
|
|
if (( parse_status )); then
|
|
_update-path-usage $0
|
|
return 255
|
|
fi
|
|
|
|
if [[ $#o_help -ne 0 ]]; then
|
|
_update-path-usage $0
|
|
return 0
|
|
fi
|
|
|
|
local -r verbose=$#o_verbose
|
|
local -r path_variable_name=${o_pathvar[-1]:-path}
|
|
|
|
if ! typeset -p $path_variable_name &> /dev/null; then
|
|
print "Invalid path variable: \$$path_variable_name" 1>&2
|
|
return 255
|
|
fi
|
|
|
|
[[ $verbose -ne 0 ]] && print "Modifying $path_variable_name"
|
|
|
|
local -i candidates_skipped=0
|
|
local did_update_path
|
|
|
|
local -a candidates=($@)
|
|
if [[ $#o_prepend -ne 0 ]]; then
|
|
# If prepending, reverse the list so paths are added in the right order.
|
|
candidates=(${(Oa)@})
|
|
fi
|
|
|
|
for candidate in $candidates; do
|
|
local candidate_index=${${(P)path_variable_name}[(Ie)$candidate]}
|
|
|
|
# An empty $o_remove means we're adding to the array.
|
|
if [[ $#o_remove -eq 0 ]]; then
|
|
if [[ $candidate_index -ne 0 ]]; then
|
|
[[ $verbose -ne 0 ]] && print "Skipping $candidate"
|
|
(( candidates_skipped++ ))
|
|
continue
|
|
fi
|
|
|
|
if [[ $#force -eq 0 && ! -d "$candidate" ]]; then
|
|
[[ $verbose -ne 0 ]] && print "$candidate doesn't exist"
|
|
(( candidates_skipped++ ))
|
|
continue
|
|
fi
|
|
|
|
did_update_path=yes
|
|
|
|
[[ $verbose -ne 0 ]] && print "Adding $candidate"
|
|
if [[ $#o_prepend -ne 0 ]]; then
|
|
eval "${path_variable_name}=(${candidate} ${path})"
|
|
else
|
|
eval "${path_variable_name}+=${candidate}"
|
|
fi
|
|
else
|
|
if [[ $candidate_index -eq 0 ]]; then
|
|
[[ $verbose -ne 0 ]] && print "Skipping $candidate"
|
|
(( candidates_skipped++ ))
|
|
continue
|
|
fi
|
|
|
|
[[ $verbose -ne 0 ]] && print "Removing $candidate"
|
|
|
|
did_update_path=yes
|
|
eval "${path_variable_name}[${candidate_index}]=()"
|
|
fi
|
|
done
|
|
|
|
if [[ -n $did_update_path && $o_export[(I)--no-export] -ne 0 ]]; then
|
|
[[ $verbose -ne 0 ]] && print "Exporting $path_variable_name"
|
|
export $path_variable_name
|
|
if [[ "$path_variable_name" == "path" ]]; then
|
|
rehash
|
|
fi
|
|
fi
|
|
|
|
return $candidates_skipped
|
|
}
|
|
|
|
update-path "$@"
|