-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathzsh-uv-env.plugin.zsh
More file actions
117 lines (101 loc) · 3.18 KB
/
zsh-uv-env.plugin.zsh
File metadata and controls
117 lines (101 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# Function to check if a virtualenv is already activated
is_venv_active() {
[[ -n "$VIRTUAL_ENV" ]] && return 0
return 1
}
# Function to find nearest .venv directory
find_venv() {
local current_dir="$PWD"
local home_dir="$HOME"
local root_dir="/"
local stop_dir="$root_dir"
# If we're under home directory, stop at home
if [[ "$current_dir" == "$home_dir"* ]]; then
stop_dir="$home_dir"
fi
while [[ "$current_dir" != "$stop_dir" ]]; do
for _v in .venv venv; do
if [[ -d "$current_dir/$_v" && -r "$current_dir/$_v/bin/activate" ]]; then
echo "$current_dir/$_v"
return 0
fi
done
current_dir="$(dirname "$current_dir")"
done
# Check stop_dir itself
for _v in .venv venv; do
if [[ -d "$stop_dir/$_v" && -r "$stop_dir/$_v/bin/activate" ]]; then
echo "$stop_dir/$_v"
return 0
fi
done
return 1
}
# Variable to track if we activated the venv
typeset -g AUTOENV_ACTIVATED=0
# Define arrays for hooks early so they're available throughout the session
typeset -ga ZSH_UV_ACTIVATE_HOOKS=()
typeset -ga ZSH_UV_DEACTIVATE_HOOKS=()
# Add the hook registration functions
zsh_uv_add_post_hook_on_activate() {
ZSH_UV_ACTIVATE_HOOKS+=("$1")
}
zsh_uv_add_post_hook_on_deactivate() {
ZSH_UV_DEACTIVATE_HOOKS+=("$1")
}
# Function to execute all activation hooks
_run_activate_hooks() {
local hook
for hook in "${ZSH_UV_ACTIVATE_HOOKS[@]}"; do
eval "$hook"
done
}
# Function to execute all deactivation hooks
_run_deactivate_hooks() {
local hook
for hook in "${ZSH_UV_DEACTIVATE_HOOKS[@]}"; do
eval "$hook"
done
}
# Function to handle directory changes
autoenv_chpwd() {
# Don't do anything if a virtualenv is already manually activated
if is_venv_active && [[ $AUTOENV_ACTIVATED == 0 ]]; then
return
fi
local venv_path=$(find_venv)
if [[ -n "$venv_path" ]]; then
# If we found a venv, check if it's different from the currently active one
if is_venv_active; then
# If the found venv is different from the active one, switch to it
if [[ "$venv_path" != "$VIRTUAL_ENV" ]]; then
deactivate
source "$venv_path/bin/activate"
AUTOENV_ACTIVATED=1
# Run activation hooks
_run_activate_hooks
fi
else
# No venv is active, activate the found one
source "$venv_path/bin/activate"
AUTOENV_ACTIVATED=1
# Run activation hooks
_run_activate_hooks
fi
else
# If no venv found and we activated one before, deactivate it
if [[ $AUTOENV_ACTIVATED == 1 ]] && is_venv_active; then
deactivate
AUTOENV_ACTIVATED=0
# Run deactivation hooks
_run_deactivate_hooks
fi
fi
}
# Register precmd hook to watch for new venv creation
# A cheaper alternative would be the chpwd hook, but
# we would miss the case where a venv is created or deleted
autoload -U add-zsh-hook
add-zsh-hook precmd autoenv_chpwd
# Run once when shell starts
autoenv_chpwd