diff --git a/init.fish b/init.fish index 3938f7f..4c968bc 100644 --- a/init.fish +++ b/init.fish @@ -9,6 +9,14 @@ if status is-interactive and set -g autovenv_enable "yes" end +# Gets particular elements from an array +# eg. $some_array | select 1 3 +# Returns the first and 3rd elements +function select + read --local --array --null arr + echo $arr[$argv] +end + ## AutoVenv Function # Activates on directory changes. function autovenv --on-variable PWD -d "Automatic activation of Python virtual environments" @@ -16,23 +24,36 @@ function autovenv --on-variable PWD -d "Automatic activation of Python virtual e test ! "$autovenv_enable" = "yes" or not status is-interactive and return - # We start by splitting our CWD path into individual elements and iterating over each element. - # If our CWD is `/opt/my/hovercraft/eels` we split it into a variable containing 4 entries: - # `opt`, `my`, `hovercraft` and `eels`. We then build back up the path by iterating over the list - # and adding each element to the previous one. (We start with `/opt`, then `/opt/my` and so on.) - # During each run through the loop we test for a sub-directory/file called `bin/activate.fish`. If a - # venv is found we go ahead and break out of the loop, otherwise continue. We go through all of this - # instead of just checking the CWD to handle cases where the user moves into a sub-directory of the venv. - for _dir in (string split -n '/' "$PWD") - set -l _tree "$_tree/$_dir" - if test -e "$_tree/bin/activate.fish" - set _source "$_tree/bin/activate.fish" - if test "$autovenv_announce" = "yes" - set -g __autovenv_old $__autovenv_new - set -g __autovenv_new (basename $_tree) + # Start at PWD (prsent working directory, see if there is a subfolder that contains bin/activate.fish + # ie. start at $PWD//bin/activate.fish + # If that doesn't exist, try $PWD/..//bin/activate.fish + # Keep going until we cannot go any further + set -l _tree "$PWD/." + set -l _done false + while true + set _tree (string split -r -m 1 -n '/' "$_tree" | select 1) + if ! string match -q -- "/*" $_tree + # This is a hack to stop when we have ascended all the way up to the top of the tree. + # The string split command above eventually returns something like "home" when it tries + # to split "/home". So the lack of a slash is what we do to tell us that "it's time to stop" + break + end + for _venv_dir in (find "$_tree" -maxdepth 1 -type d) + if test -e "$_venv_dir/bin/activate.fish" + set _source "$_venv_dir/bin/activate.fish" + if test "$autovenv_announce" = "yes" + set -g __autovenv_old $__autovenv_new + set -g __autovenv_new (basename $_tree) + set venv_dir $_venv_dir + end + set _done true + break end + end + if $_done break end + end # If we're *not* in an active venv and the venv source dir exists we activate it and return. if test -z "$VIRTUAL_ENV" -a -e "$_source" @@ -43,7 +64,7 @@ function autovenv --on-variable PWD -d "Automatic activation of Python virtual e # Next we check to see if we're already in an active venv. If so we proceed with further tests. else if test -n "$VIRTUAL_ENV" # Check to see if our CWD is inside the venv directory. - set _dir (string match -n "$VIRTUAL_ENV*" "$PWD") + set _dir (string match -n "$VIRTUAL_ENV*" "$venv_dir") # If we're no longer inside the venv dirctory deactivate it and return. if test -z "$_dir" -a ! -e "$_source" deactivate @@ -62,4 +83,4 @@ function autovenv --on-variable PWD -d "Automatic activation of Python virtual e end end end -################################################################################ \ No newline at end of file +################################################################################