|
#!/bin/bash |
|
|
|
# Cursor PyEnv Installer |
|
# This script installs cursor-pyenv, a tool to properly handle pyenv in Cursor's terminal |
|
# Author: Claude (created on March 26, 2025) |
|
|
|
set -e |
|
|
|
# Colors for terminal output |
|
RED='\033[0;31m' |
|
GREEN='\033[0;32m' |
|
YELLOW='\033[1;33m' |
|
BLUE='\033[0;34m' |
|
NC='\033[0m' # No Color |
|
|
|
# Print script banner |
|
echo -e "${BLUE}" |
|
echo "╔═══════════════════════════════════════════╗" |
|
echo "║ CURSOR-PYENV INSTALLER ║" |
|
echo "║ Fix pyenv in Cursor's Terminal Environment ║" |
|
echo "╚═══════════════════════════════════════════╝" |
|
echo -e "${NC}" |
|
|
|
# Check if pyenv is installed |
|
if ! command -v pyenv &> /dev/null; then |
|
echo -e "${RED}Error: pyenv is not installed.${NC}" |
|
echo "Please install pyenv first: https://github.com/pyenv/pyenv#installation" |
|
exit 1 |
|
fi |
|
|
|
# Check if pyenv-virtualenv is installed |
|
if ! pyenv commands | grep -q "virtualenv"; then |
|
echo -e "${YELLOW}Warning: pyenv-virtualenv might not be installed.${NC}" |
|
echo "It's recommended to install pyenv-virtualenv: https://github.com/pyenv/pyenv-virtualenv#installation" |
|
read -p "Continue anyway? (y/n) " -n 1 -r |
|
echo |
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then |
|
exit 1 |
|
fi |
|
fi |
|
|
|
# Create installation directory |
|
INSTALL_DIR="$HOME/.cursor-pyenv" |
|
echo -e "${BLUE}Creating installation directory...${NC}" |
|
mkdir -p "$INSTALL_DIR" |
|
mkdir -p "$INSTALL_DIR/bin" |
|
|
|
# Detect user's shell |
|
detect_shell() { |
|
local shell_path=$(basename "$SHELL") |
|
if [ -z "$shell_path" ]; then |
|
# Fallback detection method |
|
if [ -n "$ZSH_VERSION" ]; then |
|
echo "zsh" |
|
elif [ -n "$BASH_VERSION" ]; then |
|
echo "bash" |
|
else |
|
echo "unknown" |
|
fi |
|
else |
|
echo "$shell_path" |
|
fi |
|
} |
|
|
|
USER_SHELL=$(detect_shell) |
|
echo -e "${BLUE}Detected shell: ${GREEN}$USER_SHELL${NC}" |
|
|
|
# Determine RC file based on shell |
|
case "$USER_SHELL" in |
|
"bash") |
|
RC_FILE="$HOME/.bashrc" |
|
PROFILE_FILE="$HOME/.bash_profile" |
|
;; |
|
"zsh") |
|
RC_FILE="$HOME/.zshrc" |
|
PROFILE_FILE="$HOME/.zprofile" |
|
;; |
|
*) |
|
echo -e "${YELLOW}Unknown shell detected. Defaulting to bash configuration.${NC}" |
|
RC_FILE="$HOME/.bashrc" |
|
PROFILE_FILE="$HOME/.bash_profile" |
|
;; |
|
esac |
|
|
|
# Ensure RC file exists |
|
if [ ! -f "$RC_FILE" ]; then |
|
echo -e "${BLUE}Creating $RC_FILE...${NC}" |
|
touch "$RC_FILE" |
|
fi |
|
|
|
# Install the main cursor-pyenv script |
|
echo -e "${BLUE}Installing cursor-pyenv...${NC}" |
|
cat > "$INSTALL_DIR/bin/cursor-pyenv" << 'EOF' |
|
#!/bin/bash |
|
|
|
# Script to properly handle pyenv environment activation and deactivation in Cursor |
|
# Created by Claude on March 26, 2025 |
|
|
|
# Initialize pyenv environment |
|
export PYENV_ROOT="$HOME/.pyenv" |
|
export PATH="$PYENV_ROOT/bin:$PATH" |
|
eval "$(pyenv init -)" |
|
eval "$(pyenv virtualenv-init -)" |
|
|
|
# Default to non-verbose mode |
|
VERBOSE=0 |
|
|
|
# Function to print info in verbose mode only |
|
verbose_print() { |
|
if [ $VERBOSE -eq 1 ]; then |
|
echo "$@" |
|
fi |
|
} |
|
|
|
# Function to show usage |
|
show_usage() { |
|
echo "Usage: cursor-pyenv [options] [activate|deactivate] [environment_name]" |
|
echo "" |
|
echo "Options:" |
|
echo " -v, --verbose Print detailed information" |
|
echo "" |
|
echo "Commands:" |
|
echo " activate ENV Activate environment ENV" |
|
echo " deactivate Deactivate current environment" |
|
echo " list List available environments" |
|
echo "" |
|
echo "Examples:" |
|
echo " cursor-pyenv activate my_env # Activate my_env quietly" |
|
echo " cursor-pyenv -v activate my_env # Activate my_env with details" |
|
echo " cursor-pyenv --verbose deactivate # Deactivate with details" |
|
echo "" |
|
} |
|
|
|
# Parse command line arguments |
|
# First, check for options |
|
while [[ "$1" =~ ^- ]]; do |
|
case "$1" in |
|
-v|--verbose) |
|
VERBOSE=1 |
|
shift |
|
;; |
|
-h|--help) |
|
show_usage |
|
exit 0 |
|
;; |
|
*) |
|
echo "Error: Unknown option $1" |
|
show_usage |
|
exit 1 |
|
;; |
|
esac |
|
done |
|
|
|
# Check if an action was provided |
|
if [ $# -lt 1 ]; then |
|
show_usage |
|
exit 1 |
|
fi |
|
|
|
action="$1" |
|
|
|
# Function to add environment name to PS1 prompt |
|
add_to_prompt() { |
|
env_name="$1" |
|
# Backup original PS1 if not already done |
|
if [ -z "$CURSOR_PYENV_ORIGINAL_PS1" ]; then |
|
export CURSOR_PYENV_ORIGINAL_PS1="$PS1" |
|
fi |
|
# Add environment name to prompt |
|
export PS1="($env_name) $CURSOR_PYENV_ORIGINAL_PS1" |
|
} |
|
|
|
# Function to restore original prompt |
|
restore_prompt() { |
|
# If we have a backup, restore it |
|
if [ -n "$CURSOR_PYENV_ORIGINAL_PS1" ]; then |
|
export PS1="$CURSOR_PYENV_ORIGINAL_PS1" |
|
unset CURSOR_PYENV_ORIGINAL_PS1 |
|
fi |
|
} |
|
|
|
case "$action" in |
|
activate) |
|
# Check if environment name was provided |
|
if [ $# -lt 2 ]; then |
|
echo "Error: No environment name provided." |
|
show_usage |
|
exit 1 |
|
fi |
|
|
|
env_name="$2" |
|
|
|
# Check if already activated |
|
if [ "$VIRTUAL_ENV" == "$PYENV_ROOT/versions/$env_name" ]; then |
|
echo "Environment '$env_name' is already activated." |
|
exit 0 |
|
fi |
|
|
|
# Activate the pyenv environment |
|
verbose_print "Activating pyenv environment: $env_name" |
|
pyenv activate "$env_name" > /dev/null |
|
|
|
# Check if activation was successful |
|
if [ $? -ne 0 ]; then |
|
echo "Error: Failed to activate environment '$env_name'." |
|
exit 1 |
|
fi |
|
|
|
# Add environment to prompt |
|
add_to_prompt "$env_name" |
|
|
|
# Display info in verbose mode |
|
verbose_print "Successfully activated '$env_name'." |
|
verbose_print "Python version: $(python --version 2>&1)" |
|
verbose_print "Python executable: $(which python)" |
|
|
|
# Minimal feedback in non-verbose mode |
|
if [ $VERBOSE -eq 0 ]; then |
|
echo "Activated: $env_name" |
|
fi |
|
;; |
|
|
|
deactivate) |
|
# Check if an environment is activated |
|
if [ -z "$VIRTUAL_ENV" ]; then |
|
echo "No environment is currently activated." |
|
exit 0 |
|
fi |
|
|
|
# Get current environment name |
|
current_env=$(basename "$VIRTUAL_ENV") |
|
|
|
# Deactivate the current pyenv environment |
|
verbose_print "Deactivating current pyenv environment: $current_env" |
|
pyenv deactivate > /dev/null |
|
|
|
# Check if deactivation was successful |
|
if [ $? -ne 0 ]; then |
|
echo "Error: Failed to deactivate environment." |
|
exit 1 |
|
fi |
|
|
|
# Restore original prompt |
|
restore_prompt |
|
|
|
# Display success information in verbose mode |
|
verbose_print "Successfully deactivated pyenv environment." |
|
verbose_print "Python version: $(python --version 2>&1)" |
|
verbose_print "Python executable: $(which python)" |
|
|
|
# Minimal feedback in non-verbose mode |
|
if [ $VERBOSE -eq 0 ]; then |
|
echo "Deactivated: $current_env" |
|
fi |
|
;; |
|
|
|
list) |
|
echo "Available pyenv environments:" |
|
pyenv virtualenvs | sed 's/^ */ /' |
|
;; |
|
|
|
*) |
|
echo "Error: Unknown action '$action'." |
|
show_usage |
|
exit 1 |
|
;; |
|
esac |
|
|
|
exit 0 |
|
EOF |
|
|
|
# Make the script executable |
|
chmod +x "$INSTALL_DIR/bin/cursor-pyenv" |
|
|
|
# Create the aliases script |
|
echo -e "${BLUE}Creating aliases...${NC}" |
|
cat > "$INSTALL_DIR/cursor-aliases.sh" << 'EOF' |
|
#!/bin/bash |
|
|
|
# Add convenient aliases for cursor-pyenv |
|
alias cpyenv-activate="$HOME/.cursor-pyenv/bin/cursor-pyenv activate" |
|
alias cpyenv-deactivate="$HOME/.cursor-pyenv/bin/cursor-pyenv deactivate" |
|
alias cpyenv-list="$HOME/.cursor-pyenv/bin/cursor-pyenv list" |
|
|
|
# Let's also make an alias for verbose mode |
|
alias vcpyenv-activate="$HOME/.cursor-pyenv/bin/cursor-pyenv -v activate" |
|
alias vcpyenv-deactivate="$HOME/.cursor-pyenv/bin/cursor-pyenv -v deactivate" |
|
EOF |
|
|
|
# Make the aliases script executable |
|
chmod +x "$INSTALL_DIR/cursor-aliases.sh" |
|
|
|
# Create the prompt hook |
|
echo -e "${BLUE}Creating prompt hook...${NC}" |
|
cat > "$INSTALL_DIR/cursor-pyenv-prompt-hook" << 'EOF' |
|
# Cursor PyEnv prompt hook |
|
if [ -n "$VIRTUAL_ENV" ]; then |
|
# Get environment name from path |
|
env_name=$(basename "$VIRTUAL_ENV") |
|
# Only modify prompt if not already done |
|
if [[ "$PS1" != "($env_name) "* ]]; then |
|
# Backup original PS1 |
|
export CURSOR_PYENV_ORIGINAL_PS1="$PS1" |
|
# Add environment name to prompt |
|
export PS1="($env_name) $CURSOR_PYENV_ORIGINAL_PS1" |
|
fi |
|
fi |
|
EOF |
|
|
|
# Add to RC file if not already present |
|
echo -e "${BLUE}Updating shell configuration...${NC}" |
|
|
|
# Function to add a line to a file if it doesn't exist |
|
add_to_file() { |
|
local file="$1" |
|
local line="$2" |
|
|
|
if [ -f "$file" ] && ! grep -q "$line" "$file"; then |
|
echo "$line" >> "$file" |
|
return 0 |
|
fi |
|
return 1 |
|
} |
|
|
|
# Add PATH |
|
PATH_LINE='export PATH="$HOME/.cursor-pyenv/bin:$PATH"' |
|
add_to_file "$RC_FILE" "$PATH_LINE" |
|
|
|
# Add aliases |
|
ALIASES_LINE='source $HOME/.cursor-pyenv/cursor-aliases.sh' |
|
add_to_file "$RC_FILE" "$ALIASES_LINE" |
|
|
|
# Add prompt hook |
|
PROMPT_LINE='source $HOME/.cursor-pyenv/cursor-pyenv-prompt-hook' |
|
add_to_file "$RC_FILE" "$PROMPT_LINE" |
|
|
|
# Create README file |
|
echo -e "${BLUE}Creating documentation...${NC}" |
|
cat > "$INSTALL_DIR/README.md" << 'EOF' |
|
# Cursor PyEnv Wrapper |
|
|
|
This is a custom wrapper for pyenv to make it work properly within Cursor's terminal environment. |
|
|
|
## Usage |
|
|
|
There are two ways to use this tool: |
|
|
|
### 1. Using the cursor-pyenv script directly: |
|
|
|
```bash |
|
# Activate an environment (quiet mode) |
|
cursor-pyenv activate <environment_name> |
|
|
|
# Activate an environment with detailed output |
|
cursor-pyenv -v activate <environment_name> |
|
|
|
# Deactivate the current environment (quiet mode) |
|
cursor-pyenv deactivate |
|
|
|
# Deactivate with detailed output |
|
cursor-pyenv --verbose deactivate |
|
|
|
# List available environments |
|
cursor-pyenv list |
|
``` |
|
|
|
### 2. Using the convenient aliases: |
|
|
|
```bash |
|
# Activate an environment (quiet mode) |
|
cpyenv-activate <environment_name> |
|
|
|
# Activate an environment with detailed output |
|
cpyenv-activate -v <environment_name> |
|
|
|
# Deactivate the current environment (quiet mode) |
|
cpyenv-deactivate |
|
|
|
# Deactivate with detailed output |
|
cpyenv-deactivate --verbose |
|
|
|
# List available environments |
|
cpyenv-list |
|
``` |
|
|
|
## Features |
|
|
|
1. **Proper Cursor Terminal Integration**: Ensures pyenv works correctly in Cursor's terminal environment |
|
2. **Environment Prompt**: Displays the active environment in your shell prompt like: `(myenv) $` |
|
3. **Quiet/Verbose Mode**: Use `-v` or `--verbose` to see detailed information, or stay in quiet mode by default |
|
4. **Automatic Prompt Update**: Handles prompt changes when activating/deactivating environments |
|
|
|
## What this solves |
|
|
|
This script properly initializes pyenv and pyenv-virtualenv in Cursor's terminal before executing the commands, ensuring that virtual environments work correctly within Cursor. |
|
|
|
## Installation |
|
|
|
The script is installed at `$HOME/.cursor-pyenv/bin/cursor-pyenv` and the required path and aliases have been added to your shell configuration file. |
|
|
|
To apply these changes to your current terminal session, run: |
|
|
|
```bash |
|
source ~/.bashrc # If you're using Bash |
|
# OR |
|
source ~/.zshrc # If you're using Zsh |
|
``` |
|
|
|
For new terminal sessions in Cursor, these changes should be applied automatically. |
|
|
|
## Uninstallation |
|
|
|
To uninstall cursor-pyenv, run: |
|
|
|
```bash |
|
rm -rf $HOME/.cursor-pyenv |
|
``` |
|
|
|
Then edit your shell configuration file and remove the following lines: |
|
```bash |
|
export PATH="$HOME/.cursor-pyenv/bin:$PATH" |
|
source $HOME/.cursor-pyenv/cursor-aliases.sh |
|
source $HOME/.cursor-pyenv/cursor-pyenv-prompt-hook |
|
``` |
|
EOF |
|
|
|
# Done! |
|
echo -e "${GREEN}Installation complete!${NC}" |
|
echo -e "cursor-pyenv has been installed to ${BLUE}$INSTALL_DIR${NC}" |
|
echo -e "Usage documentation is available at ${BLUE}$INSTALL_DIR/README.md${NC}" |
|
echo |
|
echo -e "${YELLOW}To start using cursor-pyenv in your current session, run:${NC}" |
|
echo -e "${GREEN}source $RC_FILE${NC}" |
|
echo |
|
echo -e "${BLUE}Example Usage:${NC}" |
|
echo -e " ${GREEN}cpyenv-list${NC} # List environments" |
|
echo -e " ${GREEN}cpyenv-activate myenv${NC} # Activate environment" |
|
echo -e " ${GREEN}cpyenv-deactivate${NC} # Deactivate environment" |
|
echo |