Skip to content

Instantly share code, notes, and snippets.

@nolar
Last active February 14, 2024 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save nolar/9702618 to your computer and use it in GitHub Desktop.
Save nolar/9702618 to your computer and use it in GitHub Desktop.
#
# Print all possible candidates for virtualenv relative to the directory $1.
# Used in venv_find() for every directory starting from the current and up to the root.
#
function venv_candidates () {
echo $1
echo $1/.venv
echo $1/VENV
echo $1/ENV
echo $1.venv
}
#
# Finds the closest virtualenv root directory, starting from $1, and going up to the root.
# If the target directory is not specified as an argument, current directory is used.
# Prints the virtualenv path found, or nothing otherwise.
#
function venv_find () {
local venv_root=${1:-"."}
local venv_found=""
# The cycle is just for the case with broken root folder detection - never do more than N iterations.
for (( i=10; i > 0; i-- )); do
local venv_real=$(cd $venv_root && pwd -P)
local venv_name=$(basename $venv_real)
# echo REAL=$venv_real >&2
for candidate in $( venv_candidates $venv_real ) ; do
# echo CANDIDATE=$candidate >&2
if [ -f "$candidate/bin/activate" ]; then
echo $(cd $candidate && pwd -P)
return
fi
done
if [ "$venv_real" = "/" ]; then
break
fi
venv_root=$venv_root/".."
done
}
#
# Find current virtualenv, and prints its path.
# NB: The virtualenv must be activated in the current shell, or it will be ignored as if there is
# NB: no active virtualenv at all. This is needed because current virtualenv is usually determined
# NB: to be deactivated, and if it is not in the current shell, there is no "deactivate" function.
#
function venv_curr () {
if [ -n "$VIRTUAL_ENV" -a "$(type -t deactivate)" = 'function' ]; then
echo $VIRTUAL_ENV
fi
}
#
# Activates a virtualenv which we are in (or in any of its subfolders), according to our cwd.
# Deactivates any virtualenv when we leave it (cd to a directory with no venv at all).
#
function venv_auto () {
venv_new="$(venv_find)"
venv_old="$(venv_curr)"
bash_cmd=`basename $(expr "$BASH_COMMAND" : "\([^ ]*\)")`
# Special case for subshells - they will reactivate their own venv inside. This is needed
# to properly keep "deactivate" function inside subshells, and avoid recursive venvs.
if [ -n "$venv_old" -a \( "$bash_cmd" == "mc" -o "$bash_cmd" == "bash" -o "$bash_cmd" == "sh" \) ]; then
# echo "DEACTIVATE $venv_old FOR $bash_cmd"
deactivate
elif [ -z "$venv_new" -a -n "$venv_old" ]; then
# echo "DEACTIVATE $venv_old"
deactivate
elif [ -n "$venv_new" -a "$venv_new" != "$venv_old" ]; then
# echo "ACTIVATE $venv_new"
source "$venv_new"/bin/activate
prompt_colorize
fi
}
#
# Attach automatic virtualenv detection for any command or action in the shell.
# Works well even if you change dirs in mc.
#
trap venv_auto DEBUG
@dany85free
Copy link

What is command prompt_colorize?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment