Skip to content

Instantly share code, notes, and snippets.

Last active Jul 30, 2020
What would you like to do?
# 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)
if [ "$venv_real" = "/" ]; then
# 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
# 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 () {
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"
elif [ -z "$venv_new" -a -n "$venv_old" ]; then
# echo "DEACTIVATE $venv_old"
elif [ -n "$venv_new" -a "$venv_new" != "$venv_old" ]; then
# echo "ACTIVATE $venv_new"
source "$venv_new"/bin/activate
# 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment