diff options
-rwxr-xr-x | rpath.sh | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/rpath.sh b/rpath.sh new file mode 100755 index 0000000..ea84d21 --- /dev/null +++ b/rpath.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash +# +# Copyright 2014 David Vazgenovich Shakaryan +# Distributed under the terms of the MIT License. +# +# rpath +# https://github.com/omp/rpath +# Manage multiple Ruby installations with no black magic. +# +# In order to prevent environment pollution, the output of this script +# is a list of commands which must be sourced. This can be achieved +# through a simple shell function: +# +# rpath() { source <(/path/to/rpath.sh "${@}"); } +# +# Two methods of version matching are supported. If the specified +# argument consists of only numbers, it is matched against the list +# number shown in `rpath ls`. Otherwise, a substring match is performed +# against the directory name. + +: ${RUBIES_PATH:="${HOME}/.rubies"} + +_echo() { + echo "echo '${@//\'/\'\\\'\'}'" +} + +_export_path() { + echo "export PATH='${PATH//\'/\'\\\'\'}'" + echo "hash -r" +} + +_die() { + [[ -n "${@}" ]] && echo "echo '${@//\'/\'\\\'\'}' 1>&2" + + echo "false" + exit 1 +} + +_populate_dirs() { + [[ -d "${RUBIES_PATH}" ]] \ + || _die "Directory ${RUBIES_PATH} does not exist." + + # Cannot handle paths containing a newline. Only an idiot would + # encounter this in practice. + readarray -t dirs < \ + <(printf '%s\0' "${RUBIES_PATH}"/* | sort -zV | xargs -0n1) +} + +_match() { + if [[ "${1}" =~ ^[0-9]+$ ]]; then + [[ "${2}" == "${1}" ]] && return + else + [[ "${3}" == *"${1}"* ]] && return + fi + + return 1 +} + +_get() { + local dir dirs succeed=false + + IFS=':' read -a dirs <<< "${PATH}" + + for dir in "${dirs[@]}"; do + if [[ "${dir}" == "${RUBIES_PATH}/"* ]]; then + dir="${dir%/bin}" + echo "${dir##*/}" + + succeed=true + fi + done + + $succeed || return 1 +} + +_set() { + _clear + _echo "Adding ${1}/bin to PATH." + + PATH="${1}/bin:${PATH}" +} + +_clear() { + local dir dirs cdirs=() succeed=false + + IFS=':' read -a dirs <<< "${PATH}" + + for dir in "${dirs[@]}"; do + if [[ "${dir}" == "${RUBIES_PATH}/"* ]]; then + _echo "Removing ${dir} from PATH." + + succeed=true + else + cdirs+=("${dir}") + fi + done + + $succeed || return 1 + + PATH="$(IFS=':'; echo "${cdirs[*]}")" +} + +rpath_ls() { + _populate_dirs + + counter=0 + current=$(_get | head -n 1) + + for dir in "${dirs[@]}"; do + str="[$((++counter))] ${dir##*/}" + + [[ "${dir##*/}" == "${current}" ]] && str+=" *" + + _echo "${str}" + done +} + +rpath_get() { + current="$(_get)" && _echo "${current}" +} + +rpath_set() { + [[ -z "${1}" ]] && _die 'rpath set requires an argument.' + + _populate_dirs + + counter=0 + + for dir in "${dirs[@]}"; do + if _match "${1}" "$((++counter))" "${dir##*/}"; then + _set "${dir}" + _export_path + + return + fi + done + + _die 'No matching ruby found.' +} + +rpath_clear() { + _clear || _die 'No rubies found in PATH.' + _export_path +} + +rpath_help() { + _echo 'Usage: rpath <command> [args]' + _echo + _echo 'Available options:' + _echo ' ls List all available rubies.' + _echo ' get Display currently selected ruby.' + _echo ' set Select specified ruby.' + _echo ' clear Clear path of any rpath rubies.' + _echo ' help Display this help information.' +} + +case "${1}" in + 'ls') + rpath_ls ;; + 'get') + rpath_get ;; + 'set') + rpath_set "${2}" ;; + 'clear') + rpath_clear ;; + *) + rpath_help ;; +esac |