From 01f8d7ccb490d56dfeb7a5d433a4affa6ddf318a Mon Sep 17 00:00:00 2001 From: iain barnett Date: Sat, 13 Apr 2019 13:06:08 +0900 Subject: [PATCH 1/4] Why be coy? Share the PYTHONS var to make it malleable, chruby does. --- share/chpython/chpython.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/share/chpython/chpython.sh b/share/chpython/chpython.sh index a99ed0e..a9c7739 100644 --- a/share/chpython/chpython.sh +++ b/share/chpython/chpython.sh @@ -1,5 +1,6 @@ CHPYTHON_VERSION='0.1.0.dev' PYTHONS=() +export PYTHONS [ -d "${HOME}/.pythons" ] && PYTHONS+=("${HOME}/.pythons"/*) From 4f30346e5862f850387a86fca288f88a4519de10 Mon Sep 17 00:00:00 2001 From: iain barnett Date: Sat, 13 Apr 2019 13:06:17 +0900 Subject: [PATCH 2/4] Less convoluted. --- share/chpython/chpython.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/chpython/chpython.sh b/share/chpython/chpython.sh index a9c7739..c525141 100644 --- a/share/chpython/chpython.sh +++ b/share/chpython/chpython.sh @@ -44,7 +44,7 @@ function _chpython_select { } function _chpython_use { - if [[ ! -x "$1/bin/python" && ! -x "$1/bin/python3" ]]; then + if ! [[ -x "$1/bin/python" || -x "$1/bin/python3" ]]; then echo "chpython: neither $1/bin/python nor $1/bin/python3 are executable" >&2 return 1 fi From 4af19bffa1d22e23952a2635db8b996b2bcbdadf Mon Sep 17 00:00:00 2001 From: iain barnett Date: Mon, 15 Apr 2019 15:36:52 +0900 Subject: [PATCH 3/4] - Added auto so .python-version files can be used. - Tried to make the functions match the formatting of chruby's as much as possible to make it easy to use idea's from it. - Read the /opt/pythons and ~/.pythons into PYTHONS automatically. - Removed `exec` option, again to match chruby and because I wasn't using it. - I'm going to be opinionated assume that `python` exists in python3 installs because someone has done the `ln -s python3.x python` like a sensible person. - Expose a PYTHON_VERSION env var that includes a fuller version of the python version (taken from `python --version`). --- share/chpython/auto.sh | 33 ++++++++++++ share/chpython/chpython.sh | 104 ++++++++++++++----------------------- 2 files changed, 72 insertions(+), 65 deletions(-) create mode 100644 share/chpython/auto.sh mode change 100644 => 100755 share/chpython/chpython.sh diff --git a/share/chpython/auto.sh b/share/chpython/auto.sh new file mode 100644 index 0000000..4c88725 --- /dev/null +++ b/share/chpython/auto.sh @@ -0,0 +1,33 @@ +unset PYTHON_AUTO_VERSION + +function chpython_auto() { + local dir="$PWD/" version + + until [[ -z "$dir" ]]; do + dir="${dir%/*}" + + if { read -r version <"$dir/.python-version"; } 2>/dev/null || [[ -n "$version" ]]; then + version="${version%%[[:space:]]}" + + if [[ "$version" == "$PYTHON_AUTO_VERSION" ]]; then return + else + PYTHON_AUTO_VERSION="$version" + chpython "$version" + return $? + fi + fi + done + + if [[ -n "$PYTHON_AUTO_VERSION" ]]; then + chpython_reset + unset PYTHON_AUTO_VERSION + fi +} + +if [[ -n "$ZSH_VERSION" ]]; then + if [[ ! "$preexec_functions" == *chpython_auto* ]]; then + preexec_functions+=("chpython_auto") + fi +elif [[ -n "$BASH_VERSION" ]]; then + trap '[[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]] && chpython_auto' DEBUG +fi diff --git a/share/chpython/chpython.sh b/share/chpython/chpython.sh old mode 100644 new mode 100755 index c525141..801e1c2 --- a/share/chpython/chpython.sh +++ b/share/chpython/chpython.sh @@ -1,95 +1,57 @@ CHPYTHON_VERSION='0.1.0.dev' PYTHONS=() -export PYTHONS -[ -d "${HOME}/.pythons" ] && PYTHONS+=("${HOME}/.pythons"/*) +for dir in "$PREFIX/opt/pythons" "$HOME/.pythons"; do + [[ -d "$dir" && -n "$(ls -A "$dir")" ]] && PYTHONS+=("$dir"/*) +done +unset dir -function _chpython_exec { - local python - python=$1 - shift - # TODO: Clear path so invoking `chpython 3.5 python -V` when - # $CHPYTHON_VERSION is set to a 2.x Python gives a command not - # found error instead of running $CHPYTHON_VERSION/bin/python. - env PATH="$python/bin:$PATH" $* -} - -function _chpython_reset { +function chpython_reset() { [ -z "$CHPYTHON_ROOT" ] && return - PATH=":$PATH:" - PATH=${PATH//:$CHPYTHON_ROOT\/bin:/:} - PATH=${PATH#:}; PATH=${PATH%:} + + PATH=":$PATH:"; PATH=${PATH//:$CHPYTHON_ROOT\/bin:/:} + PATH="${PATH#:}"; PATH="${PATH%:}" unset CHPYTHON_ROOT hash -r - type python || type python3 } -function _chpython_select { - local dir python match - for dir in ${PYTHONS[@]}; do - dir=${dir%%/} - python=${dir##*/} - case "$python" in - "$1") - # Match using 3-part version number, e.g. `chruby 2.7.10` - match=$dir && break - ;; - "$1"*) - # Match best using 2-part version number, e.g., `chpython 2.7` - match=$dir - ;; - esac - done - echo "$match" -} -function _chpython_use { - if ! [[ -x "$1/bin/python" || -x "$1/bin/python3" ]]; then - echo "chpython: neither $1/bin/python nor $1/bin/python3 are executable" >&2 +function _chpython_use() { + if [[ ! -x "$1/bin/python" ]]; then + echo "chpython: $1/bin/python is not executable" >&2 return 1 fi - # TODO: Alias *3 stuff to base name, so, e.g., `python` can be called - # instead of `python3` + [[ -n "$CHPYTHON_ROOT" ]] && chpython_reset - export CHPYTHON_ROOT=$1 + export CHPYTHON_ROOT="$1" export PATH="${CHPYTHON_ROOT}/bin:${PATH}" + local python_version + if [[ -e "$1/bin/python3" ]]; then + PYTHON_VERSION="$($1/bin/python --version)" + else + PYTHON_VERSION="$($1/bin/python --version 2>&1 | awk '{print $2}')" + fi hash -r - type python || type python3 } -function chpython { + +function chpython() { case "$1" in -h|--help) cat <&2 - return 1 - fi - - shift - _chpython_exec $match $* - ;; - system) - _chpython_reset - ;; + system) chpython_reset ;; '') local dir python - for dir in ${PYTHONS[@]}; do - dir="${dir%%/}" - python=${dir##*/} + for dir in "${PYTHONS[@]}"; do + dir="${dir%%/}"; python="${dir##*/}" if [[ "$dir" == "$CHPYTHON_ROOT" ]]; then echo " * ${python}" else @@ -98,15 +60,27 @@ EOS done ;; *) - local match - match=$(_chpython_select $1) + local dir python match + for dir in "${PYTHONS[@]}"; do + dir="${dir%%/}"; python="${dir##*/}" + case "$python" in + "$1") + # Match using 3-part version number, e.g. `chruby 2.7.10` + match="$dir" && break + ;; + "$1"*) + # Match best using 2-part version number, e.g., `chpython 2.7` + match="$dir" + ;; + esac + done if [ -z "$match" ]; then echo "chpython: unknown Python: $1" >&2 return 1 fi shift - _chpython_use $match $* + _chpython_use "$match" ;; esac } From a92f695cfd1784420e5bc43e587e7bae2d3626a6 Mon Sep 17 00:00:00 2001 From: iain barnett Date: Sun, 17 Nov 2019 15:41:55 +0900 Subject: [PATCH 4/4] The space was confusing my editor's syntax colouring. That's all. --- share/chpython/auto.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/chpython/auto.sh b/share/chpython/auto.sh index 4c88725..5089f7b 100644 --- a/share/chpython/auto.sh +++ b/share/chpython/auto.sh @@ -6,7 +6,7 @@ function chpython_auto() { until [[ -z "$dir" ]]; do dir="${dir%/*}" - if { read -r version <"$dir/.python-version"; } 2>/dev/null || [[ -n "$version" ]]; then + if { read -r version < "$dir/.python-version"; } 2>/dev/null || [[ -n "$version" ]]; then version="${version%%[[:space:]]}" if [[ "$version" == "$PYTHON_AUTO_VERSION" ]]; then return