blob: e16e6a4a233d9244a247d1130ace2d7e414a3a82 (
plain) (
tree)
|
|
# Function to manage contents of PATH variable within the current shell
path() {
# Figure out command being called
local pathcmd
if (($#)) ; then
pathcmd=$1
shift
else
pathcmd=list
fi
# Switch between commands
case $pathcmd in
# Print help output (also done if command not found)
help|h|-h|--help|-\?)
while IFS= read -r line ; do
printf '%s\n' "$line"
done <<EOF
$FUNCNAME: Manage contents of PATH variable
USAGE:
$FUNCNAME h[elp]
Print this help message (also done if command not found)
$FUNCNAME l[ist]
Print the current directories in PATH, one per line (default command)
$FUNCNAME i[nsert] DIR
Add a directory to the front of PATH, checking for existence and uniqueness
$FUNCNAME a[ppend] DIR
Add a directory to the end of PATH, checking for existence and uniqueness
$FUNCNAME r[emove] DIR
Remove all instances of a directory from PATH
INTERNALS:
$FUNCNAME s[et] [DIR1 [DIR2...]]
Set the PATH to the given directories without checking existence or uniqueness
$FUNCNAME c[heck] DIR
Return whether DIR is a component of PATH
EOF
;;
# Print the current contents of the path
list|l)
local -a patharr
IFS=: read -a patharr < <(printf '%s\n' "$PATH")
if ((${#patharr[@]})) ; then
printf '%s\n' "${patharr[@]}"
fi
;;
# Add a directory to the front of PATH, checking for existence and uniqueness
insert|i)
local -a patharr
IFS=: read -a patharr < <(printf '%s\n' "$PATH")
local dirname
dirname=$1
[[ $dirname == / ]] || dirname=${dirname%/}
if [[ -z $dirname ]] ; then
printf 'bash: %s: need a directory path to insert\n' \
"$FUNCNAME" >&2
return 1
fi
if [[ ! -d $dirname ]] ; then
printf 'bash: %s: %s not a directory\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
if [[ $dirname == *:* ]] ; then
printf 'bash: %s: Cannot add insert directory %s with colon in name\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
if path check "$dirname" ; then
printf 'bash: %s: %s already in PATH\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
patharr=("$dirname" "${patharr[@]}")
path set "${patharr[@]}"
;;
# Add a directory to the end of PATH, checking for existence and uniqueness
append|add|a)
local -a patharr
IFS=: read -a patharr < <(printf '%s\n' "$PATH")
local dirname
dirname=$1
[[ $dirname == / ]] || dirname=${dirname%/}
if [[ -z $dirname ]] ; then
printf 'bash: %s: need a directory path to append\n' \
"$FUNCNAME" >&2
return 1
fi
if [[ ! -d $dirname ]] ; then
printf 'bash: %s: %s not a directory\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
if [[ $dirname == *:* ]] ; then
printf 'bash: %s: Cannot append directory %s with colon in name\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
if path check "$dirname" ; then
printf 'bash: %s: %s already in PATH\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
patharr[${#patharr[@]}]=$dirname
path set "${patharr[@]}"
;;
# Remove all instances of a directory from PATH
remove|rm|r)
local -a patharr
IFS=: read -a patharr < <(printf '%s\n' "$PATH")
local dirname
dirname=$1
[[ $dirname == / ]] || dirname=${dirname%/}
if [[ -z $dirname ]] ; then
printf 'bash: %s: need a directory path to remove\n' \
"$FUNCNAME" >&2
return 1
fi
if ! path check "$dirname" ; then
printf 'bash: %s: %s not in PATH\n' \
"$FUNCNAME" "$dirname" >&2
return 1
fi
local -a newpatharr
local part
for part in "${patharr[@]}" ; do
[[ $dirname == "$part" ]] && continue
newpatharr[${#newpatharr[@]}]=$part
done
path set "${newpatharr[@]}"
;;
# Set the PATH to the given directories without checking existence or uniqueness
set|s)
local -a newpatharr
local dirname
for dirname ; do
newpatharr[${#newpatharr[@]}]=$dirname
done
PATH=$(IFS=: ; printf '%s' "${newpatharr[*]}")
;;
# Return whether directory is a component of PATH
check|c)
local -a patharr
IFS=: read -a patharr < <(printf '%s\n' "$PATH")
local dirname
dirname=$1
[[ $dirname == / ]] || dirname=${dirname%/}
if [[ -z $dirname ]] ; then
printf 'bash: %s: need a directory path to check\n' \
"$FUNCNAME" >&2
return 1
fi
local part
for part in "${patharr[@]}" ; do
if [[ $dirname == "$part" ]] ; then
return 0
fi
done
return 1
;;
# Unknown command
*)
printf 'bash: %s: Unknown command %s\n' \
"$FUNCNAME" "$pathcmd" >&2
path help >&2
return 1
;;
esac
}
# Completion for path
_path() {
# What to do depends on which word we're completing
if ((COMP_CWORD == 1)) ; then
# Complete operation as first word
local cmd
for cmd in help list insert append remove set check ; do
[[ $cmd == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
COMPREPLY[${#COMPREPLY[@]}]=$cmd
done
# Complete with either directories or $PATH entries as all other words
else
case ${COMP_WORDS[1]} in
# Complete with a directory
insert|i|append|add|a|check|c|set|s)
local dirname
while IFS= read -rd '' dirname ; do
COMPREPLY[${#COMPREPLY[@]}]=$dirname
done < <(
# Set options to glob correctly
shopt -s dotglob nullglob
# Collect directory names, strip trailing slash
local -a dirnames
dirnames=("${COMP_WORDS[COMP_CWORD]}"*/)
dirnames=("${dirnames[@]%/}")
# Bail if no results to prevent empty output
((${#dirnames[@]})) || exit 1
# Print results, quoted and null-delimited
printf '%q\0' "${dirnames[@]}"
)
;;
# Complete with directories from PATH
remove|rm|r)
local -a promptarr
IFS=: read -d '' -a promptarr < <(printf '%s\0' "$PATH")
local part
for part in "${promptarr[@]}" ; do
[[ $part == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
COMPREPLY[${#COMPREPLY[@]}]=$(printf '%q\0' "$part")
done
;;
# No completion
*)
return 1
;;
esac
fi
}
complete -F _path path
|