From 78ca825a27ea02ed17be226f253cecb0e3a71daa Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 20 Aug 2016 17:27:04 +1200 Subject: Port path() to POSIX sh That was a lot easier than I thought --- README.markdown | 2 +- bash/bashrc.d/path.bash | 180 ------------------------------------------------ sh/shrc.d/path.sh | 93 +++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 181 deletions(-) delete mode 100644 bash/bashrc.d/path.bash create mode 100644 sh/shrc.d/path.sh diff --git a/README.markdown b/README.markdown index 40556ef1..4108914d 100644 --- a/README.markdown +++ b/README.markdown @@ -188,6 +188,7 @@ in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include: * `mkcd()` creates a directory and changes into it. * `mysql()` allows shortcuts to MySQL configuration files stored in `~/.mysql`. +* `path()` manages the contents of `PATH` conveniently. * `pd()` changes to the argument's parent directory. * `pwgen()` generates just one decent password with `pwgen(1)`. * `rcsdiff()` forces a unified format for `rcsdiff(1)`. @@ -208,7 +209,6 @@ There are a few other little tricks defined for other shells, mostly in `bash/bashrc.d`: * `keep()` stores ad-hoc shell functions and variables. -* `path()` manages the contents of `PATH` conveniently. * `prompt()` sets up my interactive prompt. * `pushd()` adds a default destination of `$HOME` to the `pushd` builtin. * `vared()` allows interactively editing a variable with Readline, emulating diff --git a/bash/bashrc.d/path.bash b/bash/bashrc.d/path.bash deleted file mode 100644 index 61bf73c0..00000000 --- a/bash/bashrc.d/path.bash +++ /dev/null @@ -1,180 +0,0 @@ -# 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 <&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 -} diff --git a/sh/shrc.d/path.sh b/sh/shrc.d/path.sh new file mode 100644 index 00000000..22374310 --- /dev/null +++ b/sh/shrc.d/path.sh @@ -0,0 +1,93 @@ +# Function to manage contents of PATH variable within the current shell +path() { + + # The second argument, the directory, can never have a colon + case $2 in + *:*) + printf >&2 'path(): Illegal colon in given directory\n' + return 2 + ;; + esac + + # Check first argument to figure out operation + case $1 in + + # List current directories in $PATH + list|'') ( + path=$PATH: + while [ -n "$path" ] ; do + dir=${path%%:*} + path=${path#*:} + [ -n "$dir" ] || continue + printf '%s\n' "$dir" + done + ) ;; + + # Add a directory at the start of $PATH + insert) + if path check "$2" ; then + printf >&2 'path(): %s already in $PATH\n' + return 1 + fi + PATH=${2}${PATH:+:"$PATH"} + ;; + + # Add a directory to the end of $PATH + append) + if path check "$2" ; then + printf >&2 'path(): %s already in $PATH\n' + return 1 + fi + PATH=${PATH:+"$PATH":}${2} + ;; + + # Remove a directory from $PATH + remove) + if ! path check "$2" ; then + printf >&2 'path(): %s not in $PATH\n' + return 1 + fi + PATH=$( + path=:$path: + path=${path%%:"$2":*}:${path#*:"$2":} + path=${path#:} + path=${path%:} + printf '%s\n' "$path" + ) + ;; + + # Check whether a directory is in $PATH + check) ( + path=:$PATH: + [ "$path" != "${path%:"$2":*}" ] + ) ;; + + # Print help output (also done if command not found) + help) + cat <<'EOF' +path(): Manage contents of PATH variable + +USAGE: + path [list] + Print the current directories in PATH, one per line (default command) + path insert DIR + Add a directory to the front of PATH + path append DIR + Add a directory to the end of PATH + path remove DIR + Remove directory from PATH + path check DIR + Return whether DIR is a component of PATH + path help + Print this help message (also done if command not found) +EOF + ;; + + # Command not found + *) + printf >&2 'path(): Unknown command\n' + path help + return 2 + ;; + esac +} -- cgit v1.2.3